在previous question中,我询问是否可以在内存中编写和执行汇编命令。我得到了一些很好的回答,经过一番研究后,我想出了如何做到这一点。现在我可以做到,我无法弄清楚要写入内存的内容(以及如何正确地执行此操作)。我知道一些汇编以及助记符如何转换为操作码,但我无法弄清楚如何正确使用操作码。
以下是我正在努力工作的一个例子:
void(*test)() = NULL; //create function pointer, initialize to NULL
void* hold_address = VirtualAlloc(NULL, 5*1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE); //allocate memory, make writable/ readable/ executable
unsigned char asm_commands[] = {0x55, 0x89, 0xE5, 0x83, 0xEC, 0x18, 0xC7, 0x04, 0x24, 0x41, 0xE8, 0x1E, 0xB3, 0x01, 0x00, 0xC9, 0xC3}; //create array of assembly commands, hex values
memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*10); //copy the array into the reserved memory
test = (void(*)())hold_address; //set the function pointer to start of the allocated memory
test(); //call the function
只需将0xC3放入asm_commands数组即可(并且函数只返回),但这很无聊。我现在在那里的一系列操作码(和地址)应该打印出字符“A”(大写字母a)。我通过调试一个调用printf(“A”)并在内存中查找调用的简单程序获得了操作码和地址。现在,程序返回0xC00000096错误,“特权命令”。我认为错误源于试图直接调用系统putchar地址,系统不喜欢。我也认为我可以通过给我的程序Ring 0访问来绕过它,但我几乎不知道除了很多潜在的问题之外还有什么需要。
那么有没有办法在不需要更高权限的情况下调用printf()函数(在程序集操作码中)?
我正在使用Windows 7,64位Code :: Blocks 10.05(GNU GCC编译器)。
这是调试的printf()调用的截图(在OllyDebug中):
答案 0 :(得分:4)
unsigned char asm_commands[] = {0x55, 0x89E5…
哇,坚持,停在那儿。 0x89E5
不是unsigned char
的有效值,您的编译器应该抱怨这一点。 (如果没有,请检查您的设置;您可能已禁用了一些非常重要的警告。)
您需要将此初始值设定项中的代码拆分为单个字节,例如
{0x55, 0x89, 0xE5, …
答案 1 :(得分:2)
因为你在dword 0x00000041中忘记了这些零并且错误地写了0x1A而不是0x1E,所以没有打印出来。
unsigned char asm_commands [] = {0x55,0x89,0xE5,0x83,0xEC,0x18,0xC7,0x04,0x24,0x41, 0x00,0x00,0x00, 0xE8, 0x1E, 0xB3,0x01,0x00,0xC9,0xC3}; //创建汇编命令数组,十六进制值
答案 2 :(得分:0)
除了@duskwuff和@ user3144770所写的内容。您是否更改了以下行以包含每个字节?
memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*10);
我已经计算了20个字节的汇编代码!
memcpy(hold_address, asm_commands, sizeof(asm_commands)[0]*20);