【问题标题】:diassemble strings properly in shellcode在 shellcode 中正确反汇编字符串
【发布时间】:2017-09-06 19:48:22
【问题描述】:

我正在学习 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 指令。我知道这并不容易,因为没有带有节和标题的精灵......

【问题讨论】:

  • 嗯,这确实是stackoverflow.com/questions/1737095/… 的复制品,其中提到了不同的模式(例如in this answer。)但我想我们可以将这个问题看作是关于如何在您反汇编时实现在错误的模式下......(虽然也有可能是重复的:/)

标签: x86 disassembly shellcode


【解决方案1】:

如果您有使用calljmp 跳过某些数据的shellcode,如果反汇编程序在将数据视为指令时不同步,您必须用NOP 替换字符串,正如@DavidJ 建议的那样.

在这种情况下,你只是在错误的模式下反汇编jnc 显然是假的(我想你已经意识到了)。

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

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


使用ndisasm -b32-b64 Ndisasm可以从stdin读取输入,所以我使用python2 -c 'print "... "' | ndisasm - -b32

使用objdump 时,如果您更喜欢Intel 语法,请使用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 选项的更多信息。

我在~/.bashrc:alias 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?

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多