继续old question,我无法手动调用Windows 7 putchar地址。
我使用一个程序集操作码数组来模拟C ++函数和对printf()命令的调用。我将操作码数组复制到保留的内存中,并使用一个函数指针调用它,我指向数组的开头(在复制到内存之后)。
有问题的数组:
uint8_t asmCommandsPart1[] = {0x55, //push EBP
0x89, 0xE5, //mov EBP, ESP
0x83, 0xEC, 0x18, //sub ESP, 0x18
0xC7, 0x04, 0x24, 0x41, 0x00, 0x00, 0x00, //mov DWORD PTR SS:[ESP],0x41
0xE8}; //call
//The next byte is the start of the offset to jump to
uint8_t asmCommandsPart2[] = {0xC9, 0xC3}; //leave, retn
我通过使用常量地址并从该地址减去asmCommandsPart1(0xE8)的最后一个字节的地址来计算跳转偏移量,并添加5.我可以确认这是有效的,因为我打印出的字节值计算地址(asmCommandsPart1 + offset中的0xE8的地址),并将它们与程序的反汇编版本(在OllyDbg中完成)中的值进行比较,并且它们匹配。
这是我如何计算偏移量,以及将地址放在内存中的memcpy调用(hold_address是指向保留内存开头的指针):
memcpy(hold_address, asmCommandsPart1, sizeof(asmCommandsPart1)[0]*14); //copy the array into the reserved memory
int asmCommandsOffset = 14; //when calculating offset when counting in array, start at 0
char* jumpFromAddress = (hold_address+asmCommandsOffset); //Calculate the end of asmCommandsPart1 starting from hold_address
char* jumpToAddress = reinterpret_cast<char*>(0x0041CA70); //Create pointer to memory where jumping to
int jumpAddressOffset = abs((int)(jumpToAddress-jumpFromAddress))+5; //Calculate the offset between the two pointers
memcpy(jumpFromAddress, &jumpAddressOffset, sizeof(jumpAddressOffset)); //copy calculated address of putchar into memory
memcpy(jumpFromAddress+sizeof(jumpAddressOffset), asmCommandsPart2, sizeof(asmCommandsPart2)[0]*2); //copy 0xC9 and 0xC3 into memory
唯一的问题是程序在跳转到putchar地址时返回0x3错误。 NTSTATUS values上的MSDN文档告诉我这是一个“STATUS_WAIT_3”错误代码,但是它的描述并没有告诉我什么。 System Error Codes上的MSDN文档说它是ERROR_PATH_NOT_FOUND错误,它再次告诉我什么。
我错过了什么?地址显然是可调用的,程序已经完成了,我只是无法复制它,即使完全复制操作码(注意:操作码/顺序从未改变,只是地址)。
请注意,跳转到附近的地址(例如中止)可以正常工作。我只测试了abort和putchar。另请注意,我意识到putchar的地址发生了变化,我将继续动态计算它。
这是内存中putchar和abort命令的图片。跳转到0041CA80将导致程序崩溃,错误代码为0x3,跳转到0041CA90将正常工作。