我有一个shellcode。它会在我的缓冲区溢出程序中打开计算器。
0: eb 16 jmp 0x18
2: 5b pop ebx
3: 31 c0 xor eax,eax
5: 50 push eax
6: 53 push ebx
7: bb 4d 11 86 7c mov ebx,0x7c86114d
c: ff d3 call ebx
e: 31 c0 xor eax,eax
10: 50 push eax
11: bb ea cd 81 7c mov ebx,0x7c81cdea
16: ff d3 call ebx
18: e8 e5 ff ff ff call 0x2
1d: 63 61 6c arpl WORD PTR [ecx+0x6c],sp
20: 63 2e arpl WORD PTR [esi],bp
22: 65 78 65 gs js 0x8a
25: 00 90 90 90 90 90 add BYTE PTR [eax-0x6f6f6f70],dl
2b: 90 nop
2c: 90 nop
2d: 90 nop
2e: 90 nop
2f: 90 nop
除了主要问题是“此shellcode逐行执行什么操作”外,我特别感兴趣:
答案 0 :(得分:6)
jmp 0x18
是相对于偏移量0x18的相对跳转,偏移量实际上是代码的结尾。然后,它调用地址0x2(再次相对)。该调用将“返回地址”放置在堆栈上,因此可以将其从堆栈中弹出,从而为您提供了执行此相对shellcode的地址的线索。实际上,偏移量为0x2的pop ebx
正在从堆栈中获取地址。
我说0x18是代码的结尾,因为它后面的行是数据字节,而不是asm操作码。这就是为什么您看到arpl
的原因。如果查看字节的十六进制值,则会看到:
calc.exe\0 ==> 0x63 0x61 0x63 0x6c 0x2e 0x65 0x78 0x65 0x00
已编辑:
shellcode的完整流程为:
jmp 0x18
-跳至shellcode的最后一条代码指令call 0x2
-返回偏移量2,并将偏移量0x1D的地址存储在堆栈中pop ebx
-ebx:=堆栈中的地址,它是字符串“ calc.exe”的地址xor eax,eax
-通用操作码将寄存器清零:eax:= 0 push eax
-将值0推送为将来的函数调用的第二个参数push ebx
-将指针推到“ calc.exe”作为将来函数调用的第一个参数mov ebx,0x7c86114d
-ebx是固定地址(可能是WinExec)call ebx
-调用函数:WinExec(“ calc.exe”,0)xor eax,eax
-再次,eax:= 0 push eax
-将值0推送为将来的函数调用的第一个参数mov ebx,0x7c81cdea
-ebx是固定地址(可能会退出)call ebx
-调用函数:exit(0)