在shellcode中正确地组装字符串

时间:2017-09-06 19:48:23

标签: x86 disassembly shellcode

我正在学习shellcode。

我在教程中找到了这个shellcode:

python -c 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 "' > shellcode

我想要做的是反汇编这个非常基本的shellcode,以了解它是如何工作的。

这就是我所做的:

$ objdump -D -b binary -m i8086 shellcode 

shellcode:     file format binary


Disassembly of section .data:

00000000 <.data>:
   0:   90                      nop
   1:   90                      nop
   2:   90                      nop
   3:   90                      nop
   4:   90                      nop
   5:   90                      nop
   6:   90                      nop
   7:   90                      nop
   8:   90                      nop
   9:   31 c0                   xor    %ax,%ax
   b:   50                      push   %ax
   c:   68 2f 2f                push   $0x2f2f
   f:   73 68                   jae    0x79
  11:   68 2f 62                push   $0x622f
  14:   69 6e 89 e3 50          imul   $0x50e3,-0x77(%bp),%bp
  19:   53                      push   %bx
  1a:   89 e1                   mov    %sp,%cx
  1c:   b0 0b                   mov    $0xb,%al
  1e:   cd 80                   int    $0x80

或者:

$ ndisasm shellcode 
00000000  90                nop
00000001  90                nop
00000002  90                nop
00000003  90                nop
00000004  90                nop
00000005  90                nop
00000006  90                nop
00000007  90                nop
00000008  90                nop
00000009  31C0              xor ax,ax
0000000B  50                push ax
0000000C  682F2F            push word 0x2f2f
0000000F  7368              jnc 0x79
00000011  682F62            push word 0x622f
00000014  696E89E350        imul bp,[bp-0x77],word 0x50e3
00000019  53                push bx
0000001A  89E1              mov cx,sp
0000001C  B00B              mov al,0xb
0000001E  CD80              int 0x80

此shellcode包含被解释为x86指令的字符串。 有没有办法在跳跃上放置适当的标签?

有没有办法显示字符串而不是解码字符串上的x86指令。我知道这并不容易,因为没有带有章节和标题的精灵......

2 个答案:

答案 0 :(得分:0)

这是冯·诺依曼架构的结果。代码和数据只是计算机内存中的数字。因此,反汇编程序无法知道(没有关于字节序列的任何先验信息)什么是代码以及什么是数据。意思是,你必须手动完成。

幸运的是,这很容易做到。只需用nop(\ x90)替换字符串数据,然后再次对其进行反汇编。然后,您可以通过替换nop区域将字符串数据放回源代码中。

还要确保使用正确的目标CPU进行反汇编。我认为这个shellcode不太可能适用于16位8086 CPU。

答案 1 :(得分:0)

如果你有使用calljmp来跳过某些数据的shellcode,那么如果反汇编程序在将数据视为同步时失去同步,则必须用NOP替换字符串说明,正如@DavidJ建议的那样。

在这种情况下,您只是以错误的模式进行反汇编。  jnc显然是假的(我认为你意识到)。

反汇编程序将push opcode0x68字节)视为push imm16的开头,因为这是16位模式的工作原理。但在32位和64位模式下,相同的操作码是push imm32的开头。因此push指令实际上是5个字节而不是3个,而下一个指令实际上是下一个push

伪造短 - jnc是一个巨大的暗示,这是不是 16位代码。

使用ndisasm -b32-b64 Ndisasm可以读取stdin的输入,因此我使用了python2 -c 'print "... "' | ndisasm - -b32

使用objdump时,如果您更喜欢英特尔语法,请使用objdump -d -Mintel。所以你可以 objdump -Mintel -bbinary -D -mi386 /tmp/shellcode 32位(-mi386选择x86作为架构(而不是ARM或MIPS或其他),并暗示-Mi386 32位模式也是如此)。

或者对于64位,objdump -D -b binary -mi386 -Mx86-64 /tmp/shellcode有效。 (objdump无法从stdin中读取二进制文件:/)有关objdump选项的更多信息,请查看-M手册页。

我在~/.bashrcalias disas='objdump -drwC -Mintel'中使用此别名,因为我通常反汇编ELF可执行文件/对象以查看编译器执行的操作,而不是shellcode。你的别名可能需要-D

我非常确定这是32位代码,因为在64位模式下,两次推送会留下空隙。不是push imm64,但push imm32是64位推送,立即符号扩展为64位。在64位模式下,您可以使用

push  'abcd'
mov   [rsp+4], 'efgh'

以rsp指向"abcdefgh"结束。

此外,使用带有堆栈地址的int 0x80是一个很大的线索,这不是64位代码。 int 0x80在64位模式下适用于Linux,但它会将所有输入截断为32位:What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?

ndisasm的32位反汇编是:

00000000  90                nop
00000001  90                nop
00000002  90                nop
00000003  90                nop
00000004  90                nop
00000005  90                nop
00000006  90                nop
00000007  90                nop
00000008  90                nop
00000009  31C0              xor eax,eax
0000000B  50                push eax
0000000C  682F2F7368        push dword 0x68732f2f
00000011  682F62696E        push dword 0x6e69622f
00000016  89E3              mov ebx,esp
00000018  50                push eax
00000019  53                push ebx
0000001A  89E1              mov ecx,esp
0000001C  B00B              mov al,0xb
0000001E  CD80              int 0x80
00000020  200A              and [edx],cl

看起来很健全。它不包含分支,但

  

有没有办法在跳跃上放置适当的标签?

是的,Agner Fog的objconv反汇编程序可以在分支目标上放置标签,以帮助您确定哪个分支在哪里。  见How do I disassemble raw x86 code?