我的目标是找出哪些双字节操作码会生成非法指令异常.
例如,操作码0F 0B UD2
引发无效操作码异常.提供UD2
指令用于软件测试以显式生成无效操作码.
Warning蛇油代码领先,因为我不熟悉Windows的内部 struct .
下面的代码分配一个具有读/写/执行权限的4K页面,并以UD2
为起点try 确定所有可能的双字节操作码.
首先,它将两字节操作码复制到4K页面的最后两个字节
然后执行它们并判断异常代码.
我认为执行最后两个页面字节要么
- 生成恰好为两个字节的非法异常
EXCEPTION_ILLEGAL_INSTRUCTION
. - 当扩展到超过4K页面时,生成访问冲突
EXCEPTION_ACCESS_VIOLATION
.
运行下面的代码显示了有趣的指令以及许多未知数:
Illegal opcodes 0x0f 0x0b (error 0xc000001d)
ud2 - Generates an invalid opcode.
Illegal opcodes 0x0f 0x37 (error 0xc000001d)
getsec - Exit authenticated code execution mode.
Illegal opcodes 0x0f 0xaa (error 0xc000001d)
rsm - Resume operation of interrupted program.
Question个
黑客代码在这个操作码范围内运行得很好
正在执行操作码0x0f 0x0b...正在执行操作码0x0f 0xcb
直到它遇到这两个操作码
0x0f 0xcc业务互换Ep
似乎任何操作堆栈指针的操作都会导致问题,导致堆栈指针停留在这一点(点击Continue
只会重复消息)
我try 将操作码执行移到它自己的线程中,因为它们有自己的堆栈,但没有帮助!
有没有办法保留堆栈指针RSP
和RBP
,或者可能有一个简单的修复方法来解决它?
(使用M$Visual C++2019生成)
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <intrin.h>
// The UD2 (0x0F, 0x0B) instruction is guaranteed to generate an invalid opcode exception.
DWORD InstructionResult;
void ExecuteOpcodes(LPVOID mem)
{
__try
{
// Execute opcodes...
((void(*)())((unsigned char*)mem + 0xFFE))();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
InstructionResult = GetExceptionCode();
}
}
int main()
{
LPVOID mem = VirtualAlloc(NULL, 2, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
DWORD oldProtect = VirtualProtect(mem, 2, PAGE_EXECUTE_READWRITE, &oldProtect);
// Start searching at the UD2 (0x0F, 0x0B) instruction which is guaranteed to generate an invalid opcode exception.
for (int i = 15; i <= 255; i++)
{
for (int j = 11; j <= 255; j++)
{
// Write two byte opcodes at the 4K page end.
*((unsigned char*)mem + 0xFFE) = i;
*((unsigned char*)mem + 0xFFF) = j;
printf("Executing opcodes 0x%02x 0x%02x\n",i,j);
HANDLE hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ExecuteOpcodes, mem, 0, 0);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
if (InstructionResult == EXCEPTION_ILLEGAL_INSTRUCTION)
{
printf("Illegal opcodes 0x%02x 0x%02x (error 0x%08x)\n", i, j, InstructionResult);
}
}
}
VirtualFree(mem, 0, MEM_RELEASE);
return 0;
}