如何在 C 中获取文件(主要是可执行文件)的机器代码?我编写了一个 C 程序来将机器代码转换为汇编。但是如何获取文件的机器码呢?我将如何编写 ac 程序以将文件转换为机器代码?
如何从 C 中的文件(尤其是可执行文件)中提取机器代码
您可以使用Capstone- engine 之类的引擎制作一个解释机器代码的程序,这是最简单的方法,可以轻松地以优化的方式为您提供良好的结果,请记住,这不是一件容易的事,它很重要最好使用现成的工具,我们有许多免费且非常好的选择,并且像Ghidra一样不断更新,但是如果您仍然想自己编写享受并阅读手册IA-32 Intel 手册。
很难理解你想要什么
如何在 C 中获取文件(主要是可执行文件)的机器代码?
所以你想要一个 C 程序来加载一个可执行文件(例如 dos、windows、linux 可执行文件)并显示整个或部分图像(通常包含机器代码和数据)?
所以有几种文档化的文件格式可以包含机器代码
- dos exe(旧版 exe 格式:https : //en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files)
- windows exe(pe 格式:https : //en.wikipedia.org/wiki/Portable_Executable)
- linux(精灵格式:https : //de.wikipedia.org/wiki/Executable_and_Linking_Format),
- 动态库
- 来自多个编译器的 omf、coff 格式的目标文件
- 没有记录布局的纯/专有二进制文件
例如,请参阅 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
:\>