[英]Convert assembly to machine code in C++
我尋找任何lib或函數將一串匯編代碼轉換為機器代碼,如下所示:
char asmString[] = {"mov eax,13H"};
byte[] output; // array of byte
output = asm2mach(asmString); // {0xB8, 0x13, 0x00, 0x00, 0x00}
動機是注入機器代碼來調用程序中的asm函數。 這個注入主要有3個步驟:VirtualAllocEx,WriteProcessMemory和CreateRemoteThread。 這是代碼:
bool injectAsm(const char* exeName,const byte* code, int size)
{
LPVOID allocAddr = NULL;
HANDLE ThreadProcess = NULL;
HANDLE hProcess = OpenProcessEasy(exeName);
allocAddr = VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT, PAGE_READWRITE);
if(allocAddr){
if(WriteProcessMemory(hProcess, allocAddr, code, size, NULL)) {
ThreadProcess = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)allocAddr, NULL, 0, NULL);
WaitForSingleObject(ThreadProcess, INFINITE);
VirtualFreeEx(hProcess,allocAddr, 0, MEM_RELEASE);
CloseHandle(ThreadProcess);
return true;
}
}
if(allocAddr){
VirtualFreeEx(hProcess, allocAddr, 0, MEM_RELEASE);
}
return false;
}
int main()
{
byte code[] = {0xB8, 0x10, 0xED, 0x4A, 0x00, 0xFF, 0xD0, 0xC3, 0x90};
injectAsm("game.exe",code,sizeof(code));
system("pause");
return 0;
}
你應該定義你真正想要的東西:
您想在運行時生成機器代碼嗎? 然后使用一些JIT編譯庫,如libgccjit , libjit , LLVM , GNU lightning或asmjit 。 asmjit
是一個發出x86機器代碼的庫,可能就是你需要的。 絕對不需要使用包含匯編代碼的字符串 。
或者您是否想要將一些匯編語法(甚至對於x86有幾種匯編語法)轉換為對象代碼或機器代碼? 那么你最好將一個真正的匯編程序作為外部程序運行。 生成的目標代碼將包含重定位指令,您需要處理這些指令(例如鏈接器 )。
或者,您應該考慮在運行時生成一些(例如)C代碼,然后分支編譯,並在運行時動態加載和使用結果函數(例如使用dlopen(3)和dlsym
)。 看到這個
詳細信息顯然是操作系統, ABI和處理器特定的。
我建議同時使用AsmJit和AsmTK 。 AsmTK是一個新項目,它使用AsmJit作為工具包,並在其上添加了額外的功能。 注意,目前AsmTK需要asmjit:下一個分支工作,因為這是一個新功能。
這是使用AsmTK解析某些asm的最小示例:
#include <stdio.h>
#include <stdlib.h>
#include <asmtk/asmtk.h>
using namespace asmjit;
using namespace asmtk;
static const char someAsm[] =
"test eax, eax\n"
"jz L1\n"
"mov eax, ebx\n"
"mov eax, 0xFFFFFFFF\n"
"pand mm0, mm1\n"
"paddw xmm0, xmm1\n"
"vpaddw ymm0, ymm1, ymm7\n"
"vaddpd zmm0 {k1}{z}, zmm1, [rax] {1tox}\n"
"L1:\n";
int main(int argc, char* argv[]) {
CodeHolder code;
// Here select the target architecture - either X86 or X64.
code.init(CodeInfo(Arch::kTypeX64));
X86Assembler a(&code);
AsmParser p(&a);
Error err = p.parse(someAsm);
if (err) {
printf("ERROR: %0.8x (%s)\n", err, DebugUtils::errorAsString(err));
return 1;
}
// The machine-code is now stored in CodeHolder's first section:
code.sync();
CodeBuffer& buffer = code.getSection(0)->buffer;
// You can do whatever you need with the buffer:
uint8_t* data = buffer.data;
size_t length = buffer.length;
return 0;
}
AsmJit使用JitRuntime來分配可執行內存並將生成的機器代碼重新定位到其中。 但是,AsmJit的虛擬內存分配器可以使用hProcess
創建,它可以是您的遠程進程句柄,因此它也可以分配該進程的內存。 這是一個如何完成的小例子:
bool addToRemote(HPROCESS hRemoteProcess, CodeHolder& code) {
// VMemMgr is AsmJit's low-level VM manager.
VMemMgr vm(hRemoteProcess);
// This will tell `vm` to not destroy allocated blocks when it
// gets destroyed.
vm.setKeepVirtualMemory(true);
// Okay, suppose we have the CodeHolder from previous example.
size_t codeSize = code.getCodeSize();
// Allocate a permanent memory of `hRemoteProcess`.
uint64_t remoteAddr = (uint64_t)
vm.alloc(codeSize, VMemMgr::kAllocPermanent);
// Temporary buffer for relocation.
uint8_t* tmp = ::malloc(code.getCodeSize());
if (!tmp) return false;
// First argument is where to relocate the code (it must be
// current's process memory), second argument is the base
// address of the relocated code - it's the remote process's
// memory. We need `tmp` as it will temporarily hold code
// that we want to write to the remote process.
code.relocate(tmp, remoteAddr);
// Now write to the remote process.
SIZE_T bytesWritten;
BOOL ok = WriteProcessMemory(
hRemoteProcess, (LPVOID)remoteMem, tmp, codeSize, &bytesWritten);
// Release temporary resources.
::free(tmp);
// Now the only thing needed is the CreateRemoteThread thingy...
return ok;
}
我建議將這些功能包裝到一個新的RemoteRuntime中,以使其成為單個函數調用的問題,如果需要,我可以提供幫助。
這是一個可以將一串匯編代碼(Intel或ARM)轉換為相應字節的項目。
https://github.com/bsmt/Assembler
它是用Objective-C編寫的,但源代碼就在那里。 我希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.