bool set_break_point( _In_ ch_param* param, _In_ DWORD_PTR address, _Out_ unsigned char* opcode ) { _ASSERTE(NULL != param); _ASSERTE(0 != address); _ASSERTE(NULL != opcode); if (NULL == param || 0 == address || NULL == opcode) return false; SIZE_T cb_rw = 0; unsigned char temp = 0; BOOL ret = ReadProcessMemory( param->hproc, (LPCVOID)address, &temp, sizeof(unsigned char), &cb_rw ); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); return false; } *opcode = temp; if (temp == BREAK_OPCODE) { log( "hprocess = 0x%08x, address =0x%p, breakpoint is already installed", param->hproc, address ); return true; } MEMORY_BASIC_INFORMATION mbi = { 0 }; if (0 == VirtualQueryEx( param->hproc, (LPCVOID)address, &mbi, sizeof(mbi))) { log( "VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError()); return false; } if (TRUE != VirtualProtectEx( param->hproc, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect)) { log( "VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ), gle = %u", param->hproc, mbi.BaseAddress, mbi.RegionSize, GetLastError() ); return false; } do { temp = BREAK_OPCODE; ret = WriteProcessMemory( param->hproc, (LPVOID)address, &temp, sizeof(unsigned char), &cb_rw); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); ret = FALSE; break; } if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char))) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); } } while (false); VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect); return (TRUE == ret) ? true : false; }
// from TitanEngine SDK - Property of ReversingLabs www.reversinglabs.com long long __stdcall hd_FindEx(HANDLE hProcess, LPVOID MemoryStart, DWORD MemorySize, LPVOID SearchPattern, DWORD PatternSize, LPBYTE WildCard) { /* Description: Searches for a specific pattern of bytes in a process. Syntax: long long FindEx( __in HANDLE hProcess, __in LPVOID MemoryStart, __in DWORD MemorySize, __in LPVOID SearchPattern, __in DWORD PatternSize, __in_opt WildCard ); Parameters: - Return value: - */ int i = NULL; int j = NULL; ULONG_PTR Return = NULL; LPVOID ueReadBuffer = NULL; PUCHAR SearchBuffer = NULL; PUCHAR CompareBuffer = NULL; MEMORY_BASIC_INFORMATION memoryInformation = {}; ULONG_PTR ueNumberOfBytesRead = NULL; LPVOID currentSearchPosition = NULL; DWORD currentSizeOfSearch = NULL; BYTE nWildCard = NULL; if(WildCard == NULL){WildCard = &nWildCard;} if(hProcess != NULL && MemoryStart != NULL && MemorySize != NULL){ if(hProcess != GetCurrentProcess()){ ueReadBuffer = VirtualAlloc(NULL, MemorySize, MEM_COMMIT, PAGE_READWRITE); if(!ReadProcessMemory(hProcess, MemoryStart, ueReadBuffer, MemorySize, &ueNumberOfBytesRead)){ if(ueNumberOfBytesRead == NULL){ if(VirtualQueryEx(hProcess, MemoryStart, &memoryInformation, sizeof memoryInformation) != NULL){ MemorySize = (DWORD)((ULONG_PTR)memoryInformation.BaseAddress + memoryInformation.RegionSize - (ULONG_PTR)MemoryStart); if(!ReadProcessMemory(hProcess, MemoryStart, ueReadBuffer, MemorySize, &ueNumberOfBytesRead)){ VirtualFree(ueReadBuffer, NULL, MEM_RELEASE); return(NULL); }else{ SearchBuffer = (PUCHAR)ueReadBuffer; } }else{ VirtualFree(ueReadBuffer, NULL, MEM_RELEASE); return(NULL); } }else{ SearchBuffer = (PUCHAR)ueReadBuffer; } }else{ SearchBuffer = (PUCHAR)ueReadBuffer; } }else{ SearchBuffer = (PUCHAR)MemoryStart; } __try{ CompareBuffer = (PUCHAR)SearchPattern; for(i = 0; i < (int)MemorySize && Return == NULL; i++){ for(j = 0; j < (int)PatternSize; j++){ if(CompareBuffer[j] != *(PUCHAR)WildCard && SearchBuffer[i + j] != CompareBuffer[j]){ break; } } if(j == (int)PatternSize){ Return = (ULONG_PTR)MemoryStart + i; } } VirtualFree(ueReadBuffer, NULL, MEM_RELEASE); return(Return); }__except(EXCEPTION_EXECUTE_HANDLER){ VirtualFree(ueReadBuffer, NULL, MEM_RELEASE); return(NULL); } }else{ return(NULL);
BOOL VMQuery(HANDLE hProcess, LPCVOID pvAddress, PVMQUERY pVMQ) { if (gs_dwAllocGran == 0) { // Set allocation granularity if this is the first call SYSTEM_INFO sinf; GetSystemInfo(&sinf); gs_dwAllocGran = sinf.dwAllocationGranularity; } ZeroMemory(pVMQ, sizeof(*pVMQ)); // Get the MEMORY_BASIC_INFORMATION for the passed address. MEMORY_BASIC_INFORMATION mbi; BOOL bOk = (VirtualQueryEx(hProcess, pvAddress, &mbi, sizeof(mbi)) == sizeof(mbi)); if (!bOk) return(bOk); // Bad memory address; return failure // The MEMORY_BASIC_INFORMATION structure contains valid information. // Time to start setting the members of our own VMQUERY structure. // First, fill in the block members. We'll fill the region members later. switch (mbi.State) { case MEM_FREE: // Free block (not reserved) pVMQ->pvBlkBaseAddress = NULL; pVMQ->BlkSize = 0; pVMQ->dwBlkProtection = 0; pVMQ->dwBlkStorage = MEM_FREE; break; case MEM_RESERVE: // Reserved block without committed storage in it. pVMQ->pvBlkBaseAddress = mbi.BaseAddress; pVMQ->BlkSize = mbi.RegionSize; // For an uncommitted block, mbi.Protect is invalid. So we will // show that the reserved block inherits the protection attribute // of the region in which it is contained. pVMQ->dwBlkProtection = mbi.AllocationProtect; pVMQ->dwBlkStorage = MEM_RESERVE; break; case MEM_COMMIT: // Reserved block with committed storage in it. pVMQ->pvBlkBaseAddress = mbi.BaseAddress; pVMQ->BlkSize = mbi.RegionSize; pVMQ->dwBlkProtection = mbi.Protect; pVMQ->dwBlkStorage = mbi.Type; break; default: DebugBreak(); break; } // Now fill in the region data members. VMQUERY_HELP VMQHelp; switch (mbi.State) { case MEM_FREE: // Free block (not reserved) pVMQ->pvRgnBaseAddress = mbi.BaseAddress; pVMQ->dwRgnProtection = mbi.AllocationProtect; pVMQ->RgnSize = mbi.RegionSize; pVMQ->dwRgnStorage = MEM_FREE; pVMQ->dwRgnBlocks = 0; pVMQ->dwRgnGuardBlks = 0; pVMQ->bRgnIsAStack = FALSE; break; case MEM_RESERVE: // Reserved block without committed storage in it. pVMQ->pvRgnBaseAddress = mbi.AllocationBase; pVMQ->dwRgnProtection = mbi.AllocationProtect; // Iterate through all blocks to get complete region information. VMQueryHelp(hProcess, pvAddress, &VMQHelp); pVMQ->RgnSize = VMQHelp.RgnSize; pVMQ->dwRgnStorage = VMQHelp.dwRgnStorage; pVMQ->dwRgnBlocks = VMQHelp.dwRgnBlocks; pVMQ->dwRgnGuardBlks = VMQHelp.dwRgnGuardBlks; pVMQ->bRgnIsAStack = VMQHelp.bRgnIsAStack; break; case MEM_COMMIT: // Reserved block with committed storage in it. pVMQ->pvRgnBaseAddress = mbi.AllocationBase; pVMQ->dwRgnProtection = mbi.AllocationProtect; // Iterate through all blocks to get complete region information. VMQueryHelp(hProcess, pvAddress, &VMQHelp); pVMQ->RgnSize = VMQHelp.RgnSize; pVMQ->dwRgnStorage = VMQHelp.dwRgnStorage; pVMQ->dwRgnBlocks = VMQHelp.dwRgnBlocks; pVMQ->dwRgnGuardBlks = VMQHelp.dwRgnGuardBlks; pVMQ->bRgnIsAStack = VMQHelp.bRgnIsAStack; break; default: DebugBreak(); break; } return(bOk); }
//bug fix: had endless loop if process exited after OpenProcess succeeded 7-23-16 dz int memMap(int pid, char* pth) { HANDLE hProcess; DWORD cbNeeded; int rv=0; hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, FALSE, pid ); if (NULL == hProcess){ printf("Error: failed to open process.."); return 1; } MEMORY_BASIC_INFORMATION mbi; long long va = 0; SIZE_T wErr; FILE* f = fopen(pth, "w"); char mod[500]; DWORD modLen=0; int i=0; if(f==NULL){ printf("Error: failed to open file %s", pth); return 1; } fprintf(f, "va, AllocationBase, Size, AllocationProtect, Type, Protect, State, ModuleFileName\r\n"); while(va < 0x000007FFFFFFFFFF)// x64 User Space Limit { wErr = VirtualQueryEx(hProcess, (LPCVOID)va, &mbi, sizeof(mbi)); if(mbi.State != MEM_FREE){ mod[0]=0; modLen=0; if(va > 0){ modLen = GetModuleFileNameExA(hProcess, (HMODULE)va, mod, 500); if(modLen==0) mod[0]=0; } fprintf(f, /*"%.16llX,%.16llX,%.16llX,%.8lX,%.8lX,%.8lX,%.8lX,%s\r\n",*/ "%llX,%llX,%llX,%lX,%lX,%lX,%lX,%s\r\n", va, mbi.AllocationBase, mbi.RegionSize, mbi.AllocationProtect, mbi.Type, mbi.Protect, mbi.State, mod); } if(!IsProcHandleValid(hProcess)) break; if(mbi.RegionSize < 1) break; va += mbi.RegionSize; //printf("%d) %.16llX\r\n", i++, va); /*if(va >= 0x000007FFFFFFFFFF) { break; }*/ } fclose(f); return 0; }
bool WINAPI CreateMemoryProcess( LPVOID lpImage, char* pPath ) { // Variables for Process Forking ///////////////////////////////////////////////////////////////// DWORD lWritten; DWORD lImageSize; DWORD lImageBase; DWORD lImageHeaderSize; DWORD lFirstSection; DWORD lJumpSize = 0; DWORD lSectionCount; DWORD lSectionSize; DWORD lPreviousProtection; LPVOID lpImageMemory; IMAGE_DOS_HEADER dsDosHeader; IMAGE_NT_HEADERS ntNtHeader; IMAGE_SECTION_HEADER shSections[512 * 2]; PROCESS_INFORMATION piProcessInformation; STARTUPINFO suStartUpInformation; CONTEXT cContext; DWORD lProccessBaseAdress; DWORD lProccessImageSize; char* pProcessName; bool bIsNewProccessName = false; bool bReturnValue = false; ///////////////////////////////////////////////////////////////// // End Variable Definition if(strlen(pPath) == 0) { // No process name is set. Trying to fork this process pProcessName = new char[MAX_PATH]; ZeroMemory(pProcessName, MAX_PATH); bIsNewProccessName = true; #ifdef CPDEBUG printf("Trying to fork same process file\n"); #endif // Get the file name for the dummy process if(GetModuleFileName(NULL, pProcessName, MAX_PATH) == 0) { #ifdef CPDEBUG printf("Error: Can't recive GetModuleFileName() from proccess.\n"); #endif delete [] pProcessName; return bReturnValue; } } else { pProcessName = pPath; } #ifdef CPDEBUG printf("Using %s for injection\n", pProcessName); #endif // Grab the DOS Headers memcpy(&dsDosHeader, lpImage, sizeof(dsDosHeader)); if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE) { #ifdef CPDEBUG printf("Error: File DOS header wrong\n"); #endif if(bIsNewProccessName) delete [] pProcessName; return false; } // Grab NT Headers memcpy(&ntNtHeader, (LPVOID)((DWORD)lpImage + dsDosHeader.e_lfanew), sizeof(ntNtHeader)); if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE) { #ifdef CPDEBUG printf("Error: No NT Signature finded.\n"); #endif if(bIsNewProccessName) delete [] pProcessName; return false; } // Get Size and Image Base lImageBase = ntNtHeader.OptionalHeader.ImageBase; lImageSize = ntNtHeader.OptionalHeader.SizeOfImage; lImageHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders; #ifdef CPDEBUG printf("New image base = %X\n", lImageBase); printf("New image size = %d\n", lImageSize); printf("New image header size = %d\n", lImageHeaderSize); #endif // Allocate memory for image lpImageMemory = new LPVOID[lImageSize]; ZeroMemory(lpImageMemory, lImageSize); lFirstSection = (DWORD)(((DWORD)lpImage + dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS)); memcpy(shSections, (LPVOID)(lFirstSection), sizeof(IMAGE_SECTION_HEADER) * ntNtHeader.FileHeader.NumberOfSections); #ifdef CPDEBUG printf("%d header sections founded\n", ntNtHeader.FileHeader.NumberOfSections); #endif memcpy(lpImageMemory, lpImage, lImageHeaderSize); // Get Section Alignment if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders; } else { lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders / ntNtHeader.OptionalHeader.SectionAlignment; lJumpSize += 1; lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment; } LPVOID lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemory + lJumpSize); // Copy Sections To Buffer for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++) { lJumpSize = 0; lSectionSize = shSections[lSectionCount].SizeOfRawData; memcpy(lpImageMemoryDummy, (LPVOID)((DWORD)lpImage + shSections[lSectionCount].PointerToRawData), lSectionSize); if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment) == 0) { lJumpSize = shSections[lSectionCount].Misc.VirtualSize; } else { lJumpSize = shSections[lSectionCount].Misc.VirtualSize / ntNtHeader.OptionalHeader.SectionAlignment; lJumpSize += 1; lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment; } lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemoryDummy + lJumpSize); } ZeroMemory(&suStartUpInformation, sizeof(STARTUPINFO)); ZeroMemory(&piProcessInformation, sizeof(PROCESS_INFORMATION)); ZeroMemory(&cContext, sizeof(CONTEXT)); suStartUpInformation.cb = sizeof(suStartUpInformation); // Create Process if(CreateProcess( NULL, pProcessName, NULL, NULL, false, CREATE_SUSPENDED, NULL, NULL, &suStartUpInformation, &piProcessInformation )) { #ifdef CPDEBUG printf("Proccess suspended\n"); #endif cContext.ContextFlags = CONTEXT_FULL; if(!GetThreadContext(piProcessInformation.hThread,&cContext)) { #ifdef CPDEBUG printf("Fail to get context of suspended proccess.\n"); #endif TerminateProcess(piProcessInformation.hProcess, 0); if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; return false; return true; } DWORD *pEbxInfo = (DWORD *)cContext.Ebx; DWORD read; ReadProcessMemory( piProcessInformation.hProcess, &pEbxInfo[2], (LPVOID)&lProccessBaseAdress, sizeof(DWORD), &read ); DWORD curAddr = lProccessBaseAdress; MEMORY_BASIC_INFORMATION memInfo; while(VirtualQueryEx( piProcessInformation.hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo)) ) { if(memInfo.State == MEM_FREE) break; curAddr += memInfo.RegionSize; } lProccessImageSize = (DWORD)curAddr - (DWORD)lProccessBaseAdress; #ifdef CPDEBUG printf("Current image base adress = %X\n", lProccessBaseAdress); printf("Current image size = %d\n", lProccessImageSize); #endif // Check image base and image size if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize) { // we can load new image to same place #ifdef CPDEBUG printf("Using same image place\n"); #endif VirtualProtectEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, PAGE_EXECUTE_READWRITE, (DWORD*)&lPreviousProtection ); } else { // We can't use same place, allocate memory for it. #ifdef CPDEBUG printf("Allocation place for new image\n"); #endif if(NtUnmapViewOfSection( piProcessInformation.hProcess, (LPVOID)lProccessBaseAdress ) == 0) { #ifdef CPDEBUG printf("Old section unmaped\n"); #endif LPVOID lpIsAllocated = VirtualAllocEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if(lpIsAllocated) { #ifdef CPDEBUG printf("Memory allocated successful\n"); #endif } else { #ifdef CPDEBUG printf("Error: Can't allocated\n"); #endif } } else { #ifdef CPDEBUG printf("Error: Can't unmap old section\n"); #endif } } // Write Image to Process if(WriteProcessMemory( piProcessInformation.hProcess, (LPVOID)lImageBase, lpImageMemory, lImageSize, (DWORD*)&lWritten )) { bReturnValue = true; #ifdef CPDEBUG printf("New image writen\n"); #endif } else { #ifdef CPDEBUG printf("Error: New image written error.\n"); #endif } // Set Image Base if(WriteProcessMemory( piProcessInformation.hProcess, (LPVOID)((DWORD)cContext.Ebx + 8), &lImageBase, 4, (DWORD*)&lWritten) ) { #ifdef CPDEBUG printf("Updated init point\n"); #endif } else { bReturnValue = false; #ifdef CPDEBUG printf("Error: Can't update init point\n"); #endif } if(!bReturnValue) { #ifdef CPDEBUG printf("Error: Error during image rewriting. Exit.\n"); #endif TerminateProcess(piProcessInformation.hProcess, 0); if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; return false; } // Set the new entry point cContext.Eax = lImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint; SetThreadContext( piProcessInformation.hThread, &cContext ); if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize) { #ifdef CPDEBUG printf("Returning old protection for new image.\n"); #endif VirtualProtectEx( piProcessInformation.hProcess, (LPVOID)lImageBase, lImageSize, lPreviousProtection, 0 ); } // Resume the process ResumeThread(piProcessInformation.hThread); } else { #ifdef CPDEBUG printf("Error: Can't start %s\n", pProcessName); #endif return false; } if(bIsNewProccessName) delete [] pProcessName; delete [] lpImageMemory; if(bReturnValue) { #ifdef CPDEBUG printf("Successful injected. No errors during doing this.\n"); #endif } return bReturnValue; }
/**************************************************************************** * GetModuleBase * *---------------* * Description: * Helper for imagehlp's StackWalk API. Retrieves the base address of * the module containing the giving virtual address. * * NOTE: If the module information for the given module hasnot yet been * loaded, then it is loaded on this call. * * Return: * Base virtual address where the module containing ReturnAddress is * loaded, or 0 if the address cannot be determined. ****************************************************************************/ DWORD_PTR __stdcall GetModuleBase ( HANDLE hProcess, DWORD_PTR dwAddr ) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; PLAT_IMAGEHLP_MODULE ModuleInfo; ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); if (_SymGetModuleInfo(hProcess, dwAddr, &ModuleInfo)) { return ModuleInfo.BaseOfImage; } else { MEMORY_BASIC_INFORMATION mbi; if (VirtualQueryEx(hProcess, (LPVOID)dwAddr, &mbi, sizeof(mbi))) { if (mbi.Type & MEM_IMAGE) { char achFile[MAX_LONGPATH] = {0}; DWORD cch; cch = GetModuleFileNameA( (HINSTANCE)mbi.AllocationBase, achFile, MAX_LONGPATH); // Ignore the return code since we can't do anything with it. _SymLoadModule( hProcess, NULL, ((cch) ? achFile : NULL), NULL, (DWORD_PTR)mbi.AllocationBase, 0); return (DWORD_PTR)mbi.AllocationBase; } } } #if defined(_WIN64) if (_GetRuntimeStackWalkInfo == NULL) { _GetRuntimeStackWalkInfo = (pfn_GetRuntimeStackWalkInfo) GetProcAddress(GetCLRModuleHack(), "GetRuntimeStackWalkInfo"); if (_GetRuntimeStackWalkInfo == NULL) return NULL; } DWORD_PTR moduleBase; _GetRuntimeStackWalkInfo((ULONG64)dwAddr, (UINT_PTR*)&moduleBase, NULL); if (moduleBase != NULL) return moduleBase; #endif // _WIN64 return 0; }
BOOL Scan4Key(BYTE *PrivateKeyClient_01, BYTE *PrivateKeyClient_02, BYTE *PrivateKeyClient_03, BYTE *PrivateKeyClient_04) { DWORD i; DWORD Limit = 0x80000000; //0xC0000000 : 0x80000000; MEMORY_BASIC_INFORMATION MemInfo; HANDLE hProc = GetCurrentProcess(); SIZE_T sRet; DWORD PageCount; DWORD j, k; //BYTE *bData = NULL; struct CKey *ckey = NULL; BYTE PageBuffer[0x1000]; SIZE_T BytesRead = 0; //DWORD OldProtect; i = 0x2389000; for (i = 0x0; i < Limit; i++) { sRet = VirtualQueryEx(hProc, (LPCVOID)i, &MemInfo, sizeof(MemInfo)); if (sRet == 0 || MemInfo.State == MEM_FREE || MemInfo.State == MEM_RESERVE || (MemInfo.Protect & PAGE_READONLY) != 0 || (MemInfo.Protect & PAGE_GUARD) != 0 || (MemInfo.Protect & PAGE_EXECUTE) != 0 || (MemInfo.Protect & PAGE_NOACCESS) != 0) { if (sRet == 0) { i += 0x1000; } else { i += MemInfo.RegionSize; } continue; } PageCount = MemInfo.RegionSize / 0x1000; for (j = 0; j < PageCount; j++) { /*sRet = VirtualQueryEx(hProc, (LPCVOID)(i + j * 0x1000), &MemInfo, sizeof(MemInfo)); if ((MemInfo.Protect & PAGE_READONLY) != 0 || (MemInfo.Protect & PAGE_GUARD) != 0) continue;*/ //if (!VirtualProtect((LPVOID)(i + j * 0x1000), 0x1000, PAGE_EXECUTE_READWRITE, &OldProtect)) //continue; //printf("Working on %08X\n", (LPVOID)(i + j * 0x1000)); //Sleep(10); if (ReadProcessMemory(hProc, (LPCVOID)(i + j * 0x1000), PageBuffer, sizeof(PageBuffer), &BytesRead) && BytesRead != 0) { //memcpy_s(PageBuffer, sizeof(PageBuffer), (LPVOID)(i + j * 0x1000), 1); //Sleep(10); for (k = 0; k < (0x1000 - SIZE_PATTERN_KEY); k++) { ckey = (struct CKey *)(PageBuffer + k); if (ckey->dwKeyPubSize_01 == 0x80 && ckey->dwKeyPrivSize_01 == 0x14 && ckey->dwKeyPubSize_02 == 0x80 && ckey->dwKeyPrivSize_02 == 0x14 && ckey->dwKeyPubSize_03 == 0x80 && ckey->dwKeyPrivSize_03 == 0x14 && ckey->dwKeyPubSize_04 == 0x80 && ckey->dwKeyPrivSize_04 == 0x14 && ckey->dwKeyPubSize_05 == 0x80 && ckey->dwKeyPrivSize_05 == 0x14) { dbg_msg("[+] FOUND at %08X!\n", (DWORD)(i + j * 0x1000)); DumpKeys(ckey); memcpy(PrivateKeyClient_01, ckey->bKeyPriv_01, 0x14); memcpy(PrivateKeyClient_02, ckey->bKeyPriv_02, 0x14); memcpy(PrivateKeyClient_03, ckey->bKeyPriv_03, 0x14); memcpy(PrivateKeyClient_04, ckey->bKeyPriv_04, 0x14); return TRUE; } //bData += 1; } //VirtualProtect((LPVOID)(i + j * 0x1000), 0x1000, OldProtect, &OldProtect); } } i += 0x1000 * PageCount; } return FALSE; }
int yr_process_get_memory( int pid, YR_MEMORY_BLOCK** first_block) { PVOID address; SIZE_T read; unsigned char* data; int result = ERROR_SUCCESS; SYSTEM_INFO si; MEMORY_BASIC_INFORMATION mbi; YR_MEMORY_BLOCK* new_block; YR_MEMORY_BLOCK* current_block = NULL; TOKEN_PRIVILEGES tokenPriv; LUID luidDebug; HANDLE hProcess = NULL; HANDLE hToken = NULL; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) && LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug)) { tokenPriv.PrivilegeCount = 1; tokenPriv.Privileges[0].Luid = luidDebug; tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges( hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL); } hProcess = OpenProcess( PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid); *first_block = NULL; if (hProcess == NULL) { if (hToken != NULL) CloseHandle(hToken); return ERROR_COULD_NOT_ATTACH_TO_PROCESS; } GetSystemInfo(&si); address = si.lpMinimumApplicationAddress; while (address < si.lpMaximumApplicationAddress && VirtualQueryEx(hProcess, address, &mbi, sizeof(mbi)) != 0) { if (mbi.State == MEM_COMMIT && ((mbi.Protect & PAGE_NOACCESS) == 0)) { data = (unsigned char*) yr_malloc(mbi.RegionSize); if (data == NULL) { result = ERROR_INSUFICIENT_MEMORY; break; } if (ReadProcessMemory( hProcess, mbi.BaseAddress, data, mbi.RegionSize, &read)) { new_block = (YR_MEMORY_BLOCK*) yr_malloc(sizeof(YR_MEMORY_BLOCK)); if (new_block == NULL) { yr_free(data); result = ERROR_INSUFICIENT_MEMORY; break; } if (*first_block == NULL) *first_block = new_block; new_block->base = (size_t) mbi.BaseAddress; new_block->size = mbi.RegionSize; new_block->data = data; new_block->next = NULL; if (current_block != NULL) current_block->next = new_block; current_block = new_block; } else { yr_free(data); } } address = (PVOID)((ULONG_PTR) mbi.BaseAddress + mbi.RegionSize); } if (hToken != NULL) CloseHandle(hToken); if (hProcess != NULL) CloseHandle(hProcess); return result; }
int main(void) { // how can we know the number of process DWORD aProcessIds[1024]; DWORD cResultSize; // enumProcess if (!EnumProcesses(aProcessIds, sizeof (aProcessIds), &cResultSize)) { DWORD err = GetLastError(); _ftprintf(stderr, TEXT("ERROR: can't enum processes: %lu\n"), err); return 1; } DWORD cNbProcess = cResultSize / sizeof (DWORD); // iter on them for (DWORD i = 0; i < cNbProcess; ++i) { // OpenProcess DWORD dProcessId = aProcessIds[i]; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dProcessId); if (!hProcess) { DWORD err = GetLastError(); _ftprintf(stderr, TEXT("ERROR: can't open Process with pid %lu: %lu\n"), dProcessId, err); continue; } TCHAR tmpFileName[MAX_PATH] = { 0 }; PTCHAR szFileName = NULL; if (!GetModuleFileNameEx(hProcess, 0, szFileName, sizeof(szFileName)/sizeof(TCHAR))) { DWORD err = GetLastError(); _ftprintf(stderr, TEXT("ERROR: can't get module name for pid %lu: %lu\n"), dProcessId, err); szFileName = TEXT("<unknown>"); } else { szFileName = tmpFileName; } // Iterate on pages long unsigned int p = 0; MEMORY_BASIC_INFORMATION info; while (1) { // prevent overflow on MmUserProbeAddress if (p >= (long unsigned int)0x7FFF0000) break; SIZE_T tmp = VirtualQueryEx(hProcess, (LPCVOID)p, &info, sizeof (info)); if (!tmp) { DWORD err = GetLastError(); _ftprintf(stderr, TEXT("ERROR: can't query virtual information for pid %lu in address %p: %lu\n"), dProcessId, (LPCVOID)p, err); break; } // stop when we didn't read the page information if (sizeof (info) != tmp) break; printline(hProcess, dProcessId, szFileName, &info); p += info.RegionSize; } CloseHandle(hProcess); } return 0; }
int DispatchCommand(int currentsocket, unsigned char command) { int r; switch (command) { case CMD_GETVERSION: { PCeVersion v; int versionsize=strlen(versionstring); v=(PCeVersion)malloc(sizeof(CeVersion)+versionsize); v->stringsize=versionsize; v->version=1; memcpy((char *)v+sizeof(CeVersion), versionstring, versionsize); //version request sendall(currentsocket, v, sizeof(CeVersion)+versionsize, 0); free(v); break; } case CMD_GETARCHITECTURE: { #ifdef __i386__ unsigned char arch=0; #endif #ifdef __x86_64__ unsigned char arch=1; #endif #ifdef __arm__ unsigned char arch=2; #endif #ifdef __aarch64__ unsigned char arch=3; #endif sendall(currentsocket, &arch, sizeof(arch), 0); break; } case CMD_CLOSECONNECTION: { printf("Connection %d closed properly\n", currentsocket); fflush(stdout); close(currentsocket); return NULL; } case CMD_TERMINATESERVER: { printf("Command to terminate the server received\n"); fflush(stdout); close(currentsocket); exit(0); } case CMD_STARTDEBUG: { HANDLE h; if (recvall(currentsocket, &h, sizeof(h), MSG_WAITALL)>0) { int r; printf("Calling StartDebug(%d)\n", h); r=StartDebug(h); sendall(currentsocket, &r, sizeof(r), 0); if (r) { isDebuggerThread=1; debugfd=GetDebugPort(h); } } break; } case CMD_WAITFORDEBUGEVENT: { struct { HANDLE pHandle; int timeout; } wfd; if (recvall(currentsocket, &wfd, sizeof(wfd), MSG_WAITALL)>0) { int r; DebugEvent event; memset(&event, 0, sizeof(event)); r=WaitForDebugEvent(wfd.pHandle, &event, wfd.timeout); sendall(currentsocket, &r, sizeof(r), r?MSG_MORE:0); if (r) { if (event.debugevent==SIGTRAP) { printf("!!!SIGTRAP!!!\n"); printf("event.address=%llx\n", event.address); } sendall(currentsocket, &event, sizeof(event),0); } } break; } case CMD_CONTINUEFROMDEBUGEVENT: { struct { HANDLE pHandle; int tid; int ignore; } cfd; if (recvall(currentsocket, &cfd, sizeof(cfd), MSG_WAITALL)>0) { int r; // Calling ContinueFromDebugEvent r=ContinueFromDebugEvent(cfd.pHandle, cfd.tid, cfd.ignore); // Returned from ContinueFromDebugEvent sendall(currentsocket, &r, sizeof(r), 0); } break; } case CMD_SETBREAKPOINT: { CeSetBreapointInput sb; printf("CMD_SETBREAKPOINT. sizeof(sb)=%d\n", sizeof(sb)); if (recvall(currentsocket, &sb, sizeof(sb), MSG_WAITALL)>0) { int r; printf("Calling SetBreakpoint\n"); r=SetBreakpoint(sb.hProcess, sb.tid, sb.debugreg, (void *)sb.Address, sb.bptype, sb.bpsize); printf("SetBreakpoint returned %d\n",r); sendall(currentsocket, &r, sizeof(r), 0); } break; } case CMD_REMOVEBREAKPOINT: { CeRemoveBreapointInput rb; if (recvall(currentsocket, &rb, sizeof(rb), MSG_WAITALL)>0) { int r; printf("Calling RemoveBreakpoint\n"); r=RemoveBreakpoint(rb.hProcess, rb.tid, rb.debugreg, rb.wasWatchpoint); printf("RemoveBreakpoint returned: %d\n", r); sendall(currentsocket, &r, sizeof(r), 0); } break; } case CMD_GETTHREADCONTEXT: { #pragma pack(1) struct { HANDLE hProcess; int tid; int type; } gtc; #pragma pack() CONTEXT Context; int result; printf("CMD_GETTHREADCONTEXT:\n"); recvall(currentsocket, >c, sizeof(gtc), MSG_WAITALL); printf("Going to call GetThreadContext(%d, %d, %p, %d)\n", gtc.hProcess, gtc.tid, &Context, gtc.type); memset(&Context, 0, sizeof(Context)); result=GetThreadContext(gtc.hProcess, gtc.tid, &Context, gtc.type); printf("result=%d\n", result); if (result) { uint32_t structsize=sizeof(Context); sendall(currentsocket, &result, sizeof(result), MSG_MORE); sendall(currentsocket, &structsize, sizeof(structsize), MSG_MORE); sendall(currentsocket, &Context, structsize, 0); //and context } else sendall(currentsocket, &result, sizeof(result), 0); break; } case CMD_SUSPENDTHREAD: { CeSuspendThreadInput st; if (recvall(currentsocket, &st, sizeof(st), MSG_WAITALL)>0) { int r; printf("Calling SuspendThread\n"); r=SuspendThread(st.hProcess, st.tid); printf("SuspendThread returned\n"); sendall(currentsocket, &r, sizeof(r), 0); } break; } case CMD_RESUMETHREAD: { CeResumeThreadInput rt; if (recvall(currentsocket, &rt, sizeof(rt), MSG_WAITALL)>0) { int r; printf("Calling ResumeThread\n"); r=ResumeThread(rt.hProcess, rt.tid); printf("ResumeThread returned\n"); sendall(currentsocket, &r, sizeof(r), 0); } break; } case CMD_CLOSEHANDLE: { HANDLE h; if (recvall(currentsocket, &h, sizeof(h), MSG_WAITALL)>0) { CloseHandle(h); int r=1; sendall(currentsocket, &r, sizeof(r), 0); //stupid naggle } else { printf("Error during read for CMD_CLOSEHANDLE\n"); close(currentsocket); fflush(stdout); return 0; } break; } case CMD_CREATETOOLHELP32SNAPSHOT: { CeCreateToolhelp32Snapshot params; HANDLE result; printf("CMD_CREATETOOLHELP32SNAPSHOT\n"); if (recvall(currentsocket, ¶ms, sizeof(CeCreateToolhelp32Snapshot), MSG_WAITALL) > 0) { printf("Calling CreateToolhelp32Snapshot\n"); result=CreateToolhelp32Snapshot(params.dwFlags, params.th32ProcessID); printf("result of CreateToolhelp32Snapshot=%d\n", result); fflush(stdout); sendall(currentsocket, &result, sizeof(HANDLE), 0); } else { printf("Error during read for CMD_CREATETOOLHELP32SNAPSHOT\n"); fflush(stdout); close(currentsocket); return 0; } break; } case CMD_MODULE32FIRST: //slightly obsolete now case CMD_MODULE32NEXT: { HANDLE toolhelpsnapshot; if (recvall(currentsocket, &toolhelpsnapshot, sizeof(toolhelpsnapshot), MSG_WAITALL) >0) { BOOL result; ModuleListEntry me; CeModuleEntry *r; int size; if (command==CMD_MODULE32FIRST) result=Module32First(toolhelpsnapshot, &me); else result=Module32Next(toolhelpsnapshot, &me); if (result) { size=sizeof(CeModuleEntry)+ strlen(me.moduleName); r=(PCeModuleEntry)malloc(size); r->modulebase=me.baseAddress; r->modulesize=me.moduleSize; r->modulenamesize=strlen(me.moduleName); // Sending %s size %x\n, me.moduleName, r->modulesize memcpy((char *)r+sizeof(CeModuleEntry), me.moduleName, r->modulenamesize); } else { size=sizeof(CeModuleEntry); r=(PCeModuleEntry)malloc(size); r->modulebase=0; r->modulesize=0; r->modulenamesize=0; } r->result=result; sendall(currentsocket, r, size, 0); free(r); } break; } case CMD_PROCESS32FIRST: //obsolete case CMD_PROCESS32NEXT: { HANDLE toolhelpsnapshot; if (recvall(currentsocket, &toolhelpsnapshot, sizeof(toolhelpsnapshot), MSG_WAITALL) >0) { ProcessListEntry pe; BOOL result; CeProcessEntry *r; int size; if (command==CMD_PROCESS32FIRST) result=Process32First(toolhelpsnapshot, &pe); else result=Process32Next(toolhelpsnapshot, &pe); // printf("result=%d\n", result); if (result) { size=sizeof(CeProcessEntry)+ strlen(pe.ProcessName); r=(PCeProcessEntry)malloc(size); r->processnamesize=strlen(pe.ProcessName); r->pid=pe.PID; memcpy((char *)r+sizeof(CeProcessEntry), pe.ProcessName, r->processnamesize); } else { size=sizeof(CeProcessEntry); r=(PCeProcessEntry)malloc(size); r->processnamesize=0; r->pid=0; } r->result=result; sendall(currentsocket, r, size, 0); free(r); } break; } case CMD_READPROCESSMEMORY: { CeReadProcessMemoryInput c; r=recvall(currentsocket, &c, sizeof(c), MSG_WAITALL); if (r>0) { PCeReadProcessMemoryOutput o=NULL; o=(PCeReadProcessMemoryOutput)malloc(sizeof(CeReadProcessMemoryOutput)+c.size); o->read=ReadProcessMemory(c.handle, (void *)(uintptr_t)c.address, &o[1], c.size); if (c.compress) { //compress the output #define COMPRESS_BLOCKSIZE (64*1024) int i; unsigned char *uncompressed=&o[1]; uint32_t uncompressedSize=o->read; uint32_t compressedSize=0; int maxBlocks=1+(c.size / COMPRESS_BLOCKSIZE); unsigned char **compressedBlocks=malloc(maxBlocks*sizeof(unsigned char *) ); //send in blocks of 64kb and reallocate the pointerblock if there's not enough space int currentBlock=0; z_stream strm; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; deflateInit(&strm, c.compress); compressedBlocks[currentBlock]=malloc(COMPRESS_BLOCKSIZE); strm.avail_out=COMPRESS_BLOCKSIZE; strm.next_out=compressedBlocks[currentBlock]; strm.next_in=uncompressed; strm.avail_in=uncompressedSize; while (strm.avail_in) { r=deflate(&strm, Z_NO_FLUSH); if (r!=Z_OK) { if (r==Z_STREAM_END) break; else { printf("Error while compressing\n"); break; } } if (strm.avail_out==0) { //new output block currentBlock++; if (currentBlock>=maxBlocks) { //list was too short, reallocate printf("Need to realloc the pointerlist (p1)\n"); maxBlocks*=2; compressedBlocks=realloc(compressedBlocks, maxBlocks*sizeof(unsigned char*)); } compressedBlocks[currentBlock]=malloc(COMPRESS_BLOCKSIZE); strm.avail_out=COMPRESS_BLOCKSIZE; strm.next_out=compressedBlocks[currentBlock]; } } // finishing compressiong while (1) { r=deflate(&strm, Z_FINISH); if (r==Z_STREAM_END) break; //done if (r!=Z_OK) { printf("Failure while finishing compression:%d\n", r); break; } if (strm.avail_out==0) { //new output block currentBlock++; if (currentBlock>=maxBlocks) { //list was too short, reallocate printf("Need to realloc the pointerlist (p2)\n"); maxBlocks*=2; compressedBlocks=realloc(compressedBlocks, maxBlocks*sizeof(unsigned char*)); } compressedBlocks[currentBlock]=malloc(COMPRESS_BLOCKSIZE); strm.avail_out=COMPRESS_BLOCKSIZE; strm.next_out=compressedBlocks[currentBlock]; } } deflateEnd(&strm); compressedSize=strm.total_out; // Sending compressed data sendall(currentsocket, &uncompressedSize, sizeof(uncompressedSize), MSG_MORE); //followed by the compressed size sendall(currentsocket, &compressedSize, sizeof(compressedSize), MSG_MORE); //the compressed data follows for (i=0; i<=currentBlock; i++) { if (i!=currentBlock) sendall(currentsocket, compressedBlocks[i], COMPRESS_BLOCKSIZE, MSG_MORE); else sendall(currentsocket, compressedBlocks[i], COMPRESS_BLOCKSIZE-strm.avail_out, 0); //last one, flush free(compressedBlocks[i]); } free(compressedBlocks); } else sendall(currentsocket, o, sizeof(CeReadProcessMemoryOutput)+o->read, 0); if (o) free(o); } break; } case CMD_WRITEPROCESSMEMORY: { CeWriteProcessMemoryInput c; printf("CMD_WRITEPROCESSMEMORY:\n"); r=recvall(currentsocket, &c, sizeof(c), MSG_WAITALL); if (r>0) { CeWriteProcessMemoryOutput o; unsigned char *buf; printf("recv returned %d bytes\n", r); printf("c.size=%d\n", c.size); if (c.size) { buf=(unsigned char *)malloc(c.size); r=recvall(currentsocket, buf, c.size, MSG_WAITALL); if (r>0) { printf("received %d bytes for the buffer. Wanted %d\n", r, c.size); o.written=WriteProcessMemory(c.handle, (void *)(uintptr_t)c.address, buf, c.size); r=sendall(currentsocket, &o, sizeof(CeWriteProcessMemoryOutput), 0); printf("wpm: returned %d bytes to caller\n", r); } else printf("wpm recv error while reading the data\n"); free(buf); } else { printf("wpm with a size of 0 bytes"); o.written=0; r=sendall(currentsocket, &o, sizeof(CeWriteProcessMemoryOutput), 0); printf("wpm: returned %d bytes to caller\n", r); } } else { printf("RPM: recv failed\n"); } break; } case CMD_VIRTUALQUERYEXFULL: { CeVirtualQueryExFullInput c; CeVirtualQueryExFullOutput o; r=recvall(currentsocket, &c, sizeof(c), MSG_WAITALL); if (r>0) { RegionInfo *rinfo=NULL; uint32_t count=0; if (VirtualQueryExFull(c.handle, c.flags, &rinfo, &count)) { int i; sendall(currentsocket, &count, sizeof(count),0); for (i=0; i<count; i++) sendall(currentsocket, &rinfo[i], sizeof(RegionInfo),0); if (rinfo) free(rinfo); } } break; } case CMD_GETREGIONINFO: case CMD_VIRTUALQUERYEX: { CeVirtualQueryExInput c; r=recvall(currentsocket, &c, sizeof(c), MSG_WAITALL); if (r>0) { RegionInfo rinfo; CeVirtualQueryExOutput o; if (sizeof(uintptr_t)==4) { if (c.baseaddress>0xFFFFFFFF) { o.result=0; sendall(currentsocket, &o, sizeof(o), 0); break; } } char mapsline[200]; if (command==CMD_VIRTUALQUERYEX) o.result=VirtualQueryEx(c.handle, (void *)(uintptr_t)c.baseaddress, &rinfo, NULL); else if (command==CMD_GETREGIONINFO) o.result=VirtualQueryEx(c.handle, (void *)(uintptr_t)c.baseaddress, &rinfo, mapsline); o.protection=rinfo.protection; o.baseaddress=rinfo.baseaddress; o.type=rinfo.type; o.size=rinfo.size; if (command==CMD_VIRTUALQUERYEX) sendall(currentsocket, &o, sizeof(o), 0); else if (command==CMD_GETREGIONINFO) { sendall(currentsocket, &o, sizeof(o), MSG_MORE); { uint8_t size=strlen(mapsline); sendall(currentsocket, &size, sizeof(size), MSG_MORE); sendall(currentsocket, mapsline, size, 0); } } } break; } case CMD_OPENPROCESS: { int pid=0; r=recvall(currentsocket, &pid, sizeof(int), MSG_WAITALL); if (r>0) { int processhandle; printf("OpenProcess(%d)\n", pid); processhandle=OpenProcess(pid); printf("processhandle=%d\n", processhandle); sendall(currentsocket, &processhandle, sizeof(int), 0); } else { printf("Error\n"); fflush(stdout); close(currentsocket); return NULL; } break; } case CMD_GETSYMBOLLISTFROMFILE: { //get the list and send it to the client //zip it first uint32_t symbolpathsize; printf("CMD_GETSYMBOLLISTFROMFILE\n"); if (recvall(currentsocket, &symbolpathsize, sizeof(symbolpathsize), MSG_WAITALL)>0) { char *symbolpath=(char *)malloc(symbolpathsize+1); symbolpath[symbolpathsize]='\0'; if (recvall(currentsocket, symbolpath, symbolpathsize, MSG_WAITALL)>0) { unsigned char *output=NULL; printf("symbolpath=%s\n", symbolpath); if (memcmp("/dev/", symbolpath, 5)!=0) //don't even bother if it's a /dev/ file GetSymbolListFromFile(symbolpath, &output); if (output) { printf("output is not NULL (%p)\n", output); fflush(stdout); printf("Sending %d bytes\n", *(uint32_t *)&output[4]); sendall(currentsocket, output, *(uint32_t *)&output[4], 0); //the output buffer contains the size itself free(output); } else { printf("Sending 8 bytes (fail)\n"); uint64_t fail=0; sendall(currentsocket, &fail, sizeof(fail), 0); //just write 0 } } else { printf("Failure getting symbol path\n"); close(currentsocket); } free(symbolpath); } break; } case CMD_LOADEXTENSION: { //Load the extension if it isn't loaded yet //LOADEXTENSION(handle) uint32_t handle; if (recvall(currentsocket, &handle, sizeof(handle),0)>0) { int result=loadCEServerExtension(handle); sendall(currentsocket, &result, sizeof(result),0); } break; } case CMD_ALLOC: { //ALLOC(processhandle, preferedbase, size) CeAllocInput c; printf("CESERVER: CMD_ALLOC\n"); if (recvall(currentsocket, &c, sizeof(c),0)>0) { printf("c.hProcess=%d\n", c.hProcess); printf("c.preferedBase=%llx\n", c.preferedBase); printf("c.size=%d\n", c.size); uint64_t address=ext_alloc(c.hProcess, c.preferedBase, c.size); sendall(currentsocket, &address, sizeof(address),0); } break; } case CMD_FREE: { CeFreeInput c; printf("CESERVER: CMD_FREE\n"); if (recvall(currentsocket, &c, sizeof(c),0)>0) { uint32_t r; r=ext_free(c.hProcess, c.address, c.size); sendall(currentsocket, &r, sizeof(r),0); } break; } case CMD_CREATETHREAD: { CeCreateThreadInput c; printf("CESERVER: CMD_CREATETHREAD\n"); if (recvall(currentsocket, &c, sizeof(c),0)>0) { uint64_t th; HANDLE h; th=ext_createThread(c.hProcess, c.startaddress, c.startaddress); printf("returned from ext_createthread\n"); if (th) //create a handle for this object { uint64_t *threadobject=(uint64_t *)malloc(sizeof(uint64_t)); *threadobject=th; h=CreateHandleFromPointer(threadobject, htNativeThreadHandle); } else h=0; sendall(currentsocket, &h, sizeof(h),0); } break; } case CMD_LOADMODULE: { CeLoadModuleInput c; printf("CESERVER: CMD_LOADMODULE\n"); if (recvall(currentsocket, &c, sizeof(c),0)>0) { char modulepath[c.modulepathlength+1]; if (recvall(currentsocket, &modulepath, sizeof(c.modulepathlength),0)>0) { uint32_t result; modulepath[c.modulepathlength]=0; result=ext_loadModule(c.hProcess, modulepath); sendall(currentsocket, &result, sizeof(result),0); } } break; } case CMD_SPEEDHACK_SETSPEED: { CeSpeedhackSetSpeedInput c; printf("CESERVER: CMD_SPEEDHACK_SETSPEED\n"); if (recvall(currentsocket, &c, sizeof(c),0)>0) { uint32_t r; r=ext_speedhack_setSpeed(c.hProcess, c.speed); sendall(currentsocket, &r, sizeof(r),0); } break; } } }
void qtDLGMemoryView::DisplayMemory() { PTCHAR sTemp = (PTCHAR)clsMemManager::CAlloc(MAX_PATH * sizeof(TCHAR)); PTCHAR sTemp2 = (PTCHAR)clsMemManager::CAlloc(MAX_PATH * sizeof(TCHAR)); MEMORY_BASIC_INFORMATION mbi; tblMemoryView->setRowCount(0); for(size_t i = m_processCountEntry; i < m_processCountEnd;i++) { quint64 dwAddress = NULL; while(VirtualQueryEx(m_pMainWindow->coreDebugger->PIDs[i].hProc,(LPVOID)dwAddress,&mbi,sizeof(mbi))) { tblMemoryView->insertRow(tblMemoryView->rowCount()); // PID tblMemoryView->setItem(tblMemoryView->rowCount() -1,0, new QTableWidgetItem(QString().sprintf("%08X",m_pMainWindow->coreDebugger->PIDs[i].dwPID))); // Base Address #ifdef _AMD64_ wsprintf(sTemp,L"%016I64X",mbi.BaseAddress); #else wsprintf(sTemp,L"%016X",mbi.BaseAddress); #endif tblMemoryView->setItem(tblMemoryView->rowCount() -1,1, new QTableWidgetItem(QString().fromStdWString(sTemp))); // Size wsprintf(sTemp,L"%08X",mbi.RegionSize); tblMemoryView->setItem(tblMemoryView->rowCount() -1,2, new QTableWidgetItem(QString().fromStdWString(sTemp))); // Path size_t iModPos = NULL, iModLen = NULL; memset(sTemp,0,MAX_PATH * sizeof(TCHAR)); memset(sTemp2,0,MAX_PATH * sizeof(TCHAR)); GetMappedFileName(m_pMainWindow->coreDebugger->PIDs[i].hProc,(LPVOID)dwAddress,sTemp2,MAX_PATH); iModLen = wcslen(sTemp2); if(iModLen > 0) { for(size_t i = iModLen; i > 0 ; i--) { if(sTemp2[i] == '\\') { iModPos = i; break; } } memcpy_s(sTemp,MAX_PATH,(LPVOID)&sTemp2[iModPos + 1],(iModLen - iModPos) * sizeof(TCHAR)); tblMemoryView->setItem(tblMemoryView->rowCount() -1,3, new QTableWidgetItem(QString().fromStdWString(sTemp))); } else tblMemoryView->setItem(tblMemoryView->rowCount() -1,3, new QTableWidgetItem(QString(""))); // Mem Type switch (mbi.State) { case MEM_FREE: wsprintf(sTemp,L"%s",L"Free"); break; case MEM_RESERVE: wsprintf(sTemp,L"%s",L"Reserve"); break; case MEM_COMMIT: switch (mbi.Type) { case MEM_FREE: wsprintf(sTemp,L"%s",L"Free"); break; case MEM_RESERVE: wsprintf(sTemp,L"%s",L"Reserve"); break; case MEM_IMAGE: wsprintf(sTemp,L"%s",L"Image"); break; case MEM_MAPPED: wsprintf(sTemp,L"%s",L"Mapped"); break; case MEM_PRIVATE: wsprintf(sTemp,L"%s",L"Private"); break; } break; } tblMemoryView->setItem(tblMemoryView->rowCount() -1,4, new QTableWidgetItem(QString().fromStdWString(sTemp))); // Access wsprintf(sTemp,L"%s",L"Unknown"); if(mbi.State == MEM_FREE) mbi.Protect = PAGE_NOACCESS; if(mbi.State == MEM_RESERVE) mbi.Protect = PAGE_NOACCESS; switch (mbi.Protect & ~(PAGE_GUARD | PAGE_NOCACHE | PAGE_WRITECOMBINE)) { case PAGE_READONLY: wsprintf(sTemp,L"%s",L"-R--"); break; case PAGE_READWRITE: wsprintf(sTemp,L"%s",L"-RW-"); break; case PAGE_WRITECOPY: wsprintf(sTemp,L"%s",L"-RWC"); break; case PAGE_EXECUTE: wsprintf(sTemp,L"%s",L"E---"); break; case PAGE_EXECUTE_READ: wsprintf(sTemp,L"%s",L"ER--"); break; case PAGE_EXECUTE_READWRITE: wsprintf(sTemp,L"%s",L"ERW-"); break; case PAGE_EXECUTE_WRITECOPY: wsprintf(sTemp,L"%s",L"ERWC"); break; case PAGE_NOACCESS: wsprintf(sTemp,L"%s",L"----"); break; } tblMemoryView->setItem(tblMemoryView->rowCount() -1,5, new QTableWidgetItem(QString().fromStdWString(sTemp))); dwAddress += mbi.RegionSize; } } clsMemManager::CFree(sTemp2); clsMemManager::CFree(sTemp); }
int main (int argc, char** argv) { MEMORY_BASIC_INFORMATION mbi; char* region = 0; const char* type; wchar_t namebuf[4096]; DWORD winpid = (argv[1] ? atoi (argv[1]) : GetCurrentProcessId ()); HANDLE proc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, winpid); if (!proc) { fprintf (stderr, "OpenProcess(%lu): 0x%lx\n", winpid, GetLastError ()); return 1; } var_in_data = 43; for (;; region += mbi.RegionSize) { if (!VirtualQueryEx (proc, region, &mbi, sizeof (mbi))) { if (GetLastError () != ERROR_INVALID_PARAMETER) fprintf (stderr, "VirtualQuery: 0x%lx\n", GetLastError ()); break; } if (mbi.State == MEM_FREE) continue; #if 0 if (mbi.Type == MEM_IMAGE) continue; #endif if (mbi.State == MEM_FREE) type = "free"; else if (mbi.Type == MEM_IMAGE) type = "image"; else if (mbi.Type == MEM_MAPPED) type = "mapped"; else if (mbi.Type == MEM_PRIVATE) type = "private"; else type = "unknown"; printf ("0x%08lx %-9s %010lu %-8s %s\n", (unsigned long) region, mbi.State == MEM_COMMIT ? "commit" : "reserved", mbi.RegionSize, type, describe_protection (mbi.Protect) ); if (winpid == GetCurrentProcessId ()) { if (region <= (char*) &var_in_bss && (char*) &var_in_bss < (region + mbi.RegionSize)) { printf (" ^^^^ BSS\n"); } if (region <= (char*) &var_in_data && (char*) &var_in_data < (region + mbi.RegionSize)) { printf (" ^^^^ DATA\n"); } if (mbi.Type == MEM_MAPPED) { namebuf[0] = L'\0'; wcscpy (namebuf, L"[unknown]"); GetMappedFileNameW (GetCurrentProcess (), region, &namebuf[0], countof (namebuf)); printf (" ^^^^ - %S\n", namebuf); } } } }
/*********************************************************************** * VirtualQuery (KERNEL32.@) * * Provides info about a range of pages in virtual address space. * * PARAMS * addr [I] Address of region. * info [O] Address of info buffer. * len [I] Size of buffer. * * RETURNS * Number of bytes returned in information buffer or 0 if * addr >= 0xc0000000 (kernel space). */ SIZE_T WINAPI VirtualQuery( LPCVOID addr, PMEMORY_BASIC_INFORMATION info, SIZE_T len ) { return VirtualQueryEx( GetCurrentProcess(), addr, info, len ); }
// ------------------------------------------------------------- // メモリイメージを実行する関数 // 引数:pe(PEファイルのヘッダポインタ構造体のポインタ) // pMemImage (メモリイメージのポインタ) // dwMemImageSize(メモリイメージのサイズ) // szTargetProc (ターゲットプロセスのパス) // 戻り値:成功時0、失敗時0以外 // ------------------------------------------------------------- int ExecPEImage(PPE_HEADERS pe, LPVOID pMemImage, DWORD dwMemImageSize, PTCHAR szTargetProc) { // プロセス生成 STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); BOOL bFlag = CreateProcess(NULL, szTargetProc, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, &pi); if( ! bFlag) return -1; // 生成したプロセス内のスレッドコンテキスト取得 CONTEXT ctx; ctx.ContextFlags = CONTEXT_FULL; GetThreadContext(pi.hThread, &ctx); PROCINFO piChildInfo; DWORD *pebInfo = (DWORD *)ctx.Ebx; // 生成したプロセスのベースアドレスを取得 DWORD dwRead; ReadProcessMemory(pi.hProcess, &pebInfo[2], (LPVOID)&(piChildInfo.dwBaseAddr), sizeof(DWORD), &dwRead); DWORD dwCurAddr = piChildInfo.dwBaseAddr; // フリーに扱えるメモリ領域を検索 MEMORY_BASIC_INFORMATION mbiInfo; while(VirtualQueryEx(pi.hProcess, (LPVOID)dwCurAddr, &mbiInfo, sizeof(mbiInfo))) { if(mbiInfo.State == MEM_FREE) break; dwCurAddr += mbiInfo.RegionSize; } // 生成したプロセスが割り当ているメモリサイズを取得 piChildInfo.dwImageSize = dwCurAddr - (DWORD)piChildInfo.dwBaseAddr; LPVOID lpProcessMem; // 生成されたプロセスのメモリ空間に収まるならそのまま利用する if(pe->poh->ImageBase == piChildInfo.dwBaseAddr && dwMemImageSize <= piChildInfo.dwImageSize) { lpProcessMem = (LPVOID)piChildInfo.dwBaseAddr; DWORD dwOldProtect; VirtualProtectEx(pi.hProcess, (LPVOID)piChildInfo.dwBaseAddr, piChildInfo.dwImageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 生成されたプロセスのメモリ空間に収まらないならば // 新しくメモリ空間を割り当てる }else{ // ZwUnmapViewOfSection関数は // プロセスの仮想アドレス空間にマップされたビューを解放する PTRZwUnmapViewOfSection pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress( GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection"); // メモリを開放 if(pZwUnmapViewOfSection( pi.hProcess, (LPVOID)piChildInfo.dwBaseAddr) == 0) { // 強引にメモリ空間を確保する lpProcessMem = VirtualAllocEx(pi.hProcess, (LPVOID)pe->poh->ImageBase, dwMemImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if( ! lpProcessMem) return -1; } } pebInfo = (DWORD *)ctx.Ebx; // プロセスのベースアドレスを書き換える DWORD dwWrote; WriteProcessMemory(pi.hProcess, &pebInfo[2], &lpProcessMem, sizeof(DWORD), &dwWrote); // メモリイメージをプロセス空間へコピー if( ! WriteProcessMemory(pi.hProcess, lpProcessMem, pMemImage, dwMemImageSize, NULL)) { TerminateProcess(pi.hProcess, 0); return -1; } // プログラムのエントリポイントをEAXへ if((DWORD)lpProcessMem == piChildInfo.dwBaseAddr) ctx.Eax = pe->poh->ImageBase + pe->poh->AddressOfEntryPoint; else ctx.Eax = (DWORD)lpProcessMem + pe->poh->AddressOfEntryPoint; // コンテキストをセットしてプロセスを開始 ctx.ContextFlags = CONTEXT_FULL; SetThreadContext(pi.hThread, &ctx); ResumeThread(pi.hThread); return 0; }
bool UpdateMemoryMap(void) { MemMap.clear(); MemMapCode.clear(); MemMapData.clear(); MemMapModule.clear(); Exports.clear(); CustomNames.clear(); if (g_hProcess == NULL) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Process handle NULL!")); #endif return 0; } if (!IsProcHandleValid(g_hProcess)) { g_hProcess = NULL; #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Process handle invalid!")); #endif return 0; } SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); MEMORY_BASIC_INFORMATION MemInfo; size_t pMemory = (size_t)SysInfo.lpMinimumApplicationAddress; while (pMemory < (size_t)SysInfo.lpMaximumApplicationAddress) { if (VirtualQueryEx(g_hProcess, (LPCVOID)pMemory, &MemInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0) { if (MemInfo.State == MEM_COMMIT /*&& MemInfo.Type == MEM_PRIVATE*/) { MemMapInfo Mem; Mem.Start = (size_t)pMemory; Mem.End = (size_t)pMemory + MemInfo.RegionSize - 1; MemMap.push_back(Mem); } pMemory = (ULONG_PTR)MemInfo.BaseAddress + MemInfo.RegionSize; } else { pMemory += 1024; } } static HMODULE hNtDll = (HMODULE)Utils::GetLocalModuleHandle("ntdll.dll"); static tNtQueryInformationProcess NtQueryInformationProcess = (tNtQueryInformationProcess)Utils::GetProcAddress(hNtDll, "NtQueryInformationProcess"); PPROCESS_BASIC_INFORMATION ProcessInfo = NULL; PEB Peb; PEB_LDR_DATA LdrData; // Try to allocate buffer HANDLE hHeap = GetProcessHeap(); DWORD dwSize = sizeof(PROCESS_BASIC_INFORMATION); ProcessInfo = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, dwSize); ULONG dwSizeNeeded = 0; NTSTATUS status = NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, ProcessInfo, dwSize, &dwSizeNeeded); if (status >= 0 && dwSize < dwSizeNeeded) { if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); ProcessInfo = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, dwSizeNeeded); if (!ProcessInfo) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Couldn't allocate heap buffer!")); #endif return 0; } status = NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, ProcessInfo, dwSizeNeeded, &dwSizeNeeded); } // Did we successfully get basic info on process if (NT_SUCCESS(status)) { // Check for PEB if (!ProcessInfo->PebBaseAddress) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: PEB is null! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } // Read Process Environment Block (PEB) SIZE_T dwBytesRead = 0; if ( ReadMemory( ProcessInfo->PebBaseAddress, &Peb, sizeof(PEB), &dwBytesRead) == 0) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Failed to read PEB! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } // Get Ldr dwBytesRead = 0; if ( ReadMemory( Peb.Ldr, &LdrData, sizeof(LdrData), &dwBytesRead) == 0) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Failed to read PEB Ldr Data! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } LIST_ENTRY *pLdrListHead = (LIST_ENTRY *)LdrData.InLoadOrderModuleList.Flink; LIST_ENTRY *pLdrCurrentNode = LdrData.InLoadOrderModuleList.Flink; do { LDR_DATA_TABLE_ENTRY lstEntry = { 0 }; dwBytesRead = 0; if (! ReadMemory( (void*)pLdrCurrentNode, &lstEntry, sizeof(LDR_DATA_TABLE_ENTRY), &dwBytesRead)) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Could not read list entry from LDR list. Error = %s"), Utils::GetLastErrorString().GetString()); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } pLdrCurrentNode = lstEntry.InLoadOrderLinks.Flink; if (lstEntry.DllBase != NULL /*&& lstEntry.SizeOfImage != 0*/) { unsigned char* ModuleBase = (unsigned char*)lstEntry.DllBase; DWORD ModuleSize = lstEntry.SizeOfImage; wchar_t wcsFullDllName[MAX_PATH] = { 0 }; wchar_t* wcsModule = 0; if (lstEntry.FullDllName.Length > 0) { dwBytesRead = 0; if ( ReadMemory( (LPVOID)lstEntry.FullDllName.Buffer, &wcsFullDllName, lstEntry.FullDllName.Length, &dwBytesRead)) { wcsModule = wcsrchr(wcsFullDllName, L'\\'); if (!wcsModule) wcsModule = wcsrchr(wcsFullDllName, L'/'); wcsModule++; if (g_AttachedProcessAddress == NULL) { wchar_t filename[MAX_PATH]; GetModuleFileNameExW(g_hProcess, NULL, filename, MAX_PATH); if (_wcsicmp(filename, wcsFullDllName) == 0) { g_AttachedProcessAddress = (size_t)ModuleBase; g_AttachedProcessSize = ModuleSize; } } } } // module info MemMapInfo Mem; Mem.Start = (size_t)ModuleBase; Mem.End = Mem.Start + ModuleSize; Mem.Size = ModuleSize; Mem.Name = wcsModule; Mem.Path = wcsFullDllName; //PrintOut(_T("%s: %IX"), Mem.Name.GetBuffer(), Mem.Start); MemMapModule.push_back(Mem); // module code IMAGE_DOS_HEADER DosHdr; IMAGE_NT_HEADERS NtHdr; ReadMemory( ModuleBase, &DosHdr, sizeof(IMAGE_DOS_HEADER), NULL); ReadMemory( ModuleBase + DosHdr.e_lfanew, &NtHdr, sizeof(IMAGE_NT_HEADERS), NULL); DWORD sectionsSize = (DWORD)NtHdr.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)malloc(sectionsSize); ReadMemory( ModuleBase + DosHdr.e_lfanew + sizeof(IMAGE_NT_HEADERS), sections, sectionsSize, NULL); for (int i = 0; i < NtHdr.FileHeader.NumberOfSections; i++) { CString txt; MemMapInfo Mem; txt.Format(_T("%.8s"), sections[i].Name); txt.MakeLower(); if (txt == ".text" || txt == "code") { Mem.Start = (size_t)ModuleBase + sections[i].VirtualAddress; Mem.End = Mem.Start + sections[i].Misc.VirtualSize; Mem.Name = wcsModule; MemMapCode.push_back(Mem); } if (txt == ".data" || txt == "data" || txt == ".rdata" || txt == ".idata") { Mem.Start = (size_t)ModuleBase + sections[i].VirtualAddress; Mem.End = Mem.Start + sections[i].Misc.VirtualSize; Mem.Name = wcsModule; MemMapData.push_back(Mem); } } delete sections; } } while (pLdrListHead != pLdrCurrentNode); } else { #ifdef _DEBUG PrintOut(_T("[UpdateExports]: NtQueryInformationProcess failed! Aborting...")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); for (UINT i = 0; i < MemMap.size(); i++) { if (IsModule(MemMap[i].Start)) MemMap[i].Name = GetModuleName(MemMap[i].Start); } return 1; }
int _tmain(int argc, _TCHAR* argv[]) { // Init PMEMORY_BASIC_INFORMATION basicInfo = (PMEMORY_BASIC_INFORMATION)malloc(sizeof(MEMORY_BASIC_INFORMATION)); PMEMORY_BASIC_INFORMATION basicInfoEnum = (PMEMORY_BASIC_INFORMATION)malloc(sizeof(MEMORY_BASIC_INFORMATION)); LPSYSTEM_INFO sysInfo = (LPSYSTEM_INFO)malloc(sizeof(SYSTEM_INFO)); SIZE_T i = 0, j = 0, szbuffer = 0; PBYTE hDump = 0; // Pattern Signature BYTE pattern[] = { 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64 }; BYTE offset_pointer = 0; if (argc != 2) return 0; GetNativeSystemInfo(sysInfo); HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, _tstoi(argv[1])); //printf("Dump from %p to %p\n", sysInfo->lpMinimumApplicationAddress, sysInfo->lpMaximumApplicationAddress); for (i = (SIZE_T)sysInfo->lpMinimumApplicationAddress; i < (SIZE_T)sysInfo->lpMaximumApplicationAddress; i += basicInfoEnum->RegionSize) { VirtualQueryEx(hProcess, (LPCVOID)i, basicInfoEnum, sizeof(MEMORY_BASIC_INFORMATION)); if (memcmp(basicInfoEnum, basicInfo, sizeof(MEMORY_BASIC_INFORMATION)) && basicInfoEnum->AllocationBase != 0) { if (basicInfoEnum->AllocationBase == basicInfo->AllocationBase) { printf("%24s [+] BaseAddress: %p RegionSize: %p Protect: %x\t\n", " ", basicInfoEnum->BaseAddress, basicInfoEnum->RegionSize, basicInfoEnum->Protect); } else { printf("[-] AllocationBase: %p BaseAddress: %p RegionSize: %p Protect: %x\t\n", basicInfoEnum->AllocationBase, basicInfoEnum->BaseAddress, basicInfoEnum->RegionSize, basicInfoEnum->Protect); } memcpy(basicInfo, basicInfoEnum, sizeof(MEMORY_BASIC_INFORMATION)); } if (basicInfoEnum->RegionSize != -1) { hDump = (PBYTE)malloc(basicInfoEnum->RegionSize); ReadProcessMemory(hProcess, basicInfoEnum->BaseAddress, hDump, basicInfoEnum->RegionSize, &szbuffer); if (hDump && szbuffer != 0) { for (j = 0; j < basicInfoEnum->RegionSize; j++) { if (!memcmp(&hDump[j], &pattern, sizeof(pattern))) { printf("Pattern over here, Captain! Addr: %x\n", (DWORD)basicInfoEnum->BaseAddress + (j + offset_pointer)); /* SIZE_T k = j; for (; k < j + 16; k++) { printf("%x", hDump[k]); } break; */ } } } } i += 1000; } printf("FIN\n"); free(hDump); free(basicInfo); free(basicInfoEnum); free(sysInfo); CloseHandle(hProcess); return 0; }
/* * Creates memory close to the target function, used to force the actual hook * to use a 32bit jump instead of a 64bit jump, thus preventing the chance of * overwriting adjacent functions, which can cause a crash. (by R1CH) */ static void setup_64bit_bounce(struct func_hook *hook, intptr_t *offset) { MEMORY_BASIC_INFORMATION mbi; uintptr_t address; uintptr_t newdiff; SYSTEM_INFO si; bool success; int pagesize; int i; success = VirtualQueryEx(GetCurrentProcess(), (const void*)hook->func_addr, &mbi, sizeof(mbi)); if (!success) return; GetSystemInfo(&si); pagesize = (int)si.dwAllocationGranularity; address = (uintptr_t)mbi.AllocationBase - pagesize; for (i = 0; i < 256; i++, address -= pagesize) { hook->bounce_addr = VirtualAlloc((LPVOID)address, pagesize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (hook->bounce_addr) break; } if (!hook->bounce_addr) { address = (uintptr_t)mbi.AllocationBase + mbi.RegionSize + pagesize; for (i = 0; i < 256; i++, address += pagesize) { hook->bounce_addr = VirtualAlloc((LPVOID)address, pagesize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (hook->bounce_addr) break; } } if (!hook->bounce_addr) return; if ((hook->func_addr + 5) > (uintptr_t)hook->bounce_addr) newdiff = hook->func_addr + 5 - (uintptr_t)hook->bounce_addr; else newdiff = (uintptr_t)hook->bounce_addr - hook->func_addr + 5; if (newdiff <= 0x7ffffff0) { uint8_t *addr = (uint8_t*)hook->bounce_addr; FillMemory(hook->bounce_addr, pagesize, 0xCC); *(addr++) = 0xFF; *(addr++) = 0x25; *((uint32_t*)addr) = 0; *((uint64_t*)(addr + 4)) = hook->hook_addr; hook->hook_addr = (uint64_t)hook->bounce_addr; *offset = hook->hook_addr - hook->func_addr - JMP_32_SIZE; hook->is_64bit_jump = false; } }
bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer) { DWORD_PTR addressPart = 0; DWORD_PTR readBytes = 0; DWORD_PTR bytesToRead = 0; MEMORY_BASIC_INFORMATION memBasic = {0}; bool returnValue = false; if (!hProcess) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL"); #endif return returnValue; } if (!readMemoryFromProcess(address, size, dataBuffer)) { addressPart = address; do { if (!VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)addressPart,&memBasic,sizeof(memBasic))) { #ifdef DEBUG_COMMENTS Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart,size, GetLastError()); #endif break; } bytesToRead = memBasic.RegionSize; if ( (readBytes+bytesToRead) > size) { bytesToRead = size - readBytes; } if (memBasic.State == MEM_COMMIT) { if (!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes))) { break; } } else { ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes),bytesToRead); } readBytes += bytesToRead; addressPart += memBasic.RegionSize; } while (readBytes < size); if (readBytes == size) { returnValue = true; } } else { returnValue = true; } return returnValue; }
DWORD _cdecl main( int argc, char *argv[], char *envp[] ) { STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; BOOL Success; DWORD st; DWORD ProcessCount; SMALL_RECT Window; MEMORY_BASIC_INFORMATION info; PUCHAR address; PUCHAR buffer; ProcessCount = 0; if ( strchr(GetCommandLine(),'+') ) { NewProcess(); } GetStartupInfo(&StartupInfo); Success = CreateProcess( NULL, "vmread +", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInfo ); if (Success) { printf("Process Created\n"); Sleep (1000); buffer = VirtualAlloc (NULL, 10*1000*1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!buffer) { printf("virtual alloc failed at %ld.\n",GetLastError()); return 1; } address = NULL; do { Success = VirtualQueryEx (ProcessInfo.hProcess, (PVOID)address, &info, sizeof(info)); if (!Success) { printf ("virtual query failed at %lx - %ld.\n",address,GetLastError()); break; } else { printf("address: %lx size %lx state %lx protect %lx type %lx\n", address, info.RegionSize, info.State, info.Protect, info.Type); } address += info.RegionSize; } while (address < (PUCHAR)0x80000000); address = 0x40000000; do { Success = VirtualQueryEx (ProcessInfo.hProcess, (PVOID)address, &info, sizeof(info)); if (!Success) { printf ("virtual query failed at %lx %ld.\n",address,GetLastError()); return 1; } else { if (info.AllocationBase == address) { printf("address: %lx size %lx state %lx protect %lx type %lx\n", address, info.RegionSize, info.State, info.Protect, info.Type); } } address += 4096; } while (address < (PUCHAR)0x80000000); CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); } }
void CT_cbCertificateFunction() { if(!cert_func_count) cert_func_count++; else if(cert_func_count==1) { DeleteHardwareBreakPoint(UE_DR0); long retn_eax=GetContextData(UE_EAX); MEMORY_BASIC_INFORMATION mbi= {0}; unsigned int mem_size=0x10000; if(VirtualQueryEx(fdProcessInfo->hProcess, (void*)retn_eax, &mbi, sizeof(MEMORY_BASIC_INFORMATION))) mem_size=mbi.RegionSize-(retn_eax-(unsigned int)mbi.BaseAddress); BYTE* certificate_code=(BYTE*)malloc2(mem_size); if(!ReadProcessMemory(fdProcessInfo->hProcess, (void*)retn_eax, certificate_code, mem_size, 0)) { free2(certificate_code); CT_FatalError("Failed to read process memory..."); } //Arma 9.60 support puts("errorfuck"); unsigned int esp=GetContextData(UE_ESP); unsigned int _stack=0; if(!ReadProcessMemory(fdProcessInfo->hProcess, (void*)esp, &_stack, 4, 0)) { CT_FatalError(rpmerror()); return; } unsigned char* return_bytes=(unsigned char*)malloc2(0x1000); if(!ReadProcessMemory(fdProcessInfo->hProcess, (void*)_stack, return_bytes, 0x1000, 0)) { CT_FatalError(rpmerror()); return; } unsigned int push100=CT_FindPush100Pattern(return_bytes, 0x1000); unsigned int retn=CT_FindReturnPattern(return_bytes, 0x1000); if(!retn) CT_FindReturnPattern2(return_bytes, 0x1000); if(push100 and push100<retn) { unsigned int call=CT_FindCall1Pattern(return_bytes+push100, 0x1000-push100); if(!call) call=CT_FindCall2Pattern(return_bytes+push100, 0x1000-push100); if(!call) { if(MessageBoxA(CT_shared, "Could not find call, continue?", "Continue?", MB_ICONERROR|MB_YESNO)==IDYES) if(!magic_value_addr) CT_RetrieveSaltValue(); } else { SetBPX(_stack+call+push100, UE_BREAKPOINT, (void*)CT_cbSeed1); return_counter=0; SetBPX(_stack+retn, UE_BREAKPOINT, (void*)CT_cbReturnSeed1); } CT_cert_data->raw_size=mem_size; CT_cert_data->raw_data=(unsigned char*)malloc2(mem_size); memcpy(CT_cert_data->raw_data, certificate_code, mem_size); } else { free2(return_bytes); //Get raw certificate data unsigned int cert_start=CT_FindCertificateMarkers(certificate_code, mem_size); if(!cert_start) cert_start=CT_FindCertificateMarkers2(certificate_code, mem_size); if(!cert_start) { free2(certificate_code); if(MessageBoxA(CT_shared, "Could not find start markers, continue?", "Continue?", MB_ICONERROR|MB_YESNO)==IDYES) { if(!magic_value_addr) CT_RetrieveSaltValue(); } else StopDebug(); return; } CT_cert_data->raw_size=mem_size; CT_cert_data->raw_data=(unsigned char*)malloc2(mem_size); memcpy(CT_cert_data->raw_data, certificate_code, mem_size); if(!magic_value_addr) CT_RetrieveSaltValue(); } } else DeleteHardwareBreakPoint(UE_DR0); }
/** * @brief 遍历虚拟内存 * * @details 遍历指定进程的整个虚拟内存并对用户显示其属性的工作程序的方法 * * @param hProcess 待遍历的进程的进程句柄 */ void WalkVM(HANDLE hProcess) { // 首先,获得系统信息 SYSTEM_INFO si; ZeroMemory(&si, sizeof(si)); GetSystemInfo(&si); // 分配要存放信息的缓冲区 MEMORY_BASIC_INFORMATION mbi; ZeroMemory(&mbi, sizeof(mbi)); // 循环整个应用程序地址空间 LPCVOID pBlock = (LPVOID)si.lpMinimumApplicationAddress; while (pBlock < si.lpMaximumApplicationAddress) { // 获得下一个虚拟内存块的信息 if (VirtualQueryEx( hProcess, // 相关的进程 pBlock, // 开始位置 &mbi, // 缓冲区 sizeof(mbi) // 大小的确认 ) == sizeof(mbi)) { // 计算块的结尾及其大小 LPCVOID pEnd = (PBYTE)pBlock + mbi.RegionSize; TCHAR szSize[MAX_PATH]; StrFormatByteSize(mbi.RegionSize, szSize, MAX_PATH); // 显示块地址和大小 _tprintf(TEXT("%08x-%08x"), (DWORD)pBlock, (DWORD)pEnd); _tprintf(TEXT(" (%7s) "), szSize); switch (mbi.State) { case MEM_COMMIT: _tprintf(TEXT("Committed")); break; case MEM_FREE: _tprintf(TEXT("Free")); break; case MEM_RESERVE: _tprintf(TEXT("Reserved")); break; } // 显示保护 if (mbi.Protect == 0 && mbi.State != MEM_FREE) mbi.Protect = PAGE_READONLY; ShowProtection(mbi.Protect); // 显示类型 switch (mbi.Type) { case MEM_IMAGE: _tprintf(TEXT(", Image")); break; case MEM_MAPPED: _tprintf(TEXT(", Mapped")); break; case MEM_PRIVATE: _tprintf(TEXT(", Private")); break; } // 检验可执行的影像 TCHAR szFilename[MAX_PATH]; if (GetModuleFileName( (HMODULE)pBlock, szFilename, MAX_PATH ) > 0) { // 除去路径并显示 PathStripPath(szFilename); _tprintf(TEXT(", Module: %s"), szFilename); } _putts(TEXT("")); // 移动块指针以获得下一个块 pBlock = pEnd; } } }
BOOL DumpProcess(HANDLE hp) { ULONG64 base; ULONG64 next; MEMORY_BASIC_INFORMATION mbi; printf(" %12s %8s %8s: %3s %3s %4s %3s : %8s\n", "Address", "Offset", "Size", "Typ", "Sta", "Prot", "Ini", "Contents"); printf(" %12s %8s %8s: %3s %3s %4s %3s : %8s\n", "------------", "--------", "--------", "---", "---", "----", "---", "-----------------"); for (next = 0;;) { base = next; ZeroMemory(&mbi, sizeof(mbi)); if (VirtualQueryEx(hp, (PVOID)base, &mbi, sizeof(mbi)) == 0) { break; } if ((mbi.RegionSize & 0xfff) == 0xfff) { break; } next = (ULONG64)mbi.BaseAddress + mbi.RegionSize; if (mbi.State == MEM_FREE) { continue; } CHAR szType[16]; TypeToString(mbi.Type, szType, ARRAYSIZE(szType)); CHAR szState[16]; StateToString(mbi.State, szState, ARRAYSIZE(szState)); CHAR szProtect[16]; ProtectToString(mbi.Protect, szProtect, ARRAYSIZE(szProtect)); CHAR szAllocProtect[16]; ProtectToString(mbi.AllocationProtect, szAllocProtect, ARRAYSIZE(szAllocProtect)); CHAR szFile[MAX_PATH]; szFile[0] = '\0'; DWORD cb = 0; PCHAR pszFile = szFile; if (base == (ULONG64)mbi.AllocationBase) { #if 0 cb = pfGetMappedFileName(hp, (PVOID)mbi.AllocationBase, szFile, ARRAYSIZE(szFile)); #endif if (GetSections(hp, (PBYTE)mbi.AllocationBase)) { next = base + 0x1000; sprintf_s(szFile, ARRAYSIZE(szFile), "%d-bit PE", Bitness); } } if (cb > 0) { for (DWORD c = 0; c < cb; c++) { szFile[c] = (szFile[c] >= 'a' && szFile[c] <= 'z') ? szFile[c] - 'a' + 'A' : szFile[c]; } szFile[cb] = '\0'; } if ((pszFile = strrchr(szFile, '\\')) == NULL) { pszFile = szFile; } else { pszFile++; } PBYTE pbEnd; PCHAR pszSect = FindSectionName((PBYTE)base, pbEnd); if (pszSect != NULL) { pszFile = pszSect; if (next > (ULONG64)pbEnd) { next = (ULONG64)pbEnd; } } CHAR szDesc[128]; ZeroMemory(&szDesc, ARRAYSIZE(szDesc)); if (base == (ULONG64)mbi.AllocationBase) { sprintf_s(szDesc, ARRAYSIZE(szDesc), " %12I64x %8I64x %8I64x: %3s %3s %4s %3s : %s", (ULONG64)base, (ULONG64)base - (ULONG64)mbi.AllocationBase, (ULONG64)next - (ULONG64)base, szType, szState, szProtect, szAllocProtect, pszFile); } else { sprintf_s(szDesc, ARRAYSIZE(szDesc), " %12s %8I64x %8I64x: %3s %3s %4s %3s : %s", "-", (ULONG64)base - (ULONG64)mbi.AllocationBase, (ULONG64)next - (ULONG64)base, szType, szState, szProtect, szAllocProtect, pszFile); } printf("%s\n", szDesc); } return TRUE; }
bool apienumimports(duint base, const IMPORTENUMCALLBACK & cbEnum) { // Variables bool readSuccess; Memory<char*> importName(MAX_IMPORT_SIZE + 1, "apienumimports:buffer"); char importModuleName[MAX_MODULE_SIZE] = ""; duint regionSize; ULONG_PTR importTableRva, importTableSize; MEMORY_BASIC_INFORMATION mbi; PIMAGE_IMPORT_DESCRIPTOR importTableVa; IMAGE_IMPORT_DESCRIPTOR importDescriptor; PIMAGE_THUNK_DATA imageIATVa, imageINTVa; IMAGE_THUNK_DATA imageOftThunkData, imageFtThunkData; PIMAGE_IMPORT_BY_NAME pImageImportByNameVa; // Get page size VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi)); regionSize = mbi.RegionSize; Memory<void*> buffer(regionSize, "apienumimports:buffer"); // Read first page into buffer if(!MemRead(base, buffer(), regionSize)) return false; // Import Table address and size importTableRva = GetPE32DataFromMappedFile((duint)buffer(), 0, UE_IMPORTTABLEADDRESS); importTableSize = GetPE32DataFromMappedFile((duint)buffer(), 0, UE_IMPORTTABLESIZE); // Return if no imports if(!importTableSize) return false; importTableVa = (PIMAGE_IMPORT_DESCRIPTOR)(base + importTableRva); readSuccess = MemRead((duint)importTableVa, &importDescriptor, sizeof(importDescriptor)); // Loop through all dlls while(readSuccess && importDescriptor.FirstThunk) { // Copy module name into importModuleName MemRead((duint)(base + importDescriptor.Name), &importModuleName, MAX_MODULE_SIZE); imageIATVa = (PIMAGE_THUNK_DATA)(base + importDescriptor.FirstThunk); imageINTVa = (PIMAGE_THUNK_DATA)(base + importDescriptor.OriginalFirstThunk); if(!MemRead((duint)imageIATVa, &imageFtThunkData, sizeof(imageFtThunkData))) return false; if(!MemRead((duint)imageINTVa, &imageOftThunkData, sizeof(imageOftThunkData))) return false; // Loop through all imported function in this dll while(imageFtThunkData.u1.AddressOfData) { pImageImportByNameVa = (PIMAGE_IMPORT_BY_NAME)(base + imageOftThunkData.u1.AddressOfData); // Read every IMPORT_BY_NAME.name if(!MemRead((duint)pImageImportByNameVa + sizeof(WORD), importName(), MAX_IMPORT_SIZE)) return false; // Callback cbEnum(base, imageFtThunkData.u1.Function, importName(), importModuleName); // Move to next address in the INT imageINTVa++; if(!MemRead((duint)imageINTVa, &imageOftThunkData, sizeof(imageOftThunkData))) return false; // Move to next address in the IAT and read it into imageFtThunkData imageIATVa++; if(!MemRead((duint)imageIATVa, &imageFtThunkData, sizeof(imageFtThunkData))) return false; } importTableVa++; readSuccess = MemRead((duint)importTableVa, &importDescriptor, sizeof(importDescriptor)); } return true; }
///api functions bool apienumexports(uint base, EXPORTENUMCALLBACK cbEnum) { MEMORY_BASIC_INFORMATION mbi; VirtualQueryEx(fdProcessInfo->hProcess, (const void*)base, &mbi, sizeof(mbi)); uint size = mbi.RegionSize; Memory<void*> buffer(size, "apienumexports:buffer"); if(!MemRead(base, buffer(), size)) return false; IMAGE_NT_HEADERS* pnth = (IMAGE_NT_HEADERS*)((uint)buffer() + GetPE32DataFromMappedFile((ULONG_PTR)buffer(), 0, UE_PE_OFFSET)); uint export_dir_rva = pnth->OptionalHeader.DataDirectory[0].VirtualAddress; uint export_dir_size = pnth->OptionalHeader.DataDirectory[0].Size; IMAGE_EXPORT_DIRECTORY export_dir; memset(&export_dir, 0, sizeof(export_dir)); MemRead((export_dir_rva + base), &export_dir, sizeof(export_dir)); unsigned int NumberOfNames = export_dir.NumberOfNames; if(!export_dir.NumberOfFunctions || !NumberOfNames) //no named exports return false; char modname[MAX_MODULE_SIZE] = ""; ModNameFromAddr(base, modname, true); uint original_name_va = export_dir.Name + base; char original_name[deflen] = ""; memset(original_name, 0, sizeof(original_name)); MemRead(original_name_va, original_name, deflen); char* AddrOfFunctions_va = (char*)(export_dir.AddressOfFunctions + base); //not a valid local pointer char* AddrOfNames_va = (char*)(export_dir.AddressOfNames + base); //not a valid local pointer char* AddrOfNameOrdinals_va = (char*)(export_dir.AddressOfNameOrdinals + base); //not a valid local pointer for(DWORD i = 0; i < NumberOfNames; i++) { DWORD curAddrOfName = 0; MemRead((uint)(AddrOfNames_va + sizeof(DWORD)*i), &curAddrOfName, sizeof(DWORD)); char* cur_name_va = (char*)(curAddrOfName + base); char cur_name[deflen] = ""; memset(cur_name, 0, deflen); MemRead((uint)cur_name_va, cur_name, deflen); WORD curAddrOfNameOrdinals = 0; MemRead((uint)(AddrOfNameOrdinals_va + sizeof(WORD)*i), &curAddrOfNameOrdinals, sizeof(WORD)); DWORD curFunctionRva = 0; MemRead((uint)(AddrOfFunctions_va + sizeof(DWORD)*curAddrOfNameOrdinals), &curFunctionRva, sizeof(DWORD)); if(curFunctionRva >= export_dir_rva && curFunctionRva < export_dir_rva + export_dir_size) { char forwarded_api[deflen] = ""; memset(forwarded_api, 0, deflen); MemRead((curFunctionRva + base), forwarded_api, deflen); int len = (int)strlen(forwarded_api); int j = 0; while(forwarded_api[j] != '.' && j < len) j++; if(forwarded_api[j] == '.') { forwarded_api[j] = 0; HINSTANCE hTempDll = LoadLibraryExA(forwarded_api, 0, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); if(hTempDll) { uint local_addr = (uint)GetProcAddress(hTempDll, forwarded_api + j + 1); if(local_addr) { uint remote_addr = ImporterGetRemoteAPIAddress(fdProcessInfo->hProcess, local_addr); cbEnum(base, modname, cur_name, remote_addr); } } } } else { cbEnum(base, modname, cur_name, curFunctionRva + base); } } return true; }
BOOL PsGetProcessMappedModules(HANDLE ProcessHandle, MODULE_INFO *Entries, SIZE_T NumOfEntries, PSIZE_T RealNumOfEntries) { SIZE_T moduleOffset = 0; SIZE_T moduleCounter = 0; MEMORY_BASIC_INFORMATION memBasicInfo; LPVOID baseAddress = NULL; SIZE_T queryResult; SIZE_T returnLength; do { queryResult = VirtualQueryEx(ProcessHandle, baseAddress, &memBasicInfo, sizeof(memBasicInfo)); if (!queryResult) { break; } if (memBasicInfo.Type == MEM_IMAGE && baseAddress == memBasicInfo.AllocationBase) { moduleCounter++; if (moduleOffset >= NumOfEntries) { baseAddress = (LPVOID)((uintptr_t)baseAddress + memBasicInfo.RegionSize); continue; } DWORD Result = PsGetImageFileNameEx(ProcessHandle, baseAddress, Entries[moduleOffset].ModulePath, MAX_PATH, &returnLength); Entries[moduleOffset].ModuleHandle = (HMODULE)baseAddress; GetShortFileName(Entries[moduleOffset].ModulePath, Entries[moduleOffset].ModuleName, MAX_PATH); moduleOffset++; } baseAddress = (LPVOID)((uintptr_t)baseAddress + memBasicInfo.RegionSize); } while (TRUE); if (RealNumOfEntries) { *RealNumOfEntries = moduleCounter; } if (moduleCounter > NumOfEntries) { return FALSE; } return TRUE; }
bool clear_break_point( _In_ ch_param* param, _In_ DWORD_PTR address, _In_ unsigned char opcode, _In_ bool reset_eip ) { _ASSERTE(NULL != param); _ASSERTE(0 != address); _ASSERTE(NULL != opcode); if (NULL == param || 0 == address || NULL == opcode) return false; SIZE_T cb_rw = 0; unsigned char temp = 0; BOOL ret = ReadProcessMemory( param->hproc, (LPCVOID)address, &temp, sizeof(unsigned char), &cb_rw ); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); return false; } if (temp != BREAK_OPCODE) { log( "hprocess = 0x%08x, address = 0x%p, opcode = 0x%02x (not BREAK_OPCODE!)", param->hproc, address, temp ); return false; } MEMORY_BASIC_INFORMATION mbi = { 0 }; if (0 == VirtualQueryEx( param->hproc, (LPCVOID)address, &mbi, sizeof(mbi))) { log( "VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); return false; } if (TRUE != VirtualProtectEx( param->hproc, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect)) { log( "VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ) gle = %u", param->hproc, mbi.BaseAddress, mbi.RegionSize, GetLastError() ); return false; } do { ret = WriteProcessMemory( param->hproc, (LPVOID)address, &opcode, sizeof(unsigned char), &cb_rw); if (TRUE != ret || cb_rw != sizeof(unsigned char)) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); ret = FALSE; break; } if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char))) { log( "WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u", param->hproc, address, GetLastError() ); } } while (false); VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect); if (true == reset_eip) { _ASSERTE(NULL != param->hthread); if (NULL != param->hthread) { #if defined(_AMD64_) param->context.Rip--; #elif defined(_X86_) param->context.Eip--; #else #error !!unsupported architecture!! #endif if (TRUE != SetThreadContext(param->hthread, ¶m->context)) { log( "SetThreadContext(hthread=0x%08x), gle = %u", param->hthread, GetLastError() ); } } } return (TRUE == ret) ? true : false; }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //memory dump of process (need debug mode) DWORD WINAPI DumpProcessMemory(LPVOID lParam) { //open process DWORD pid = (DWORD)lParam; HANDLE hProc = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION/*|PROCESS_ALL_ACCESS*/, FALSE, pid); if (hProc!=NULL) { //hardward info : last memory process SYSTEM_INFO si; #ifdef _WIN64_VERSION_ //64bit GetSystemInfo(&si); #else GetNativeSystemInfo(&si); #endif OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(OPENFILENAME)); char path[MAX_PATH] =""; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = h_main; ofn.lpstrFile = path; ofn.nMaxFile = MAX_PATH; ofn.lpstrFilter = "RAW\0*.raw\0"; ofn.nFilterIndex = 1; ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; ofn.lpstrDefExt =".raw\0"; if (GetSaveFileName(&ofn)==TRUE) { HANDLE MyhFile = CreateFile(path, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, 0); if (MyhFile != INVALID_HANDLE_VALUE) { DWORD copiee; MEMORY_BASIC_INFORMATION mbi; LPVOID mem = 0; LPVOID buffer; while (mem < si.lpMaximumApplicationAddress) { //read memory info if (!VirtualQueryEx(hProc,mem, &mbi, sizeof(MEMORY_BASIC_INFORMATION)))break; if (mbi.RegionSize > 0) { buffer = (char*)malloc(mbi.RegionSize); if (buffer!=NULL) { if (ReadProcessMemory(hProc, mbi.BaseAddress, buffer, mbi.RegionSize, NULL)) WriteFile(MyhFile,buffer,mbi.RegionSize,&copiee,0); free(buffer); } }else break; //next mem = (LPVOID)((DWORD)mbi.BaseAddress + (DWORD)mbi.RegionSize); } } CloseHandle(MyhFile); } CloseHandle(hProc); } return 0; }
ScitInjectedProcessDescriptor_t scitInjectModule(DWORD dwProcessId, LPCSTR lpLibPath, BOOL bForce, BOOL bDebugee) { ScitInjectedProcessDescriptor_t ipd; DWORD dwLibPathSize; HMODULE hKernel32; HANDLE hProcess = 0; LPVOID lpRemoteAddress = 0; BOOL bInjected; DWORD dwSizeWritten; unsigned char *imageBuffer = 0; HANDLE hRemoteThread; HMODULE hInjectedModule; HMODULE hModule; BOOL bReaded; DWORD dwSizeReaded; LPVOID lpHeaderOffset; LPVOID lpSectionOffset; IMAGE_DOS_HEADER dosHeader; IMAGE_NT_HEADERS ntHeader; IMAGE_DOS_HEADER dosCurrentHeader; IMAGE_NT_HEADERS ntCurrentHeader; IMAGE_SECTION_HEADER section; MEMORY_BASIC_INFORMATION memoryBasicInformation; DWORD dwOldProtect, dwOldProtect_; DWORD *lpDwSectionsProtect = 0; DWORD i; memset(&ipd, 0, sizeof(ScitInjectedProcessDescriptor_t)); if (!lpLibPath) { return ipd; } if (dwProcessId == SCIT_CURRENT_PROCESS) { dwProcessId = GetCurrentProcessId(); } ipd.bOk = 0; ipd.hProcess = 0; ipd.dwProcessId = dwProcessId; ipd.lpLibPath = strdup(lpLibPath); ipd.hInjectedModule = 0; ipd.hModule = 0; if (!ipd.lpLibPath) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } dwLibPathSize = strlen(lpLibPath); hKernel32 = GetModuleHandle("KERNEL32.DLL"); if(!hKernel32) { hKernel32 = GetModuleHandle("kernel32.dll"); if (!hKernel32) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } } hProcess = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION, FALSE, dwProcessId); if (!hProcess) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* get image base of current module */ hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "GetModuleHandleA"), 0, 0, NULL); if (!hRemoteThread) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } hModule = (HMODULE) _scitGetExitCodeThread(hRemoteThread, bDebugee); CloseHandle(hRemoteThread); /* read DOS and PE headers of current module */ bReaded = ReadProcessMemory(hProcess, (LPVOID) ((DWORD) hModule), &dosCurrentHeader, sizeof(IMAGE_DOS_HEADER), &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } if (dosCurrentHeader.e_magic != IMAGE_DOS_SIGNATURE) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* read PE header */ lpHeaderOffset = (LPVOID) ((DWORD) hModule + (DWORD) dosCurrentHeader.e_lfanew); bReaded = ReadProcessMemory(hProcess, lpHeaderOffset, &ntCurrentHeader, sizeof(IMAGE_NT_HEADERS), &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } if (ntCurrentHeader.FileHeader.NumberOfSections <= 0) { /* wrong file? */ _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } lpSectionOffset = (LPVOID) ((DWORD) hModule + (DWORD) dosCurrentHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)); for (i = 0; i < ntCurrentHeader.FileHeader.NumberOfSections; i++) { bReaded = ReadProcessMemory(hProcess, (LPVOID) ((DWORD) lpSectionOffset + (i * sizeof(IMAGE_SECTION_HEADER))), §ion, sizeof(IMAGE_SECTION_HEADER), &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } if ((section.Characteristics & IMAGE_SCN_CNT_CODE) && (section.Characteristics & IMAGE_SCN_MEM_WRITE) && !bForce) { /* strange - code section have write flag, maybe it's packed/compressed * so we can wait until it will be ready for infection */ _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } } /* alloc remote memory */ lpRemoteAddress = VirtualAllocEx(hProcess, NULL, dwLibPathSize + 1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); if (!lpRemoteAddress) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } bInjected = WriteProcessMemory(hProcess, lpRemoteAddress, (LPVOID)lpLibPath, dwLibPathSize, &dwSizeWritten); if (!bInjected) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* check if DLL is already injected... */ hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "GetModuleHandleA"), lpRemoteAddress, 0, NULL); if (!hRemoteThread) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } hInjectedModule = (HMODULE) _scitGetExitCodeThread(hRemoteThread, bDebugee); CloseHandle(hRemoteThread); /* DLL already injected? */ if (hInjectedModule) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), lpRemoteAddress, 0, NULL); if (!hRemoteThread) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } hInjectedModule = (HMODULE) _scitGetExitCodeThread(hRemoteThread, bDebugee); CloseHandle(hRemoteThread); /* free module name buffer */ VirtualFreeEx(hProcess, lpRemoteAddress, 0, MEM_RELEASE); lpRemoteAddress = 0; /* read DOS header */ bReaded = ReadProcessMemory(hProcess, (LPVOID) hInjectedModule, &dosHeader, sizeof(IMAGE_DOS_HEADER), &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* read PE header */ lpHeaderOffset = (LPVOID) ((DWORD) hInjectedModule + (DWORD) dosHeader.e_lfanew); bReaded = ReadProcessMemory(hProcess, lpHeaderOffset, &ntHeader, sizeof(IMAGE_NT_HEADERS), &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } if (ntHeader.OptionalHeader.ImageBase != (DWORD) hInjectedModule) { lpDwSectionsProtect = (LPDWORD) malloc(IMAGE_NUMBEROF_DIRECTORY_ENTRIES * sizeof(DWORD)); if (!lpDwSectionsProtect) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* get memory regions protect information */ for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { lpDwSectionsProtect[i] = 0; if (ntHeader.OptionalHeader.DataDirectory[i].VirtualAddress && ntHeader.OptionalHeader.DataDirectory[i].Size) { if (VirtualQueryEx(hProcess, (LPVOID) ((DWORD) hInjectedModule + ntHeader.OptionalHeader.DataDirectory[i].VirtualAddress), &memoryBasicInformation, ntHeader.OptionalHeader.DataDirectory[i].Size)) { if (memoryBasicInformation.AllocationProtect) { lpDwSectionsProtect[i] = memoryBasicInformation.AllocationProtect; } /* printf("%x, %d, %x\n", ntHeader.OptionalHeader.DataDirectory[i].VirtualAddress, ntHeader.OptionalHeader.DataDirectory[i].Size, lpDwSectionsProtect[i]); */ } } /* printf("%x\n", lpDwSectionsProtect[i]); */ } if (!(imageBuffer = (unsigned char*) malloc(ntHeader.OptionalHeader.SizeOfImage + 1))) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* unlock memory before read/write */ if (!VirtualProtectEx(hProcess, (LPVOID) hInjectedModule, ntHeader.OptionalHeader.SizeOfImage, PAGE_READWRITE, &dwOldProtect)) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } bReaded = ReadProcessMemory(hProcess, (LPVOID) hInjectedModule, imageBuffer, ntHeader.OptionalHeader.SizeOfImage, &dwSizeReaded); if (!bReaded) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } _scitFixRelocations(hInjectedModule, (char*)imageBuffer, ntHeader.OptionalHeader.SizeOfImage); _scitFixImports(hInjectedModule, imageBuffer, ntHeader.OptionalHeader.SizeOfImage); /* write module image back to process */ bInjected = WriteProcessMemory(hProcess, (LPVOID) hInjectedModule, imageBuffer, ntHeader.OptionalHeader.SizeOfImage, &dwSizeWritten); if (!bInjected) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* restore old lock */ if (!VirtualProtectEx(hProcess, (LPVOID) hInjectedModule, ntHeader.OptionalHeader.SizeOfImage, dwOldProtect, &dwOldProtect_)) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } /* restore protect for each section */ for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) { if (ntHeader.OptionalHeader.DataDirectory[i].VirtualAddress && ntHeader.OptionalHeader.DataDirectory[i].Size && lpDwSectionsProtect[i]) { if (!VirtualProtectEx(hProcess, (LPVOID) hInjectedModule, ntHeader.OptionalHeader.SizeOfImage, lpDwSectionsProtect[i], &dwOldProtect)) { _scitReleaseAndUnloadModule(hProcess, dwProcessId, lpLibPath, lpRemoteAddress, MEM_RELEASE, imageBuffer, lpDwSectionsProtect, ipd); return ipd; } } /* printf("%x\n", lpDwSectionsProtect[i]); */ } free(imageBuffer); imageBuffer = 0; } ipd.hProcess = hProcess; ipd.hModule = GetModuleHandle(0); ipd.hInjectedModule = hInjectedModule; ipd.bOk = TRUE; return ipd; }
/******************************** Scans a running process for patterns parameters ULONG pid [in] Process identifier pmempattern mempatterns [in] Memory patterns linked list return Value ERROR_SUCCESS : no error ERROR_VIRUS_INFECTED : a pattern matched ERROR_ACCESS_DENIED : cannot open process ********************************/ DWORD __fastcall processMemScan( _In_ ULONG pid, _In_ pmempattern mempatterns) { HANDLE hProcess; pmempattern currentPattern = mempatterns; BOOL continueScan; DWORD found = ERROR_SUCCESS; PVOID regionMemory; PVOID match; ULONG i = 0; MEMORY_BASIC_INFORMATION mbi; pmemoryRegion last, current; DWORD dwRead; last=NULL; if(pid == 0 || mempatterns == NULL) { return ERROR_INVALID_PARAMETER; } // opens the process with minimal required access rights. hProcess = OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE,pid); if(hProcess==NULL) { printf("\n\t\t[!] Cannot scan process.\n "); #ifdef DEBUG printf("\n\t\t[!] processMemScan :: OpenProcess() failed.\n",pid); #endif return ERROR_ACCESS_DENIED; } // gather the virtual memory regions of the process for(i = 1; VirtualQueryEx(hProcess,(PVOID)i,&mbi,sizeof(MEMORY_BASIC_INFORMATION))==sizeof(mbi) ; i += mbi.RegionSize) { current = (pmemoryRegion)malloc(sizeof(memoryRegion)); current->baseAddress=(ULONG)mbi.BaseAddress; current->size=mbi.RegionSize; current->protect=mbi.Protect; current->state=mbi.State; current->type=mbi.Type; current->blink=last; last=current; } // For each memory region while(current!=NULL) { // Search the pattern currentPattern=mempatterns; while(currentPattern != NULL) { continueScan = TRUE; // Memory access test if(currentPattern->protect!=0) { // tests the memory access rights if((currentPattern->protect & current->protect) == 0) { continueScan=FALSE; } } if(continueScan) { regionMemory = malloc(current->size); // copy the whole memory region if(ReadProcessMemory(hProcess,(PVOID)current->baseAddress,regionMemory,current->size,&dwRead)!=0) { // searchs the memory for the current pattern match = searchMem(currentPattern->pattern,currentPattern->patternlen,regionMemory, current->size); while(match != NULL) { found = ERROR_VIRUS_INFECTED; // match printf("\n\t\t[-] Pattern %d matched at 0x%.8x\n",currentPattern->patternId, ((ULONG)match-(ULONG)regionMemory+current->baseAddress)); // other ones? match = (PVOID)((ULONG)match+currentPattern->patternlen); match = searchMem(currentPattern->pattern,currentPattern->patternlen,match, ((ULONG)regionMemory + current->size - (ULONG)match)); } } free(regionMemory); } // next pattern currentPattern = (pmempattern)currentPattern->flink; } // next memory region current=(pmemoryRegion)current->blink; } // free current = last; while(current != NULL) { last = (pmemoryRegion)current->blink; free(current); current = last; } return found; }
BOOL __stdcall DumpProcessRange( IN DWORD dwProcessId, IN void* pStartAddr, IN DWORD dwcBytes, OUT void* pDumpedBytes, OUT char* szErrorStr) { BOOL bRet; HANDLE hProc; DWORD cb, cbFailure = 0, cb2Do, dwBlockSize; MEMORY_BASIC_INFORMATION minfo; char cBuff[100]; // get process handle hProc = OpenProcess( PROCESS_VM_READ, FALSE, dwProcessId ); if ( !hProc ) { lstrcpy( szErrorStr, "Error while querying process handle !" ); return FALSE; // ERR } // // first let's try 2 dump the whole block directly // bRet = ReadProcessMemory( hProc, pStartAddr, pDumpedBytes, dwcBytes, &cb ); CloseHandle( hProc ); if ( bRet ) goto TidyUp; // // scan the memory information // hProc = OpenProcess( PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId ); if ( !hProc ) { lstrcpy( szErrorStr, "Error while querying process handle !" ); return FALSE; // ERR } cb2Do = dwcBytes; minfo.BaseAddress = pStartAddr; while ( cb2Do ) { // get memory info bRet = VirtualQueryEx( hProc, minfo.BaseAddress, &minfo, sizeof(minfo)); if ( !bRet ) { lstrcpy( szErrorStr, "VirtualQueryEx() failed !" ); goto TidyUp; // ERR } #define f minfo.Protect dwBlockSize = min( minfo.RegionSize, cb2Do ); if ( pStartAddr ) // first region dump ? dwBlockSize -= (DWORD)pStartAddr - (DWORD)minfo.BaseAddress; if ( ((f & PAGE_GUARD) != 0) || // do we have access there ? ((f & PAGE_NOACCESS) != 0) ) { // // don't try 2 dump this memory part // // zero not dumped part in output buffer memset( MakePtr( PVOID, pDumpedBytes, dwcBytes - cb2Do ), 0, dwBlockSize); cbFailure += dwBlockSize; } else { // // dump normally // bRet = ReadProcessMemory( hProc, pStartAddr ? pStartAddr : minfo.BaseAddress, MakePtr( PVOID, pDumpedBytes, dwcBytes - cb2Do ), dwBlockSize, &cb); if ( pStartAddr ) // only non-zero on first region dump pStartAddr = NULL; if ( !bRet ) { // OK,no...zero not dumped part in output buffer memset( MakePtr( PVOID, pDumpedBytes, dwcBytes - cb2Do ), 0, dwBlockSize); cbFailure += dwBlockSize; } } // adjust vars minfo.BaseAddress = MakePtr( PVOID, minfo.BaseAddress, minfo.RegionSize ); cb2Do -= dwBlockSize; } bRet = TRUE; // ret an OK if ( cbFailure ) // were any bytes not dumpable ? { wsprintf( cBuff, "0x%X of 0x%X bytes could not be dumped\nand were padded with zeros.", cbFailure, dwcBytes); MessageBox( GetActiveWindow(), cBuff, "IntelliDump", MB_ICONWARNING ); } // // tidy up // TidyUp: CloseHandle( hProc ); return bRet; }