Example #1
0
LPVOID engine_HookFunctionInProcess(HANDLE hProcess,LPSTR lpModuleName,LPSTR lpFunctionName,LPVOID lpHookFunctionAddress,PDWORD pdwHookFunctionSize,LPVOID* lpFunctionAddress,INT iRndJmp)
{
	LPVOID lpModule=NULL;
	LPVOID lpFunction=NULL;
	MEMORY_BASIC_INFORMATION mbi;
	CHAR  lpTmpFunction[MAX_FUNC_LEN*2];
	CHAR  lpLocalStub[MAX_FUNC_LEN*3];
	CHAR  lpLocalFunc[MAX_FUNC_LEN*3];
	DWORD dwBytesRead;
	DWORD dwReadLen=0;
	DWORD dwExistingJMP=0;
	DWORD dwStubSize;
	DWORD dwFree=0;
	DWORD dwBytesWritten;
	DWORD dwOldProtect;

	LPVOID lpRemoteStub=NULL;
	INT   iFuncLen;
	PBYTE pReadAddress;
	NTSTATUS ntStatus;

	// Get module address
	lpModule=(LPVOID)engine_GetRemoteModuleHandle(hProcess,lpModuleName);
	if (!lpModule)
		return NULL;
		
	// Get function address
	lpFunction=engine_GetRemoteProcAddress(hProcess,lpModule,lpFunctionName);
	if (!lpFunction)
		return NULL;

	// Get info about the function address
	if (!NT_SUCCESS(SafeNtQueryVirtualMemory(hProcess,lpFunction,MemoryBasicInformation,&mbi,sizeof(mbi),NULL)))
		return NULL;

	// Flush instruction cache
	NtFlushInstructionCache(hProcess,mbi.BaseAddress,mbi.RegionSize);

	// Change the protection for the region
	if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,PAGE_EXECUTE_READWRITE,&mbi.Protect)))
		return NULL;

	// Fill stub buffer with nops
	RtlFillMemory(lpLocalStub,MAX_FUNC_LEN*3,NOP);

	// Read MAX_FUNC_LEN instruction(s) from the function into our function buffer
	if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpTmpFunction,MAX_FUNC_LEN*2,&dwBytesRead)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	pReadAddress=(PBYTE)lpTmpFunction;

	// check if first opcode in the function is a another jump
	if (*pReadAddress==LONG_JMP_OPCODE)
	{
		// get relative address
		memcpy(&dwExistingJMP,pReadAddress+1,4);
		// get absolute address
		dwExistingJMP=(DWORD)lpFunction+dwExistingJMP;
		// readlen
		dwReadLen=jtJmpTable[RELATIVE_JMP].iCodeSize

		engine_BuildJMPBuffer((CHAR*)lpLocalStub,((DWORD)lpRemoteStub+dwReadLen)-dwExistingJMP,RELATIVE_JMP);

		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Get the length of the first instruction(s)
	// This part is done by Z0MBiE's LDE32 v1.05
	iFuncLen=disasm_main(pReadAddress); // get first instruction length
	while (iFuncLen!=-1 && dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize)
	{
		dwReadLen+=iFuncLen;
		pReadAddress+=iFuncLen;
		iFuncLen=disasm_main(pReadAddress); // next instruction length
	}

	// API code is too short or too long too hook this way (for now ;))
	if (dwReadLen<(DWORD)jtJmpTable[iRndJmp].iCodeSize||dwReadLen>MAX_FUNC_LEN*2)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Read the first instruction(s) from the function into our stub buffer
	if (!NT_SUCCESS(SafeNtReadVirtualMemory(hProcess,lpFunction,lpLocalStub,dwReadLen,&dwBytesRead)))
	{	
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Allocate space with read/write access for our "stub"
	// note: always use a relative jump for our stub -> RELATIVE_JMP

	dwStubSize=dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize;
	if (!NT_SUCCESS(NtAllocateVirtualMemory(hProcess,&lpRemoteStub,0,&dwStubSize,MEM_COMMIT|MEM_TOP_DOWN,PAGE_READWRITE)))
	{	
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		return NULL;
	}

	// Check
	if (dwStubSize<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}

	engine_BuildJMPBuffer((CHAR*)lpLocalStub+dwReadLen,jtJmpTable[RELATIVE_JMP].jcStub((DWORD)lpFunction+dwReadLen,(DWORD)lpRemoteStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize),RELATIVE_JMP);

	// Copy the "stub" buffer to process memory
	if (!NT_SUCCESS(NtWriteVirtualMemory(hProcess,lpRemoteStub,lpLocalStub,dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize,&dwBytesWritten)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}

	// Check
	if (dwBytesWritten<dwReadLen+jtJmpTable[RELATIVE_JMP].iCodeSize)
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
	
	// change access
	if (!NT_SUCCESS(NtProtectVirtualMemory(hProcess,&lpRemoteStub,&dwStubSize,PAGE_EXECUTE_READ,&dwOldProtect)))
	{
		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
		
	// Fill it with NOP
	RtlFillMemory(lpLocalFunc,MAX_FUNC_LEN*3,NOP);

	// Prepare jmpcode
	engine_BuildJMPBuffer((CHAR*)lpLocalFunc,jtJmpTable[iRndJmp].jcFunc((DWORD)lpHookFunctionAddress,(DWORD)lpFunction,(DWORD)jtJmpTable[iRndJmp].iCodeSize),iRndJmp);
	
	ntStatus=NtWriteVirtualMemory(hProcess,lpFunction,lpLocalFunc,dwReadLen,&dwBytesWritten);
		
	// Check that we really wrote our jmpcode completely
	if (!NT_SUCCESS(ntStatus) || dwBytesWritten!=dwReadLen)
	{
		// Try to fix stuff
		if (dwBytesWritten)
			NtWriteVirtualMemory(hProcess,lpFunction,lpRemoteStub,dwBytesWritten,&dwBytesWritten);

		NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);
		
		// Free allocated buffer
		NtFreeVirtualMemory(hProcess,&lpRemoteStub,&dwFree,MEM_RELEASE);
		return NULL;
	}
	
	// Restore protection
	NtProtectVirtualMemory(hProcess,&mbi.BaseAddress,&mbi.RegionSize,mbi.Protect,NULL);

	// Save size of read function length
	if (pdwHookFunctionSize) *pdwHookFunctionSize=dwReadLen;
	// Save address of function
	if (lpFunctionAddress) *lpFunctionAddress=lpFunction;

	return lpRemoteStub;
}
Example #2
0
int main(int argc, char *argv[]) {
	if (argc < 2) {
		std::clog << "usage: " << (argc > 0 ? argv[0] : "btctool") << " <function> [<args>]\n" <<
				encode16_usage << '\n' << decode16_usage << '\n' <<
				encode64_usage << '\n' << decode64_usage << '\n' <<
				encode58_usage << '\n' << decode58_usage << '\n' <<
				disasm_usage << '\n' <<
				sha256_usage << '\n' << rmd160_usage << '\n' <<
				privkey_usage << '\n' << pubkey_usage << '\n' << address_usage << '\n' <<
				encrypt_usage << '\n' << decrypt_usage << '\n' <<
				privkeys_usage << '\n' << pubkeys_usage << '\n' << addresses_usage << std::endl;
		return -1;
	}
	--argc, ++argv;
	const char *f = argv[0];
	switch (f[0] | 0x20) {
		case '-': // -
			if (std::strcmp(f, "--version") == 0) { // --version
				std::clog << VERSION << std::endl;
				return 0;
			}
			break;
		case 'a': // a
			if ((f[1] | 0x20) == 'd' && (f[2] | 0x20) == 'd' && (f[3] | 0x20) == 'r' && (f[4] | 0x20) == 'e' && (f[5] | 0x20) == 's' && (f[6] | 0x20) == 's') { // address
				if (f[7] == '\0') { // address
					return address_main(argc, argv);
				}
				if ((f[7] | 0x20) == 'e' && (f[8] | 0x20) == 's' && f[9] == '\0') { // addresses
					return addresses_main(argc, argv);
				}
			}
			break;
		case 'd': // d
			switch (f[1] | 0x20) {
				case 'e': // de
					if ((f[2] | 0x20) == 'c') { // dec
						switch (f[3] | 0x20) {
							case 'o': // deco
								if ((f[4] | 0x20) == 'd' && (f[5] | 0x20) == 'e') { // decode
									switch (f[6]) {
										case '1': // decode1
											if (f[7] == '6' && f[8] == '\0') { // decode16
												return decode16_main(argc, argv);
											}
											break;
										case '5': // decode5
											if (f[7] == '8' && f[8] == '\0') { // decode58
												return decode58_main(argc, argv);
											}
											break;
										case '6': // decode6
											if (f[7] == '4' && f[8] == '\0') { // decode64
												return decode64_main(argc, argv);
											}
											break;
									}
								}
								break;
							case 'r': // decr
								if ((f[4] | 0x20) == 'y' && (f[5] | 0x20) == 'p' && (f[6] | 0x20) == 't' && f[7] == '\0') { // decrypt
									return decrypt_main(argc, argv);
								}
								break;
						}
					}
					break;
				case 'i': // di
					if ((f[2] | 0x20) == 's' && (f[3] | 0x20) == 'a' && (f[4] | 0x20) == 's' && (f[5] | 0x20) == 'm' && f[6] == '\0') { // disasm
						return disasm_main(argc, argv);
					}
					break;
			}
			break;
		case 'e': // e
			if ((f[1] | 0x20) == 'n' && (f[2] | 0x20) == 'c') { // enc
				switch (f[3] | 0x20) {
					case 'o': // enco
						if ((f[4] | 0x20) == 'd' && (f[5] | 0x20) == 'e') { // encode
							switch (f[6]) {
								case '1': // encode1
									if (f[7] == '6' && f[8] == '\0') { // encode16
										return encode16_main(argc, argv);
									}
									break;
								case '5': // encode5
									if (f[7] == '8' && f[8] == '\0') { // encode58
										return encode58_main(argc, argv);
									}
									break;
								case '6': // encode6
									if (f[7] == '4' && f[8] == '\0') { // encode64
										return encode64_main(argc, argv);
									}
									break;
							}
						}
						break;
					case 'r': // encr
						if ((f[4] | 0x20) == 'y' && (f[5] | 0x20) == 'p' && (f[6] | 0x20) == 't' && f[7] == '\0') { // encrypt
							return encrypt_main(argc, argv);
						}
						break;
				}
			}
			break;
		case 'p': // p
			switch (f[1] | 0x20) {
				case 'r': // pr
					if ((f[2] | 0x20) == 'i' && (f[3] | 0x20) == 'v' && (f[4] | 0x20) == 'k' && (f[5] | 0x20) == 'e' && (f[6] | 0x20) == 'y') { // privkey
						if (f[7] == '\0') { // privkey
							return privkey_main(argc, argv);
						}
						if ((f[7] | 0x20) == 's' && f[8] == '\0') { // privkeys
							return privkeys_main(argc, argv);
						}
					}
					break;
				case 'u': // pu
					if ((f[2] | 0x20) == 'b' && (f[3] | 0x20) == 'k' && (f[4] | 0x20) == 'e' && (f[5] | 0x20) == 'y') { // pubkey
						if (f[6] == '\0') { // pubkey
							return pubkey_main(argc, argv);
						}
						if ((f[6] | 0x20) == 's' && f[7] == '\0') { // pubkeys
							return pubkeys_main(argc, argv);
						}
					}
					break;
			}
			break;
		case 'r': // r
			if ((f[1] | 0x20) == 'm' && (f[2] | 0x20) == 'd' && f[3] == '1' && f[4] == '6' && f[5] == '0' && f[6] == '\0') { // rmd160
				return rmd160_main(argc, argv);
			}
			break;
		case 's': // s
			if ((f[1] | 0x20) == 'h' && (f[2] | 0x20) == 'a' && f[3] == '2' && f[4] == '5' && f[5] == '6' && f[6] == '\0') { // sha256
				return sha256_main(argc, argv);
			}
			break;
	}
	std::clog << "unknown function: " << f << std::endl;
	return -1;
}
Example #3
0
DWORD __cdecl disasm(DWORD,const BYTE* x)
{
  return disasm_main(x);
}