注册机偷懒写法3、之内联Hook让程序自己弹出注册码

注册机偷懒写法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
(出处: 吾爱破解论坛)

你可能感兴趣的:(注册机偷懒写法3、之内联Hook让程序自己弹出注册码)