如何在字符串变量中运行ASM操作码或将其转换为字节



我在string属性中有这段asm代码:

mov [ecx+ebx*4+10],ff
jmp client.dll+3A8D96

在进入我试图实现的目标之前,首先我会将client.dll+…更改为它的最终地址。

现在我正在努力实现的是:

  • 将这段asm代码转换为等效字节,这样我就可以在使用winapi更改这些字节后将其写回内存。。

  • 或者以某种方式在分配的内存中写入字符串的内容,如果不将其转换为字节,这似乎是不可能的。。idk

我不知道是否可能,但我也有这个想法

  • 在c++中创建一个dll,该dll将具有一个可以从我的c#应用程序导入的函数
  • 通过传递asm操作码和分配的内存地址作为参数(不是c++专家(,利用任何可能的方法来实现我的目标,但我知道在c++中内联asm是可能的

请记住,本文中给出的ASM代码只是为了演示我正在尝试做的事情,它实际上会发生很大的变化,我希望您能理解。

使用Keystone的C#绑定将程序集转换为字节。它非常容易使用,你给它一个字符串,它给你一个字节数组,代表你为输入提供的汇编代码:

using Keystone;
using (Engine keystone = new Engine(Architecture.X86, Mode.X32) { ThrowOnError = true })
{
ulong address = 0;
keystone.ResolveSymbol += (string s, ref ulong w) =>
{
if (s == "_j1")
{
w = 0x1234abcd;
return true;
}
return false;
};
EncodedData enc = keystone.Assemble("xor eax, eax; jmp _j1", address);
enc.Buffer.ShouldBe(new byte[] { 0x00 });
enc.Address.ShouldBe(address);
enc.StatementCount.ShouldBe(3);
}

要将作弊引擎代码注入脚本转换为C#代码,您需要进行外部迂回。使用VirtualAllocateEx()在目标进程中获得空间,使用WriteProcessMemory将您使用KeyStone创建的shell代码写入内存,然后执行迂回执行流到您注入的shell代码。

您需要在绕行函数中手动解析相对跳转和所有相对地址。

或者,您可以使用CreateRemoteThread()在新线程中执行目标进程中的代码,而不是通过迂回,这取决于您想要做什么

如果您使用c#,我建议您使用包装器来写入进程内存和导入必要的dll等,并获取asm操作码的原始字节,并根据自己的对其进行操作

如果您使用的是c++,那么您可以只使用函数,而不需要获取包装器等;大多数函数都在C++库的中

如果你正在寻找像作弊引擎codecave(带跳转和跳回的aob注入(这样的东西,我认为你可以投入一些时间来学习一些关于内存操作/分配内存/asm如何工作的知识,之后你可以轻松地处理内存

同样,对于使用c++的内部dll,您需要使用原始字节,如果我记得正确的话,他们从visualstudio2010中删除了codecaves等的asm功能,并将其仅限于企业版或其他

如果您考虑按原样使用此操作码jmp client.dll+3A8D96如果你知道asm,那将是一个非常糟糕的主意,如果它是一个近乎跳跃的,那也没什么大不了的,但这些偏移可能会不时地改变

"xFExC8x5Bx23xC1"

这只是我如何使用字节作为代码的一个例子,youtube上有一些很好的教程,你应该看看

这远不是你的全部问题(C#…(,但它可能会给你一些线索。

这个例子是用C语言和Linux-64上的gcc完成的;你可能需要调整一下您的平台。

第一步是编写一个带有内联程序集的函数(gnu-asm语法(,以便查看objdump的外观(它从未被调用实际上(
跳转到常量地址的技巧在这里找到:https://stackoverflow.com/a/53876008/11527076

之后,我们必须创建一个可执行内存段并填充它的字节灵感来自上一个函数(多亏了objdump(
如果唯一可以更改的是地址,那么我们只覆盖上一个代码中的此地址
在本例中,另一个函数的地址用于此目的。

那么这个可执行内存段可以被认为是一个函数(嗯…希望如此(并且我们通过函数指针来使用它
而且它似乎起作用了!

我能看到的唯一问题是指令movb $0xff,0xa(%ecx,%ebx,4)因为我不知道具体登记了什么应包含
我决定用六个nop代替这个指令,以占据相同的位置并保持此示例与原始问题类似
(我想在您的问题中,这些寄存器将具有相关值(。

/**
gcc -std=c99 -o prog_c prog_c.c 
-pedantic -Wall -Wextra -Wconversion 
-Wc++-compat -Wwrite-strings -Wold-style-definition -Wvla 
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#undef __STRICT_ANSI__ // for MAP_ANONYMOUS
#include <sys/mman.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
void
target_function(void)
{
printf("~~~~ %s ~~~~n", __func__);
}
void
inline_asm_example(void)
{
__asm__ __volatile__(
"tnopn"
"tmovb   $0xff,0xa(%ecx,%ebx,4)n"
"tjmpq   *0x0(%rip)n"
".quad 0xAA00BB11CC22DD33n");
// the jump relative to rip is inspired from
// https://stackoverflow.com/a/53876008/11527076
}
int
main(void)
{
// create an executable page
void *page=mmap(NULL, 6+6+8,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(page==MAP_FAILED)
{
fprintf(stderr, "cannot allocate memory pagen");
return 1;
}
// initialise code pattern
//   objdump --disassemble=inline_asm_example prog
char *code_pattern=(char *)page;
#if 0 // this instruction causes something wrong
memcpy(code_pattern+0,
"x67xc6x44x99x0axff", 6); // movb   $0xff, 10(%ecx,%ebx,4)
#else // use some useless instructions instead
memcpy(code_pattern+0,
"x90x90x90x90x90x90", 6); // 6x nop
#endif
memcpy(code_pattern+6,
"xffx25x00x00x00x00", 6); // jmpq   *0x0(%rip)
// insert into the pattern the address we want to jump to
ptrdiff_t target_address=(ptrdiff_t)target_function;
memcpy(code_pattern+6+6, &target_address, sizeof(target_address));
// consider the code pattern as a function
void (*fnct_ptr)(void)=NULL;
memcpy(&fnct_ptr, &code_pattern, sizeof(code_pattern));
// here we go
printf("about to do something I will probably regret...n");
fnct_ptr();
printf("ah? it was not so painful after all!n");
// let's forget everything about that
munmap(code_pattern, 6+6+8);
return 0;
}

最新更新