一直想做一个类似KeyMaker的Loader,能解壳,能读寄存器,读指定内存值,通宵了一晚上基本搞定
下面是代码:
//
MemoryReader.cpp : 定义控制台应用程序的入口点。
//
#include
"
stdafx.h
"
#include
"
windows.h
"
#include
"
Commdlg.h
"
#include
"
winnt.h
"
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
BYTE INT3
=
0xCC
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
写入前的
BYTE Old;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
页面属性
DWORD OldProtect;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
是否已写入INT3
bool
HasINT3
=
false
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
bool
IsFirstINT3
=
true
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
DWORD BreakPoint
=
0x10074B8
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
BYTE Org[
8
]
=
...
{0x80,0x3E}
;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
判断是否解压完成
bool
IsUnpacked(PROCESS_INFORMATION pi)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
SuspendThread(pi.hThread);
CONTEXT context;
ZeroMemory(&context,sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread,&context);
printf("Exe Info:Eax:%x,Esp:%x,Eip:%x ",context.Eax,context.Esp,context.Eip);
ResumeThread(pi.hThread);
BYTE mem[8];
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
ReadProcessMemory(pi.hProcess,(LPCVOID)BreakPoint,&mem,8,NULL);
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
printf("hex num is:%x,%x,%x,%x ",mem[0],mem[1],mem[2],mem[3]);
if(mem[0] ^ 0xff == Org[0] && mem[1] ^ 0xff == Org[1])
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//不能乱调用
Old = mem[0];
return TRUE;
}
return false;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
写INT3
bool
WriteINT3(PROCESS_INFORMATION pi)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
//VirtualAllocEx(pi.hProcess,(LPVOID)0x0101259b,sizeof(INT3), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
SuspendThread(pi.hThread);
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
bool ret = WriteProcessMemory(pi.hProcess,(LPVOID)BreakPoint,&INT3,sizeof(INT3),NULL);
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
HasINT3 = ret;
ResumeThread(pi.hThread);
return ret;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
改回去
bool
CleanINT3(PROCESS_INFORMATION pi)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
//SuspendThread(pi.hThread);
bool ret = WriteProcessMemory(pi.hProcess,(LPVOID)BreakPoint,&Old,sizeof(Old),NULL);
if(ret == false)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("改回去失败! ");
}
CONTEXT context;
ZeroMemory(&context,sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread,&context);
context.Eip--;
SetThreadContext(pi.hThread,&context);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
printf("已经改回去了,Eax:%x ",context.Eax);
return ret;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int
main(
int
argc,
char
*
argv[])
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
char f_name[256];
f_name[0] = NULL;
OPENFILENAME filename;
ZeroMemory(&filename,sizeof(OPENFILENAME));
filename.lStructSize = sizeof(OPENFILENAME);
filename.hwndOwner = NULL;
filename.lpstrFilter = "*.exe";
filename.lpstrFile = f_name;
filename.nMaxFile = 256;
filename.lpstrInitialDir = NULL;
filename.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
if(!GetOpenFileName(&filename))
return 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si,sizeof(STARTUPINFO));
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
bool ret = CreateProcess(filename.lpstrFile,"",NULL,NULL,FALSE,DEBUG_PROCESS,NULL,NULL,&si,&pi);
if(ret == false)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
MessageBox(NULL,"创建进程失败!","",0);
return -1;
}
DEBUG_EVENT devent;
int DllCount = 0;
while(TRUE)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(WaitForDebugEvent(&devent,1))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
switch(devent.dwDebugEventCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
case CREATE_PROCESS_DEBUG_EVENT:
printf("CREATE_PROCESS_DEBUG_EVENT... ");
break;
case CREATE_THREAD_DEBUG_EVENT:
printf("CREATE_THREAD_DEBUG_EVENT... ");
break;
case EXCEPTION_DEBUG_EVENT:
//printf("EXCEPTION_DEBUG_EVENT... ");
switch(devent.u.Exception.ExceptionRecord.ExceptionCode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
case EXCEPTION_BREAKPOINT:
if(HasINT3)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
SuspendThread(pi.hThread);
CONTEXT context;
ZeroMemory(&context,sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread,&context);
printf("Eax:%x ,Esi:%x ,Eip:%x ,Ebp:%x ",context.Eax,context.Esi,context.Eip,context.Ebp);
if(context.Eip == BreakPoint + 1)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(!CleanINT3(pi))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("清除断点失败!");
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
printf("Program Stopped At What We Want ");
char key[256];
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,PAGE_READWRITE, &OldProtect);
ReadProcessMemory(pi.hProcess,(LPCVOID)context.Esi,key,sizeof(key),NULL);
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
printf("读出来的东西是 %s ",key);
}
ResumeThread(pi.hThread);
}
break;
case EXCEPTION_SINGLE_STEP:
printf("2 EXCEPTION_SINGLE_STEP ");
break;
case EXCEPTION_ACCESS_VIOLATION:
printf("读写地址出错 ");
printf("%d,%x ",devent.u.Exception.ExceptionRecord.ExceptionInformation[0],devent.u.Exception.ExceptionRecord.ExceptionAddress);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
/**//* char Nop[3];
Nop[0] = 0x90;
Nop[1] = 0x90;
Nop[2] = 0x90;
PVOID pathAddress;
pathAddress = devent.u.Exception.ExceptionRecord.ExceptionAddress;
VirtualProtectEx(pi.hProcess,pathAddress,3,PAGE_READWRITE, &OldProtect);
WriteProcessMemory(pi.hProcess,pathAddress,Nop,3,NULL);
VirtualProtectEx(pi.hProcess,(LPVOID)BreakPoint,1,OldProtect,&OldProtect);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_EXCEPTION_NOT_HANDLED); */
break;
default:
break;
}
break;
case LOAD_DLL_DEBUG_EVENT:
//获取DLL NAME太复杂,暂时做不到
DllCount ++;
printf("%d,Program Loads a Dll From BaseImage:%x,ImageName:%x ",DllCount,devent.u.LoadDll.lpBaseOfDll,devent.u.LoadDll.lpImageName);
if(!HasINT3)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(IsUnpacked(pi))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("UnPacked Success!! ");
WriteINT3(pi);
printf("Write a INT3 ");
}
}
break;
case UNLOAD_DLL_DEBUG_EVENT:
printf("UnLoad a Dll From BaseImage:%x,ImageName:%x ",devent.u.LoadDll.lpBaseOfDll,devent.u.LoadDll.lpImageName);
if(!HasINT3)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if(IsUnpacked(pi))
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
printf("UnPacked Success!! ");
WriteINT3(pi);
printf("Write a INT3 ");
}
}
break;
break;
case OUTPUT_DEBUG_STRING_EVENT:
break;
case EXIT_PROCESS_DEBUG_EVENT:
printf("调试程序已退出");
break;
default:
printf("%d ",devent.dwDebugEventCode);
break;
}
ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_CONTINUE);
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
}
}
//KeyMake中不要这两句
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
可以解压缩和加密壳,不过必须是要获得的内容是壳执行之后,如果再壳执行之前有内容的话可能会被壳偷掉,另外还不支持AntiDebug,不过测试Keymake也不支持AntiDebug,慢慢修改了