如何获取C程序的操作码

12

我知道如何使用gdb获取我的程序的汇编代码,但是我该如何获取操作码? 我需要它来黑掉一个Linux服务器(不用担心,这是我正在上课时的一部分,没有真正的服务器会受到影响)。实际上,我正在阅读 这篇文章,我想知道如何从汇编代码中获取操作码:

[aleph1]$ gcc -o shellcodeasm -g -ggdb shellcodeasm.c
[aleph1]$ gdb shellcodeasm

(gdb) disassemble main
Dump of assembler code for function main:
0x8000130 <main>:       pushl  %ebp
0x8000131 <main+1>:     movl   %esp,%ebp
0x8000133 <main+3>:     jmp    0x800015f <main+47>
0x8000135 <main+5>:     popl   %esi
0x8000136 <main+6>:     movl   %esi,0x8(%esi)
0x8000139 <main+9>:     movb   $0x0,0x7(%esi)
0x800013d <main+13>:    movl   $0x0,0xc(%esi)
0x8000144 <main+20>:    movl   $0xb,%eax
0x8000149 <main+25>:    movl   %esi,%ebx
0x800014b <main+27>:    leal   0x8(%esi),%ecx
0x800014e <main+30>:    leal   0xc(%esi),%edx
0x8000151 <main+33>:    int    $0x80
0x8000153 <main+35>:    movl   $0x1,%eax
0x8000158 <main+40>:    movl   $0x0,%ebx
0x800015d <main+45>:    int    $0x80
0x800015f <main+47>:    call   0x8000135 <main+5>
0x8000164 <main+52>:    das
0x8000165 <main+53>:    boundl 0x6e(%ecx),%ebp
0x8000168 <main+56>:    das
0x8000169 <main+57>:    jae    0x80001d3 <__new_exitfn+55>
0x800016b <main+59>:    addb   %cl,0x55c35dec(%ecx)
End of assembler dump.

以下内容:

testsc.c
------------------------------------------------------------------------------
char shellcode[] =
    "\xeb\x2a\x5e\x89\x76\x08\xc6\x46\x07\x00\xc7\x46\x0c\x00\x00\x00"
    "\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80"
    "\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xe8\xd1\xff\xff"
    "\xff\x2f\x62\x69\x6e\x2f\x73\x68\x00\x89\xec\x5d\xc3";

我的系统是Linux x86,我将使用C语言。我希望有一种自动化的方法,但手动解决方案也可以。

我的意思是,如何将%ebp、%esi、%esp等转换?有没有可以使用的映射表或自动化程序?


你正在寻找一个 x86 反汇编器吗? - David Pointer
我认为反汇编器做的是与我尝试做的相反的事情。 - George Panic
x86指令集清单具有映射,可以用于反汇编0xEB(即JMP),也可以反之(汇编或“编译”JMP为0xEB)。 - tripleee
你知道我可以在哪里找到它吗? - George Panic
还有,我该怎么把“<main+47>”转换成操作码呢? - George Panic
任何良好的指令集概述都会解释各种寻址模式等内容。但如果您只关心最终结果,那么您只需要一个汇编器。我相信gas已经包含在GCC套件中了。 - tripleee
4个回答

12

好的,这是:

Disassembly of section .data:

00000000 <shellcode>:
   0:       eb 2a                   jmp    2c <shellcode+0x2c>
   2:       5e                      pop    %esi
   3:       89 76 08                mov    %esi,0x8(%esi)
   6:       c6 46 07 00             movb   $0x0,0x7(%esi)
   a:       c7 46 0c 00 00 00 00    movl   $0x0,0xc(%esi)
  11:       b8 0b 00 00 00          mov    $0xb,%eax
  16:       89 f3                   mov    %esi,%ebx
  18:       8d 4e 08                lea    0x8(%esi),%ecx
  1b:       8d 56 0c                lea    0xc(%esi),%edx
  1e:       cd 80                   int    $0x80
  20:       b8 01 00 00 00          mov    $0x1,%eax
  25:       bb 00 00 00 00          mov    $0x0,%ebx
  2a:       cd 80                   int    $0x80
  2c:       e8 d1 ff ff ff          call   2 <shellcode+0x2>
  31:       2f                      das
  32:       62 69 6e                bound  %ebp,0x6e(%ecx)
  35:       2f                      das
  36:       73 68                   jae    a0 <shellcode+0xa0>
  38:       00 89 ec 5d c3 00       add    %cl,0xc35dec(%ecx)

注意在add %cl指令中的最后两个零是来自于字符串的空终止符,而非显式写出来的。

我得到这个结论的方法是,我只是用编译器编译了你的声明:

gcc testsc.c -c

然后

objdump -D testsc.o

可能是这样,但答案是一样的。你可以使用objdump来反汇编shellcodeasm程序,而不是在gcc内部进行操作。正如你所看到的,输出格式为您提供了反汇编列表操作码。您可以进行一些文本处理,剪切字节列并自动将其转换为C声明。 - Kaz

6

您可以使用:

gcc -S -c tst.c -o -

或者

gcc -g -ggdb -c tst.c
objdump -S tst.o

获取程序opcode的反汇编。

要获取字符数组的反汇编,您可以使用以下方法:

gcc -c tst.c
objdump -D -j .data tst.o

你确定吗?objdump默认不会反汇编数据段,gcc也不会将任意文字字符串转换为操作码。 - zvrba
@zvrba 更新了我的答案,我一开始没有注意到他想要数组字节的反汇编。 - ouah
如果objdump默认不会反汇编数据部分,那么我是如何生成答案的? - Kaz
@Kaz -S 只会反汇编.text,但 -D 会反汇编其他部分。 - ouah
1
GNU binutils中的objdump默认不会反汇编任何部分。实际上,默认情况下,它会打印一个帮助屏幕。 - Kaz
在Linux 2.6.32-5和gcc 4.7.1上,gcc -c tst.c && objdump -S tst.o 对我很有用。但是,在我的系统上,如果只执行 gcc -S -c tst.c -o - 而不进行 objdump 步骤,则只会产生汇编助记符,而不是操作码。 - Morten Jensen

4

找到了!首先进行反汇编,然后键入:x/bx,按回车键,逐个获取汇编命令的十六进制表示!


1
你可以使用x /100bx start_address一次性完成所有操作。这将给出从start_address开始的下一个100个字节的十六进制表示。将100更改为您反汇编代码跨越的字节数。 - Anonymous

0
创建一个小的汇编文件,比如code.s。然后在里面放入以下内容:
.text
.byte 0xeb, 0x2a, 0x5e, ..

使用as code.s -o code.o进行汇编,并使用objdump反汇编结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接