注册机偷懒写法1、之直接扣代码
注册机偷懒写法2、之直接调用源程序的函数
注册机偷懒写法3、内联Hook让程序自己弹出注册码
注册机偷懒写法4、调试模式下获取
找到存储注册码的存储到内存或者寄存器的代码,通过通过修改内存中程序的代码,如弹出messagebox之类
#include
#include
/*
找到存储注册码的存储到内存或者寄存器的代码
通过通过修改内存中程序的代码,如弹出messagebox之类
获取注册码
release编译关闭安全检查
*/
//获取需要调用的函数或数据新地址,源程序的加载基址与需要调用的函数或数据相对虚拟地址
int GetNewAddress(HMODULE hsrc, int sRva)
{
return (int)hsrc + sRva;
}
void shellcode2()
{
__asm
{
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
}
__asm
{
//分配栈空间
mov eax, [ebp - 0xc]
sub esp, 0x80
sub ebp, 0x40
}
int msgadr;
__asm
{
mov msgadr,eax
}
HMODULE hKernel = NULL;
// 1. 获取kernel32.dll的加载基址
DWORD imageBase = 0;
_asm
{
mov eax, fs: [0x30];
mov ebx, [eax + 8];//进程基址
mov imageBase, ebx;
mov eax, [eax + 0xc];//Ldr
mov eax, [eax + 0x1C];// Ldr.LoadXXX链表
mov eax, [eax]; // 第二个节点
mov eax, [eax]; // 第三个节点:kernel32
mov eax, [eax + 0x8];// 加载基址
mov hKernel, eax;
}
typedef void* (WINAPI* FnGetProcAddress)(HMODULE, LPCSTR);
FnGetProcAddress pFnGetProcAddress;
// 2. 遍历导出表, 获取GetProcAddress的地址
IMAGE_OPTIONAL_HEADER* pOptionHeader = &((IMAGE_NT_HEADERS*)(((IMAGE_DOS_HEADER*)hKernel)->e_lfanew + (SIZE_T)hKernel))->OptionalHeader;
IMAGE_EXPORT_DIRECTORY* pExp = (IMAGE_EXPORT_DIRECTORY*)
(pOptionHeader->DataDirectory[0].VirtualAddress + (DWORD)hKernel);
DWORD * pEAT = (DWORD*)(pExp->AddressOfFunctions + (DWORD)hKernel);
DWORD * pENT = (DWORD*)(pExp->AddressOfNames + (DWORD)hKernel);
WORD * pEOT = (WORD*)(pExp->AddressOfNameOrdinals + (DWORD)hKernel);
for (DWORD i = 0; i < pExp->NumberOfNames; ++i)
{
char* pName = pENT[i] + (char*)hKernel;
// pName -> "GetProcAddress"
//
// 47 65 74 50 72 6f 63 41
// 64 64 72 65
// 73 73
// if (strcmp(pName, "GetProcAddress") == 0)
if (*(ULONGLONG*)pName == 0x41636f7250746547) {
if (*(DWORD*)(pName + 8) == 0x65726464) {
if (*(WORD*)(pName + 8 + 4) == 0x7373)
{
pFnGetProcAddress = (FnGetProcAddress)
(pEAT[pEOT[i]] + (DWORD)hKernel);
break;
}
}
}
}
// 3. 通过GetProcAddress获取LoadLibraryA的地址
char strLoadLibraryA[] = { 'L','o','a','d','L','i','b','r','a','r','y','A','\0' };
typedef HMODULE(WINAPI* FnLoadLibraryA)(LPCSTR);
FnLoadLibraryA pFnLoadLibraryA = (FnLoadLibraryA)
pFnGetProcAddress(hKernel, strLoadLibraryA);
// 4. 获取其它API的地址
char user32_dll[] = { 'u','s','e','r','3','2','.','d','l','l','\0' };
HMODULE hUser = pFnLoadLibraryA(user32_dll);
typedef int (WINAPI* FnMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
char strMessageBoxA[] = { 'M','e','s','s','a','g','e','B','o','x','A','\0' };
FnMessageBoxA msgBox = (FnMessageBoxA)
pFnGetProcAddress(hUser, strMessageBoxA);
msgBox(NULL, (LPCSTR)msgadr, NULL, 0);
__asm
{
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x00
_emit 0x11
}
}
int main()
{
HMODULE hsrc = NULL;
STARTUPINFO ie_si = { 0 };
PROCESS_INFORMATION ie_pi;
ie_si.cb = sizeof(ie_si);
//以挂起的方式创建进程
TCHAR szBuffer[256] = "Dope2112.1.exe";
CreateProcessA(
NULL, // name of executable module
szBuffer, // command line string
NULL, // SD
NULL, // SD
FALSE, // handle inheritance option
CREATE_SUSPENDED, // creation flags
NULL, // new environment block
NULL, // current directory name
&ie_si, // startup information
&ie_pi // process information
);
CONTEXT contx;
contx.ContextFlags = CONTEXT_FULL;
GetThreadContext(ie_pi.hThread, &contx);
//获取入口点
DWORD dwEntryPoint = contx.Eax;
//获取ImageBase
char* baseAddress = (char*)contx.Ebx + 8;
ReadProcessMemory(ie_pi.hProcess, baseAddress, &hsrc, 4, NULL);
/*
00421CFE | E8 71 36 FE FF | call | ???
00421D03 | 8D 55 E4 | lea edx,dword ptr ss:[ebp-1C] | [ebp-1C]:"46"
00421D06 | 33 C0 | xor eax,eax | [ebp-1c]临时变量
00421D08 | 8A C3 | mov al,bl |
00421D0A | E8 65 36 FE FF | call | ???
00421D0F | FF 75 E4 | push dword ptr ss:[ebp-1C] | [ebp-1C]:"46"
00421D12 | 68 D8 1D 42 00 | push dope2112.1.421DD8 | 421DD8:L"-"
00421D17 | FF 75 F0 | push dword ptr ss:[ebp-10] | [ebp-10]:"114420"
00421D1A | 8D 45 F4 | lea eax,dword ptr ss:[ebp-C] | [ebp-C]:"46-114420"
00421D1D | BA 03 00 00 00 | mov edx,3 | [ebp-c]存储姓名计算出的密码
00421D22 | E8 FD 16 FE FF | call | 1.sub_403424)
00421D27 | 8D 55 E8 | lea edx,dword ptr ss:[ebp-18] | [ebp-18]:"123456"
*/
//在程序运行到00421D27时[ebp-C]:"46-133490"中保存着注册码,hook 00421D27
//获取shellocde2的字节数
int i = 0;
char *temp = (char *)shellcode2;
while (true)
{
if (((char *)shellcode2)[i] == '\0' && ((char *)shellcode2)[i + 1] == '\0' &&
((char *)shellcode2)[i + 2] == '\0' && ((char *)shellcode2)[i + 3] == '\0' &&
((char *)shellcode2)[i + 4] == '\0' && ((char *)shellcode2)[i + 5] == '\0' &&
((char *)shellcode2)[i + 6] == '\0' && ((char *)shellcode2)[i + 7] == '\0')
{
break;
}
i++;
}
std::cout << i;
//申请代码空间
PVOID lpBuf = VirtualAllocEx(
ie_pi.hProcess, //句柄
NULL, //申请内存的地址(0是由系统分配地址)
i + 10, //申请字节个数
MEM_COMMIT, //内存状态(提交的,可以直接使用)
PAGE_EXECUTE_READWRITE); //内存属性(可读可写可执行)
std::cout << lpBuf;
//修改00421D1D处代码为 jmp lpBuf
char shellcode1[] = "\xE9\x00\x00\x00\x00";
//计算偏移
PVOID ptemp = (void *)GetNewAddress(hsrc, 0x21D27);
int temp1 = (int)lpBuf -(int) ptemp - 5;
//跳过开头的一些代码,可以使用裸函数,只不过编写有些麻烦
temp1 += 20;
std::cout << temp1;
//修改jmp中的偏移
memcpy(&shellcode1[1], &temp1, 4);
ptemp = (void *)GetNewAddress(hsrc, 0x21D27);
DWORD writeNumber = 0;
WriteProcessMemory(ie_pi.hProcess, ptemp, shellcode1, 5, &writeNumber);
//填充代码到申请的空间
WriteProcessMemory(ie_pi.hProcess, lpBuf, shellcode2, i + 1, &writeNumber);
//恢复进程
ResumeThread(ie_pi.hThread);
return 0;
}
源码
https://download.csdn.net/download/u012332009/11122063
源程序的分析请看
[反汇编练习] 160个CrackMe之044
(出处: 吾爱破解论坛)