如何从 C 中的文件(尤其是可执行文件)中提取机器代码

逆向工程 C 可执行 可执行程序 机器码
2021-06-13 11:10:39

如何在 C 中获取文件(主要是可执行文件)的机器代码?我编写了一个 C 程序来将机器代码转换为汇编。但是如何获取文件的机器码呢?我将如何编写 ac 程序以将文件转换为机器代码?

3个回答

您可以使用Capstone- engine 之类的引擎制作一个解释机器代码的程序,这是最简单的方法,可以轻松地以优化的方式为您提供良好的结果,请记住,这不是一件容易的事,它很重要最好使用现成的工具,我们有许多免费且非常好的选择,并且像Ghidra一样不断更新,但是如果您仍然想自己编写享受并阅读手册IA-32 Intel 手册

很难理解你想要什么

如何在 C 中获取文件(主要是可执行文件)的机器代码?

所以你想要一个 C 程序来加载一个可执行文件(例如 dos、windows、linux 可执行文件)并显示整个或部分图像(通常包含机器代码和数据)?

所以有几种文档化的文件格式可以包含机器代码

例如,请参阅 IDA 支持的文件类型:https : //www.hex-rays.com/products/ida/file_formats/

我编写了一个 C 程序来将机器代码转换为汇编。

所以你已经有了某种反汇编程序?

但是如何获取文件的机器码呢?

阅读您的操作系统文件格式的规范并编写一个小的加载器/解析器,有几个 C、C++、go、python ...... github/google 上的示例......

我将如何编写 ac 程序以将文件转换为机器代码?

现在你完全恢复了你的问题 - 之前 - 你问如何用机器代码加载文件,现在你问如何将“文件”转换为机器代码

在您的示例中,“文件”是什么格式 - 某种源代码或目标文件格式?

通常是这样:C/C++/Assembler/whatever-Source --> Compiler --> Objectfiles --> OS-related-Executable-Format[Machine-Code+Data]

试着问得更精确——当你清楚你的确切目标是什么时,它很容易帮助你

from binascii import *
from pefile import *
from capstone import *

if(sys.argv[1]):
    pe      = PE(sys.argv[1])
    entry   = pe.OPTIONAL_HEADER.AddressOfEntryPoint
    base    = pe.OPTIONAL_HEADER.ImageBase
    OEP = base+entry
    bytes   = pe.get_data(entry,17)
    print(hexlify(bytes))
    for i in (Cs(CS_ARCH_X86,CS_MODE_64).disasm(bytes,OEP)):
        print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
    

结果和确认

:\>python getbytatent.py c:\Windows\System32\calc.exe
b'e84bfdffff6a5868e82e0101e8eb99ffff'
0x1012d6c:      call    0x1012abc
0x1012d71:      push    0x58
0x1012d73:      push    0x1012ee8
0x1012d78:      call    0x100c768

:\>cdb -c "u @$exentry l4;q" c:\Windows\System32\calc.exe | awk "/Reading/,/quit/"
0:000> cdb: Reading initial command 'u @$exentry l4;q'
calc!WinMainCRTStartup:
00a92d6c e84bfdffff      call    calc!__security_init_cookie (00a92abc)
00a92d71 6a58            push    58h
00a92d73 68e82ea900      push    offset calc!_CT??_R0?AV_com_error+0xdc (00a92ee8)
00a92d78 e8eb99ffff      call    calc!_SEH_prolog4 (00a8c768)
quit:

我讨厌在评论之后把它放在这里 BY OP 将
它转换为 winapi 需要不到一分钟的时间
(我应该声明 winapi 不是 c )
并且纯 c 没有定义 PE 格式结构,
显然可以执行 fopen() ,fseek(),fread() 但那是徒劳无功的

:\>type mcc.cpp
#include <windows.h>
#include <dbghelp.h>
#include <stdio.h>
int main (int argc ,char * argv[]) {
    if(argc == 2) {
        HMODULE hMod = LoadLibraryA(argv[1]);
        if(hMod){
            DWORD AEP = ((PIMAGE_NT_HEADERS32)ImageNtHeader(hMod))->OptionalHeader.AddressOfEntryPoint;
            DWORD OEP = (DWORD)hMod + AEP;
            for (int i =0; i< 17 ; i++) {
                printf("%02x ",*(BYTE *)(OEP+i));
            }
        }
    }
}
:\>cl /Zi /W4 /analyze /Od mcc.cpp /nologo /link /release dbghelp.lib
mcc.cpp


:\>mcc.exe c:\Windows\System32\calc.exe
e8 4b fd ff ff 6a 58 68 e8 2e 82 00 e8 eb 99 ff ff
:\>

并且只是为了完成这个圈子 ,针对特定操作系统中
的特定应用程序
进行脆弱的非生产性 c hack
具有特定的 dos、nt 头、
.code 部分中的 aep 从
0x200 的0x400文件对齐和 0x1000 的页面对齐开始

:\>type futilemcc.cpp
//assume = ass u and me a beyond compare exercise in futility
#include <stdio.h>
int main (int argc ,char *argv[] ){
    if(argc ==2){
        FILE *fp = NULL;
        unsigned long nth = NULL;
        unsigned char mcc[17] ={0};
        errno_t err= fopen_s(&fp,argv[1],"rb");
        if(err == 0 && fp != NULL) {
            if ( fseek(fp,0x3c,SEEK_SET) == 0) {
                fread_s(&nth,sizeof(unsigned long),sizeof(unsigned long),1,fp);
                if ( fseek(fp,nth+0x28,SEEK_SET) == 0) {
                    fread_s(&nth,sizeof(unsigned long),sizeof(unsigned long),1,fp);
                    if ( fseek(fp,nth-(0x1000-0x400),SEEK_SET) == 0) {
                        fread_s(&mcc,sizeof(mcc),sizeof(unsigned char),sizeof(mcc),fp);
                        for(int i =0;i<17;i++){
                            printf("%02x ",mcc[i]);
                        }
                    }
                }
            }
        }
    }
}
:\>complink.bat futilemcc

:\>cl /Zi /W4 /analyze /nologo /Od /EHsc futilemcc.cpp /link /release
futilemcc.cpp

:\>futilemcc.exe c:\Windows\System32\calc.exe
e8 4b fd ff ff 6a 58 68 e8 2e 01 01 e8 eb 99 ff ff
:\>