一直想做一个类似KeyMaker的Loader,能解壳,能读寄存器,读指定内存值,通宵了一晚上基本搞定
下面是代码:
// MemoryReader.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
#include "Commdlg.h"
#include "winnt.h"
BYTE INT3 = 0xCC;
//写入前的
BYTE Old;
//页面属性
DWORD OldProtect;
//是否已写入INT3
bool HasINT3 = false;
bool IsFirstINT3 = true;
DWORD BreakPoint = 0x10074B8;
BYTE Org[8] = ...{0x80,0x3E};
//判断是否解压完成
bool IsUnpacked(PROCESS_INFORMATION pi)
...{
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])
...{
//不能乱调用
Old = mem[0];
return TRUE;
}
return false;
}
//写INT3
bool WriteINT3(PROCESS_INFORMATION pi)
...{
//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;
}
//改回去
bool CleanINT3(PROCESS_INFORMATION pi)
...{
//SuspendThread(pi.hThread);
bool ret = WriteProcessMemory(pi.hProcess,(LPVOID)BreakPoint,&Old,sizeof(Old),NULL);
if(ret == false)
...{
printf("改回去失败!");
}
CONTEXT context;
ZeroMemory(&context,sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread,&context);
context.Eip--;
SetThreadContext(pi.hThread,&context);
printf("已经改回去了,Eax:%x",context.Eax);
return ret;
}
int main(int argc, char* argv[])
...{
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)
...{
MessageBox(NULL,"创建进程失败!","",0);
return -1;
}
DEBUG_EVENT devent;
int DllCount = 0;
while(TRUE)
...{
if(WaitForDebugEvent(&devent,1))
...{
switch(devent.dwDebugEventCode)
...{
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)
...{
case EXCEPTION_BREAKPOINT:
if(HasINT3)
...{
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)
...{
if(!CleanINT3(pi))
...{
printf("清除断点失败!");
}
printf("Program Stopped At What We Want");
char key[256];
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);
ContinueDebugEvent(pi.dwProcessId,pi.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
/**//* 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);
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)
...{
if(IsUnpacked(pi))
...{
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)
...{
if(IsUnpacked(pi))
...{
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
...{
}
}
//KeyMake中不要这两句
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
可以解压缩和加密壳,不过必须是要获得的内容是壳执行之后,如果再壳执行之前有内容的话可能会被壳偷掉,另外还不支持AntiDebug,不过测试Keymake也不支持AntiDebug,慢慢修改了