我有一个简单的C语言程序,带有编译器开关:/ GS-
这只是将EIP更改为机器代码字符串位置的概念证明。
假设我们设置EIP = 0x012f5000,这会将EIP放在以下数组的地址中:char code[] = "\x00\x00\x8B\x00\x00";
我不完全知道这些指令会做什么,但是x00指令似乎没有问题。将EIP切换到程序中的任何其他位置似乎都会引起问题,但是当我将EIP指向该阵列的地址时,我在EIP的该位置收到一些“访问冲突”异常。
为什么会出现此错误?这是由于某种Windows保护机制引起的吗?还是Windows无法以这种字符串形式运行指令?您如何获得执行这些指令的程序?
最佳答案
我猜你如果不使用x86 32位机器代码,我的答案是不正确的。
您的机器代码提供以下内容
0000 ADD BYTE PTR DS:[EAX],AL
8B00 MOV EAX,DWORD PTR DS:[EAX]
00XX ADD BYTE PTR ??? ; depends on the next byte
如您所见,如果您尝试执行此操作,它将尝试访问
eax
中地址处的内存。它也不会以ret
或其他结尾,因此它会直接运行而无需担心。在大多数情况下,这将崩溃。无论如何,您也有可能无法执行DATA段中定义的代码。如果要执行一些shellcode,可以尝试使用以下简单模板。这个想法是在堆栈上创建代码并在其中执行。给定的机器代码功能没有很好地实现,但至少是正确的,不会导致崩溃。它等效于C代码
void f( void ) { return; };
由VC ++在调试模式下编译。
#include <stdio.h>
int main()
{
const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00"
"\x00\x53\x56\x57\x8D\xBD\x40\xFF"
"\xFF\xFF\xB9\x30\x00\x00\x00\xB8"
"\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E"
"\x5B\x8B\xE5\x5D\xC3";
printf("Start execution\r\n");
((void (*)())code)();
printf("End execution\r\n");
_getch();
}
如果上述方法不起作用,您可以尝试。
#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
int main()
{
const char code[] = "\x55\x8B\xEC\x81\xEC\xC0\x00\x00"
"\x00\x53\x56\x57\x8D\xBD\x40\xFF"
"\xFF\xFF\xB9\x30\x00\x00\x00\xB8"
"\xCC\xCC\xCC\xCC\xF3\xAB\x5F\x5E"
"\x5B\x8B\xE5\x5D\xC3";
void *exec = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, code, sizeof(code));
printf("Start execution\r\n");
((void(*)())exec)();
printf("End execution\r\n");
//_getch();
}
想法是使用带有标志
PAGE_EXECUTE_READWRITE
的已分配内存页。关于c - 内联程序集在Visual C 2010中发生访问冲突,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13799472/