年底了,又赶上离职潮了。离职的coder总想着带走一些代码,自己的无可厚非,别人的就不大好了。如何保护公司的重要代码成了头痛的问题。本文通过添加一些简单的手段保护重要的代码。当然,这些手段有些陈旧,对付老鸟基本无效,但一般的coder拿到这样的代码,只能按delete了。。。吗啡,在药师手上变成了麻醉药,但在瘾君子看来又是一顿饕餮,这些手段如果被离职的coder自己使用,不仅制造bug还代码保护,那交接的coder又要抓狂了~
这里做一些约定VS编译器去除了/Gz 选项(函数调用后检查堆栈),并启用非增量连接方式。
//V1 假设CriticalCodeV1是核心代码 需要隐藏其实现CriticalCodeV1是我的核心代码,假设这个代码被人觊觎(事实不会)。在文章的结尾,这段代码会被我隐藏的面目全非。
__declspec(naked) void CriticalCodeV1()
{
MessageBox(NULL,"Cap","Msg",MB_OK);
ExitProcess(0);
}
void CriticalCodeEnd()
{
}
int main()
{
CriticalCodeV1();
}
现在逐步开始隐藏代码:
DWORD MsgBoxAddr;这段代码仅仅是一个过渡,用来生成后续的ShellCode。注释中已经写到同样的API在不同的机器上入口地址不同,因此需要重定位,如何重定位?反汇编后记录Call指令之后EIP跳转到一个jmp指令,jmp指令的目标地址就是你机器上API函数的入口,用你的地址替换我的地址。当然,最好的办法是通过PE文件导入表获取,不过这样就不是简单的保护方式了;另外,毕竟是自己的代码,在代码中获得本机API入口还是比较方便的,因此用LoadLibrary(/GetProcAddress)直接加载。啊真是简单粗暴而又有效的方法~
DWORD ExitProcAddr;
__declspec(naked) void CriticalCodeV2()
{
//因为函数声明为裸函数 不会自动生成函数框架
//因此需要自己保存函数框架和开辟堆空间
__asm
{
push ebp;
mov ebp,esp;
sub esp,0x10;
mov al,'C';
mov [ebp-0x04],al;
mov al,'a';
mov [ebp-0x03],al;
mov al,'p';
mov [ebp-0x02],al;
xor eax,eax;
mov [ebp-0x01],al;
mov al, 'M';
mov [ebp-0x08],al;
mov al,'s';
mov [ebp-0x07],al;
mov al, 'g';
mov [ebp-0x06],al;
xor eax,eax;
mov [ebp-0x05],al;
push 0x00;
lea eax,[ebp-0x04]
push eax; //push "cap"
lea eax,[ebp-0x08]
push eax; //push "Msg"
push 0x00;
//不同机器 MessageBoxA ExitProcess入口地址不同 需要重定位
//此处为了方便 直接硬编码
mov eax,0x749AFD1E;
call eax;
push 0x00;
mov eax,0x768F79D8;
call eax;
}
}
void CriticalCodeEnd()
{
}
int main()
{
HMODULE hU32Mod = LoadLibrary("user32.dll");
MsgBoxAddr = (DWORD)GetProcAddress(hU32Mod,"MessageBoxA");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
ExitProcAddr = (DWORD)GetProcAddress(hKrlMod,"ExitProcess");
//反汇编 记录函数地址的内容
CriticalCodeV2();
}
//V3 将V2中的OpCode写入数组,初步隐藏关键代码。创建读写可执行的页,然后跳转到该页执行程序写到这,CriticalCodeV2已经被数组CriticalCodeSCSrcEnc中的内容取代,一眼看去不知CriticalCodeSCSrcEnc所云何物。不过只要跟着jmp [esp]一起跳转到SMCPtr的地址,就能看到程序正在做啥,更进一步,还可以把代码全记录下来,copy到静态汇编工具慢慢看。
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//shellcode 写到这 谁能一眼看出是什么鸟语
char CriticalCodeSCSrc[] = {"\x55\x8B\xEC\x83\xEC\x10\xB0\x43" \
"\x88\x45\xFC\xB0\x61\x88\x45\xFD" \
"\xB0\x70\x88\x45\xFE\x33\xC0\x88" \
"\x45\xFF\xB0\x4D\x88\x45\xF8\xB0" \
"\x73\x88\x45\xF9\xB0\x67\x88\x45" \
"\xFA\x33\xC0\x88\x45\xFB\x6A\x00" \
"\x8D\x45\xFC\x50\x8D\x45\xF8\x50" \
"\x6A\x00\xB8\x1E\xFD\x9A\x74\xFF" \
"\xD0\x6A\x00\xB8\xD8\x79\x8F\x76" \
"\xFF\xD0\xCC\xCC\xCC\xCC\xCC\xCC"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrc,CriticalCodeLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
__asm
{
//这句的效果等于 call SMCPtr
push SMCPtr;
jmp [esp];
}
}
//V4 对数组进行加密,直到关键代码段执行前才解密,进一步隐藏源码既然,上面可以把隐藏的代码记录下来慢慢分析,那我只能把CriticalCodeSCSrcEnc中的内容加密,在运行DeCode后才解密全部内容,让观察者不能尽兴~加密方式是CriticalCodeSCSrcEnc与0xCC异或。不过问题又来了,这解密函数是明文,观察者自己解密,又能慢慢看了,还真是藏头露尾的办法。下面对解密部分略作修改,办法如V2/V3
void DeCode(char* SMCPtr,DWORD SMCLen)
{
for(DWORD i=0;i<SMCLen;i++)
{
SMCPtr[i] ^= 0xcc;
}
}
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
DeCode(SMCPtr,CriticalCodeLen);
__asm
{
push SMCPtr;
jmp [esp];
}
}
//V4中 解密部分源码是为加密的 这等于CriticalCodeSCSrcEnc没有保护V5又是一个半成品,不说了,直接跳到V5-1
//因此 需要把解密部分的代码也隐藏起来 这段就不用抑或了 要不然又要有人去解密这段代码了
//在V5中将使用V4 DeCode部分实现的OpCode
__declspec(naked) void DeCodeSMC(char* SMCPtr,DWORD SMCLen)
{
__asm
{
//[ebp+0]:ebp [ebp+0x04]:retAddtr [ebp+0x08]:SMCPtr [ebp+0x0C]:SMCLen
push ebp;
mov ebp,esp;
sub esp,0x10;
//[ebp-4]:DWORD i;
mov [ebp-4],0x00;
mov [ebp-3],0x00;
mov [ebp-2],0x00;
mov [ebp-1],0x00;
jmp Lab2;
Lab1:
mov eax,[ebp-4];
inc eax;
mov [ebp-4],eax
Lab2:
mov ecx,[ebp-4];
cmp ecx,[ebp+0Ch];
jae Lab3;
mov edx,[ebp+8];
add edx,[ebp-4];
mov al,[edx];
xor al,0xCC;
mov ecx,[ebp+8];
add ecx,[ebp-4];
mov [ecx],al;
jmp Lab1;
Lab3:
mov esp,ebp;
pop ebp;
ret 8
}
}
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
push SMCPtr;
jmp [esp];
}
}
//v5-1借助V5,将DeCodeSMC成功毁容,现在DeCodeSMC已经寄居在DeCodeSMC数组中,程序运行前跳转到DeCodeSMC数组中,解密CriticalCodeSCSrcEnc数组,解密完成才跳转到CriticalCodeSCSrcEnc执行。
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
DWORD DeCodeSMCLen = 0x80;
char DeCodeSMC[] = {"\x55\x8B\xEC\x83\xEC\x10\xC6\x45" \
"\xFC\x00\xC6\x45\xFD\x00\xC6\x45" \
"\xFE\x00\xC6\x45\xFF\x00\xEB\x07" \
"\x8B\x45\xFC\x40\x89\x45\xFC\x8B" \
"\x4D\xFC\x3B\x4D\x0C\x73\x14\x8B" \
"\x55\x08\x03\x55\xFC\x8A\x02\x34" \
"\xCC\x8B\x4D\x08\x03\x4D\xFC\x88" \
"\x01\xEB\xDD\x8B\xE5\x5D\xC2\x08" \
"\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
//DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
//注意DeCodeSMC压栈顺序,右边的先入栈-先push
push CriticalCodeLen
push SMCPtr
//模拟调用DeCodeSMC(SMCPtr,CriticalCodeLen);
call SMCDecPtr
}
//SMC完成 跳去受保护的代码端执行
__asm
{
push SMCPtr;
jmp [esp];
}
}
写到这,隐藏的够深了吧?No,如果用调试器调试跟踪运行,一切还是白搭,因此下一步要检测调试器是否存在,如果存在,程序退出,麻烦你还是静态分析,因为静态分析已经够麻烦了。
//开始动态反调试前 看个检测调试器的函数原本以为win7带有IsDebuggerPresent这API,结果么得,只能自己实现了。
__declspec(naked) bool IsDebuggerPresent()
{
//windows设定 fs:[30]这个内存为当前进程的进程控制块
//进程控制块的第二个字节标志进程是否被调试
__asm
{
mov eax,fs:[0x30];
movzx eax,[eax+0x02];
ret;
}
}
好的,加上检测调试器:
//V6-1 解密前 检测是否动态调试
//V6-1 解密前 检测是否动态调试这段Shellcode在DeCodeSMC入口检测调试器,如果存在程序退出。现在可以试试程序直接运行和调试运行的结果。
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
DWORD DeCodeSMCLen = 0xC0;
char DeCodeSMC[] = {
"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
"\x90\x90\x90\x90\x90\x90\x90\x90" \
"\x55\x8B\xEC\x83\xEC\x10\xC6\x45" \
"\xFC\x00\xC6\x45\xFD\x00\xC6\x45" \
"\xFE\x00\xC6\x45\xFF\x00\xEB\x07" \
"\x8B\x45\xFC\x40\x89\x45\xFC\x8B" \
"\x4D\xFC\x3B\x4D\x0C\x73\x14\x8B" \
"\x55\x08\x03\x55\xFC\x8A\x02\x34" \
"\xCC\x8B\x4D\x08\x03\x4D\xFC\x88" \
"\x01\xEB\xDD\x8B\xE5\x5D\xC2\x08" \
"\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
//DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
//注意DeCodeSMC压栈顺序,右边的先入栈-先push
push CriticalCodeLen
push SMCPtr
//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
call SMCDecPtr
}
//SMC完成 跳去受保护的代码端执行
__asm
{
push SMCPtr;
jmp [esp];
}
}
解密函数反动态调试是过了,观察者还能静态分析,为了对付静态分析,我再手贱加点花指令,干扰他们静态分析,深入的花指令看我另一篇博文
__declspec(naked) void DeCodeSMC(char* SMCPtr,DWORD SMCLen)这个也是过渡版,来看下大结局
{
__asm
{
//[ebp+0]:ebp [ebp+0x04]:retAddtr [ebp+0x08]:SMCPtr [ebp+0x0C]:SMCLen
mov eax,fs:[0x30];
movzx eax,[eax+0x02];
cmp eax,0x00;
jz StartDecode;
push 0x00;
mov eax,0x768F79D8;
call eax;
StartDecode:
nop;
nop;
nop;
nop;
push ebp;
mov ebp,esp;
sub esp,0x10;
//[ebp-4]:DWORD i;
mov [ebp-4],0x00;
mov [ebp-3],0x00;
mov [ebp-2],0x00;
mov [ebp-1],0x00;
jmp Lab2;
Lab1:
//插入花指令
mov eax,0;
cmp eax,1;
jnz ThunkCode1;
jz ThunkCode1;
_emit 0xE9
ThunkCode1:
//花指令结束
mov eax,[ebp-4];
inc eax;
mov [ebp-4],eax
Lab2:
mov ecx,[ebp-4];
cmp ecx,[ebp+0Ch];
jae Lab3;
//插入花指令
mov eax,1;
cmp eax,0;
jnz ThunkCode2;
jz ThunkCode2;
_emit 0xE9
ThunkCode2:
//花指令结束
mov edx,[ebp+8];
add edx,[ebp-4];
mov al,[edx];
xor al,0xCC;
mov ecx,[ebp+8];
add ecx,[ebp-4];
mov [ecx],al;
jmp Lab1;
Lab3:
mov esp,ebp;
pop ebp;
ret 8
}
}
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
push SMCPtr;
jmp [esp];
}
}
int main()经手术函数CriticalCodeV1已成功整容,不用几天我也记不得他原本长什么样~
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
DWORD DeCodeSMCLen = 0x110;
char DeCodeSMC[] = {
"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
"\x90\x90\x90\x90\x55\x8B\xEC\x83" \
"\xEC\x10\xC6\x45\xFC\x00\xC6\x45" \
"\xFD\x00\xC6\x45\xFE\x00\xC6\x45" \
"\xFF\x00\xEB\x14\xB8\x00\x00\x00" \
"\x00\x83\xF8\x01\x75\x03\x74\x01" \
"\xE9\x8B\x45\xFC\x40\x89\x45\xFC" \
"\x8B\x4D\xFC\x3B\x4D\x0C\x73\x21" \
"\xB8\x01\x00\x00\x00\x83\xF8\x00" \
"\x75\x03\x74\x01\xE9\x8B\x55\x08" \
"\x03\x55\xFC\x8A\x02\x34\xCC\x8B" \
"\x4D\x08\x03\x4D\xFC\x88\x01\xEB" \
"\xC3\x8B\xE5\x5D\xC2\x08\x00\xCC" \
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
//DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
//注意DeCodeSMC压栈顺序,右边的先入栈-先push
push CriticalCodeLen
push SMCPtr
//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
call SMCDecPtr
}
//SMC完成 跳去受保护的代码端执行
__asm
{
push SMCPtr;
jmp [esp];
}
}
int main()
{
DWORD writtenNum=0;
DWORD CriticalCodeLen = 0x50;
//CriticalCodeSCSrcEnc将原CriticalCodeSCSrc中的与0xcc异或 生成新的编码
//运行前先与0xcc异或解密
char CriticalCodeSCSrcEnc[] = {"\x99\x47\x20\x4F\x20\xDC\x7C\x8F" \
"\x44\x89\x30\x7C\xAD\x44\x89\x31" \
"\x7C\xBC\x44\x89\x32\xFF\x0C\x44" \
"\x89\x33\x7C\x81\x44\x89\x34\x7C" \
"\xBF\x44\x89\x35\x7C\xAB\x44\x89" \
"\x36\xFF\x0C\x44\x89\x37\xA6\xCC" \
"\x41\x89\x30\x9C\x41\x89\x34\x9C" \
"\xA6\xCC\x74\xD2\x31\x56\xB8\x33" \
"\x1C\xA6\xCC\x74\x14\xB5\x43\xBA" \
"\x33\x1C\x00\x00\x00\x00\x00\x00"};
DWORD DeCodeSMCLen = 0x110;
char DeCodeSMC[] = {
"\x64\xA1\x30\x00\x00\x00\x0F\xB6" \
"\x40\x02\x83\xF8\x00\x74\x09\x6A" \
"\x00\xB8\xD8\x79\x8F\x76\xFF\xD0" \
"\x90\x90\x90\x90\x55\x8B\xEC\x83" \
"\xEC\x10\xC6\x45\xFC\x00\xC6\x45" \
"\xFD\x00\xC6\x45\xFE\x00\xC6\x45" \
"\xFF\x00\xEB\x14\xB8\x00\x00\x00" \
"\x00\x83\xF8\x01\x75\x03\x74\x01" \
"\xE9\x8B\x45\xFC\x40\x89\x45\xFC" \
"\x8B\x4D\xFC\x3B\x4D\x0C\x73\x21" \
"\xB8\x01\x00\x00\x00\x83\xF8\x00" \
"\x75\x03\x74\x01\xE9\x8B\x55\x08" \
"\x03\x55\xFC\x8A\x02\x34\xCC\x8B" \
"\x4D\x08\x03\x4D\xFC\x88\x01\xEB" \
"\xC3\x8B\xE5\x5D\xC2\x08\x00\xCC" \
"\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC"};
char* SMCPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
int state = WriteProcessMemory(GetCurrentProcess(),SMCPtr,CriticalCodeSCSrcEnc,CriticalCodeLen,&writtenNum);
assert(state);
char* SMCDecPtr = (char*)VirtualAllocEx(GetCurrentProcess(),NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
assert(SMCPtr);
state = WriteProcessMemory(GetCurrentProcess(),SMCDecPtr,DeCodeSMC,DeCodeSMCLen,&writtenNum);
assert(state);
HMODULE hU32Mod = LoadLibrary("user32.dll");
HMODULE hKrlMod = LoadLibrary("kernel32.dll");
//程序中已经没有DeCodeSMC这个函数 但是进程地址空间中还有类似功能的二进制码 需要显式模拟一次DeCodeSMC调用
//DeCodeSMC(SMCPtr,CriticalCodeLen);
__asm
{
//注意DeCodeSMC压栈顺序,右边的先入栈-先push
push CriticalCodeLen
push SMCPtr
//模拟DeCodeSMC(SMCPtr,CriticalCodeLen);
call SMCDecPtr
}
//SMC完成 跳去受保护的代码端执行
__asm
{
push SMCPtr;
jmp [esp];
}
}