【问题标题】:Convert assembly to machine code in C++在 C++ 中将程序集转换为机器代码
【发布时间】:2014-10-04 06:57:10
【问题描述】:

我寻找任何库或函数来将一串汇编代码转换为机器代码, 像下面这样:

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;
} 

【问题讨论】:

  • 我没有功能但是..如果您使用套接字向该站点发送请求,我猜它可以工作:defuse.ca/online-x86-assembler.htm#disassembly 那是我用来将我的 OP 代码转换为的站点二进制表示(字节)。否则,我没有想法。附: asm 是保留关键字。此外,您的 asm (mov eax, 0x13) 代码等同于 {0xB8, 0x13, 0x00, 0x00, 0x00};
  • 请记住,asm 可能是关键字。
  • 致布兰登:我知道这个网站,但我想要一些 c++ 库在运行时转换它们。对丹尼尔:是的,你是对的!我已经改了。
  • 您确实应该编辑您的问题以提供更多背景和动机。你用的是什么编译器,什么操作系统?你在编写什么样的软件?

标签: c++ assembly


【解决方案1】:

我建议同时使用AsmJitAsmTK。 AsmTK 是一个使用 AsmJit 作为工具包并在其之上添加附加功能的新项目。请注意,目前 AsmTK 需要 asmjit:next 分支才能工作,因为这是一项新功能。

这是一个使用 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 中,以使其成为单个函数调用的问题,如果需要,我可以提供帮助。

【讨论】:

    【解决方案2】:

    你应该定义你真正想要的:

    您想在运行时生成机器码吗?然后使用一些JIT compilation 库,例如libgccjitlibjitLLVMGNU lightningasmjitasmjit 是一个发出 x86 机器代码的库,可能是您需要的。没有绝对需要使用包含汇编代码的字符串

    或者您想将一些汇编语法(甚至对于 x86 也有几种汇编语法)翻译成目标代码或机器代码?然后,您最好将真正的汇编程序作为外部程序运行。生成的object code 将包含relocation 指令,您需要一些东西来处理这些指令(例如linker)。

    或者,您应该考虑在运行时生成一些(例如)C 代码,然后分叉编译,并在运行时动态加载和使用生成的函数(例如,使用 dlopen(3)dlsym)。见this

    详细信息显然是操作系统、ABI 和处理器特定的。

    【讨论】:

      【解决方案3】:

      这是一个可以将一串汇编代码(Intel 或 ARM)转换为其对应字节的项目。

      https://github.com/bsmt/Assembler

      它是用 Objective-C 编写的,但源代码在那里。我希望这会有所帮助。

      【讨论】:

      • 链接的项目需要执行shell脚本,需要安装第三方汇编器才能工作。此外,标签似乎有一些问题。
      猜你喜欢
      • 1970-01-01
      • 2017-06-22
      • 1970-01-01
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多