有人可以为上面的c程序编写汇编代码,转换成小于100字节的机器代码吗?

时间:2012-05-16 13:58:29

标签: c assembly dump machine-code

我想溢出数组buffer[100],我将在FreeBSD上的bash shell上传递python脚本。我需要机器代码作为字符串传递以溢出缓冲区buffer[100]并使程序将其主机名打印到stdout

以下是我尝试过的C中的代码,并在控制台上提供了主机名。 :

#include <stdio.h>
int main()
{
   char buff[256];
   gethostname(buff, sizeof(buff));
   printf(""%s", buff);

  return 0;

}


这是汇编中的代码,我使用gcc但是比我需要的时间长,当我查找c程序的文本部分的机器代码时,它超过100个字节,我需要一个机器代码上面的c程序小于100个字节。


     .type   main, @function
main:
pushl %ebp; saving the base pointer
    movl %esp, %ebp; Taking a snapshot of the stack pointer
subl $264, %esp; 
addl $-8, %esp
pushl $256
leal -256(%ebp), %eax
pushl %eax
call gethostname
addl $16, %esp
addl $-8, %esp
leal -256(%ebp), %eax
pushl %eax
pushl $.LCO
call printf
addl $16, %esp
xorl %eax, %eax
jmp .L6
.p2align 2, 0x90
.L6:
leave
ret
.Lfe1:
.size   main, .Lfe1-main
.ident "GCC: (GNU) c 2.95.4 20020320 [FreeBSD]"

一个人已经在另一台计算机上完成了它并且他给了我现成的37字节的机器代码,并且他使用perl脚本以下面的格式将它传递给缓冲区。我尝试了他的代码并且它有效,但他没有告诉我该怎么做。

“\ X41 \ XC1 \ X30 \ X58 \ x6e \ X61 \ X6D \ X65 \ X23 \ X23 \ XC3 \ XBC \ XA3 \ X83 \ XF4 \ X69 \ X36 \ xw3 \ XDE \ x4f \ X2F \ X5F \ X2F \ X39 \ X33 \ X60 \ X24 \ X32 \ XB4 \ XAB \ X21 \ XC1 \ X80 \ X24 \ xe0 \ XDB \ XD0”

我知道他是在一台不同的机器上做的,所以我不能得到相同的代码,但因为我们都使用完全相同的c函数,所以机器代码的大小应该几乎相同,如果不完全相同的话。他的机器代码是37个字节,他将在shell上传递以溢出FreeBSD 2.95上的二进制文件中的gets()函数,以在stdout上打印主机名。我想做同样的事情,我已经尝试过他的机器代码并且它有效,但他不会告诉我他是如何得到这个机器代码的。所以我实际上关心的是获取该代码的过程。

好的我尝试了这里的帖子中建议的方法,但只是为了函数gethostname()我得到了130个字符的机器码。它不包含printf()机器代码。因为我需要将主机名打印到控制台,所以也应该包含它,但这会使机器代码更长。我必须将代码放在一个100字节的数组中,因此代码应小于100字节。

有人可以为上面的c程序编写汇编代码,转换成小于100字节的机器代码吗?

4 个答案:

答案 0 :(得分:3)

要获取机器代码,您需要编译程序然后反汇编。例如,使用gcc执行以下操作:

gcc -o hello hello.c
objdump -D hello

转储将显示以字节为单位的机器代码以及该机器代码的反汇编。

一个简单的例子,相关的,您必须了解目标文件和可执行文件之间的区别,但这仍然应该证明我的意思:

unsigned int myfun ( unsigned int x )
{
    return(x+5);
}

gcc -O2 -c -o hello.o hello.c
objdump -D hello.o


Disassembly of section .text:

00000000 <myfun>:
   0:   e2800005    add r0, r0, #5
   4:   e12fff1e    bx  lr

答案 1 :(得分:2)

FreeBSD是一个操作系统,而不是编译器或汇编程序。

您希望汇编汇编源代码到机器代码中,因此您应该使用汇编程序。

你通常可以使用GCC,因为它足够聪明,知道对于以.s结尾的文件名,它应该运行汇编程序。

如果您已在目标文件中包含代码,则可以使用objdump读取文件的代码段。

答案 2 :(得分:1)

发布的37个字节完全是垃圾。

如果在任何版本的Windows(Windows 2000或更高版本)下运行,我相信,那 “outsb”和“insd”指令(在用户程序中)会导致错误, 因为不允许用户程序直接执行port -level I / O.

由于机器代码不会以“真空”结束,我在发布的代码后添加了一些\ x90 -bytes(再次为NOP)。这只会影响最后一个rcl -instruction的参数(在给定的代码中过早地结束;例如,发布的代码不仅是垃圾,而且还过早结束)。

但是,微处理器没有自己的智能,所以他们会(尝试)执行你提供的任何垃圾代码。并且,代码以“inc ecx”开头,这是一个愚蠢的举动,因为我们不知道ecx之前有什么价值。另外“shl dword ptr [eax],58美元”是一个“好” 随机破坏内存的方法(因为eax也是未知的值)。

并且,其中一个甚至不是有效字节(应该表示为两个十六进制数字)。

无效的“字节”是\ xw3。

我将该无效字节替换为\ x90(NOP,如果它在指令开始时),并得到:

00451B51 41 inc ecx 00451B52 C13058 shl dword ptr [eax],$58 00451B55 6E outsb 00451B56 61 popad 00451B57 6D insd 00451B58 652323 and esp,gs:[ebx] 00451B5B C3 ret

// code below is NEVER executed, since the line above does a RET.

00451B5C BCA383F469 mov esp,$69f483a3 00451B61 3690 nop // 36, w3 ???? 00451B63 DE4F2F fimul word ptr [edi+$2f] 00451B66 5F pop edi 00451B67 2F das 00451B68 3933 cmp [ebx],esi 00451B6A 60 pushad 00451B6B 2432 and al,$32 00451B6D B4AB mov ah,$ab 00451B6F 21C1 and ecx,eax 00451B71 8024E0DB and byte ptr [eax],$db 00451B75 D09090909090 rcl [eax-$6f6f6f70],1

答案 3 :(得分:0)

使用objdump -s -j .text得到目标文件的文本部分的一个很好的hexdump。

编辑了更多细节: 您需要找出目标代码中函数的地址。这是objdump -t的用途。在这种情况下,我在程序“hello”中寻找函数main

> objdump -t hello|grep main

> 0000000000400410 g     F .text  000000000000002f        main

现在我使用objdump -s -j .text hello创建一个hexdump:

400410 4881ec08 010000be 00010000 31c04889  H...........1.H.
400420 e7e8daff ffff4889 e6bff405 400031c0  ......H.....@.1.
400430 e8abffff ff31c048 81c40801 0000c390  .....1.H........
400440 31ed4989 d15e4889 e24883e4 f0505449  1.I..^H..H...PTI
400450 c7c0e005 400048c7 c1500540 0048c7c7  ....@.H..P.@.H..
...

第一行是地址。它以400410开头,即main函数的地址,但情况可能并非总是如此。以下4行是十六进制的16字节机器码,最后一行是ASCII中相同的16字节机器码。因为很多字节在ASCII中没有表示,所以有很多点。您需要使用4个十六进制列:\x48 \x81 \xec... 我在linux系统上做过这个,但是对于FreeBSD你可以完全一样 - 只有生成的machindecode才会有所不同。