StoneHeart Posted July 15, 2013 Posted July 15, 2013 Im finishing my exe loader which run exe from memory.All went fine but now im facing problem with vb6 exe.When i try loading resource data, the app crash because it cant find the resource. Does anyone know what is the problem with my loader to load vb6 exe? Some example to fix the problem would be nice. Thanks.
grizzmo Posted July 15, 2013 Posted July 15, 2013 As far as I know, not all .exe's can be run from memory.
Nacho_dj Posted July 15, 2013 Posted July 15, 2013 More details are needed to better understand your issue. How do you launch your executable? And how do you load resources?
StoneHeart Posted July 15, 2013 Author Posted July 15, 2013 (edited) @grizzmoI think all exe can be executed such way. Atleast with relocation table exist. @Nacho_djI launch the exe using peloader method ie load it in memory, fix import, fix relocation etc Tested on self code vb6 exe.I load resource using vb6 load resource method ie loadresstring function.On normal execution it works but when use peloader, it didnt work.Got error like resource id 101 doesnt exist. Basically the vb6 exe run when i didnt patch the peb->imagebase but when i patch it, the exe doesnt want to run and an error message appear ie "Error................; quiting"The error message doesnt come from my code but i think its from vb6 vm. I had no clue with what might produce such error. Please help. P/S The peb patching method that i use was taken from zombie inconexe code (adjustwindowosstructure) My peloader were based on that source code. Appearently zombie code didnt work with vb6 exe either. Edited July 15, 2013 by StoneHeart
Nacho_dj Posted July 15, 2013 Posted July 15, 2013 Ok, try to find at memory the entire resources section, loaded in the address that they should be, as PE header shows. If they are not loaded at the expected address, the error you mentioned will be displayed for sure.Resources data are dependent of the RVA address of their PE section, so if they are loaded in a different address, it won't work.
StoneHeart Posted July 15, 2013 Author Posted July 15, 2013 Ok i will try that. ... You know, i have tested any exe compiled using delphi and c/c++. All works fine.Why when i "adjustwindowosstructure" aka patch the peb, the vb6 exe wont run. Without it run.I think the problem is i really need to patch the peb because if i didnt patch the peb all exe including delphi and c/c++ wont work like resource isnt loading (i know it because when testing gui exe, the icon is missing).But since when i patch peb the vb6 exe wont run, i cant find the solution for it. Any other idea?
Nacho_dj Posted July 15, 2013 Posted July 15, 2013 Ok, let's see it in another way.If you dump from memory the executable loaded by the system, and you dump again the executable loaded by your loader, the dumps should be identical, at least in resources section. Try that to find if this condition is reached... any difference found will give you a clue about what is being missed...
StoneHeart Posted July 17, 2013 Author Posted July 17, 2013 (edited) Im a little bit noob at dumping processes but... Here is a little bit of the patching method ive done before jumping to EP:- dwImageBase = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);...PPEB pPeb;PPEB_LDR_DATA pLdrData;PLDR_ENTRY pLdrEntry;__asm PUSH FS:[0x30]__asm POP pPebpPeb->ImageBaseAddress = dwImageBase; Edited July 21, 2013 by StoneHeart
Nacho_dj Posted July 18, 2013 Posted July 18, 2013 If you assign an arbitrary address as ImageBase to an executable not owning a relocations data section, it will probably crash.You must load the executable at Imagebase address of PE header.So try to force VirtualAlloc to create a region starting at ImageBase address of PE header of your executable.
grizzmo Posted July 18, 2013 Posted July 18, 2013 (edited) I was on a forum a while ago and downloaded a c++ runpe with loader as you wish, but a few minutes later the runpe thread was closed, because the runpe is worth 5.000 US dollar and wasn't supposed to be there. Could this be possible? Regards, grizzmo Edited July 18, 2013 by grizzmo
StoneHeart Posted July 18, 2013 Author Posted July 18, 2013 (edited) If you assign an arbitrary address as ImageBase to an executable not owning a relocations data section, it will probably crash.You must load the executable at Imagebase address of PE header.So try to force VirtualAlloc to create a region starting at ImageBase address of PE header of your executable. The exe has relocation table and all the necassary stuff has been done. I was on a forum a while ago and downloaded a c++ runpe with loader as you wish, but a few minutes later the runpe thread was closed, because the runpe is worth 5.000 US dollar and wasn't supposed to be there. Could this be possible? Regards, grizzmo RunPE need to spawn another exe in suspended state. The one im trying to achieve is like running 2 exe in 1 process (The loader and the exe in memory). --- Is there any working sample to run 2 exe in 1 process? Edited July 18, 2013 by StoneHeart
grizzmo Posted July 18, 2013 Posted July 18, 2013 (edited) But getting the .exe into memory, therefore you should have a runpe, right? Otherwish you can do something like createprocess, from .exe.I used to start/load .exe's from an old tutorial from Goppit from ARTeam, which includes explanation and code on loaders to a bit more advanced loaders. Titel of tutorial: Win32_Assembler_Coding_for_Crackers_by_Goppit_v11 I can upload a copy of his tutorial, if you want to take a look. Edited July 18, 2013 by grizzmo
StoneHeart Posted July 18, 2013 Author Posted July 18, 2013 But getting the .exe into memory, therefore you should have a runpe, right? Otherwish you can do something like createprocess, from .exe. I used to start/load .exe's from an old tutorial from Goppit from ARTeam, which includes explanation and code on loaders to a bit more advanced loaders. Titel of tutorial: Win32_Assembler_Coding_for_Crackers_by_Goppit_v11 I can upload a copy of his tutorial, if you want to take a look. Sure, why not --- Anyway here is the sample im testing (Source are not mine). It can load vb6 app but cant load resource. #include <Windows.h> #define MAKE_ORDINAL(val) (val & 0xffff) int load_imports(IMAGE_IMPORT_DESCRIPTOR *imp_desc, void *load_address) { while (imp_desc->Name || imp_desc->TimeDateStamp) { IMAGE_THUNK_DATA *name_table, *address_table, *thunk; char *dll_name = (char *)load_address + imp_desc->Name; HMODULE module; module = LoadLibrary(dll_name); if (!module) { printf("error loading %s\n", dll_name); return 0; } name_table = (IMAGE_THUNK_DATA *)((char *)load_address + imp_desc->OriginalFirstThunk); address_table = (IMAGE_THUNK_DATA *)((char *)load_address + imp_desc->FirstThunk); /* if there is no name table, use address table */ thunk = name_table == load_address ? address_table : name_table; if (thunk == load_address) return 0; while (thunk->u1.AddressOfData) { unsigned char *func_name; /* is ordinal? */ if (thunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) func_name = (unsigned char *)MAKE_ORDINAL(thunk->u1.Ordinal); else func_name = ((IMAGE_IMPORT_BY_NAME *)((char *)load_address + thunk->u1.AddressOfData))->Name; /* address_table->u1.Function = (DWORD)GetProcAddress(module, (char *)func_name); */ address_table->u1.Function = (DWORD)GetProcAddress(module, (char *)func_name); thunk++; address_table++; } imp_desc++; } return 1; } void fix_relocations(IMAGE_BASE_RELOCATION *base_reloc, DWORD dir_size, DWORD new_imgbase, DWORD old_imgbase) { IMAGE_BASE_RELOCATION *cur_reloc = base_reloc, *reloc_end; DWORD delta = new_imgbase - old_imgbase; reloc_end = (IMAGE_BASE_RELOCATION *)((char *)base_reloc + dir_size); while (cur_reloc < reloc_end && cur_reloc->VirtualAddress) { int count = (cur_reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); WORD *cur_entry = (WORD *)(cur_reloc + 1); void *page_va = (void *)((char *)new_imgbase + cur_reloc->VirtualAddress); while (count--) { /* is valid x86 relocation? */ if (*cur_entry >> 12 == IMAGE_REL_BASED_HIGHLOW) *(DWORD *)((char *)page_va + (*cur_entry & 0x0fff)) += delta; cur_entry++; } /* advance to the next one */ cur_reloc = (IMAGE_BASE_RELOCATION *)((char *)cur_reloc + cur_reloc->SizeOfBlock); } } IMAGE_NT_HEADERS *get_nthdrs(void *map) { IMAGE_DOS_HEADER *dos_hdr; dos_hdr = (IMAGE_DOS_HEADER *)map; return (IMAGE_NT_HEADERS *)((char *)map + dos_hdr->e_lfanew); } /* returns EP mem address on success * NULL on failure */ void *load_pe(void *fmap) { IMAGE_NT_HEADERS *nthdrs; IMAGE_DATA_DIRECTORY *reloc_entry, *imp_entry; void *vmap; WORD nsections, i; IMAGE_SECTION_HEADER *sec_hdr; size_t hdrs_size; IMAGE_BASE_RELOCATION *base_reloc; nthdrs = get_nthdrs(fmap); reloc_entry = &nthdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; /* no reloc info? */ if (!reloc_entry->VirtualAddress) return NULL; /* allocate executable mem (.SizeOfImage) */ vmap = VirtualAlloc(NULL, nthdrs->OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!vmap) return NULL; /* copy the Image + Sec hdrs */ nsections = nthdrs->FileHeader.NumberOfSections; sec_hdr = IMAGE_FIRST_SECTION(nthdrs); hdrs_size = (char *)(sec_hdr + nsections) - (char *)fmap; memcpy(vmap, fmap, hdrs_size); /* copy the sections */ for (i = 0; i < nsections; i++) { size_t sec_size; sec_size = sec_hdr.SizeOfRawData; memcpy((char *)vmap + sec_hdr.VirtualAddress, (char *)fmap + sec_hdr.PointerToRawData, sec_size); } /* load dlls */ imp_entry = &nthdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; if (!load_imports((IMAGE_IMPORT_DESCRIPTOR *) ((char *)vmap + imp_entry->VirtualAddress), vmap)) goto cleanup; /* fix relocations */ base_reloc = (IMAGE_BASE_RELOCATION *)((char *)vmap + reloc_entry->VirtualAddress); fix_relocations(base_reloc, reloc_entry->Size, (DWORD)vmap, nthdrs->OptionalHeader.ImageBase); return (void *)((char *)vmap + nthdrs->OptionalHeader.AddressOfEntryPoint); cleanup: VirtualFree(vmap, 0, MEM_RELEASE); return NULL; } int vmem_exec(void *fmap) { void *ep; ep = load_pe(fmap); if (!ep) return 0; __asm { mov ebx, fs:[0x30] mov eax, ep call eax } return 1; } BYTE *FileToMem(LPCSTR szFileName, DWORD *dwSize) { BOOL bResult = FALSE; HANDLE hFile; DWORD dwRead; BYTE *pBuffer = NULL; hFile = CreateFileA(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); if (hFile) { *dwSize = GetFileSize(hFile, NULL); if (*dwSize > 0) { pBuffer = (BYTE *)VirtualAlloc(NULL, *dwSize + 3, MEM_COMMIT, PAGE_READWRITE); if (pBuffer) { SetFilePointer(hFile, NULL, NULL, FILE_BEGIN); ReadFile(hFile, pBuffer, *dwSize, &dwRead, NULL); if (dwRead == *dwSize) return pBuffer; } } CloseHandle(hFile); } return NULL; } int _tmain(int argc, _TCHAR* argv[]) { BYTE *bvByte; DWORD dwSize; bvByte = FileToMem("c:\\vbapp.exe", &dwSize); vmem_exec(bvByte); return 0; } Any way around to make it to work with vb app so that the resource is working? Thanks.
grizzmo Posted July 18, 2013 Posted July 18, 2013 (edited) ASM tutorial from Goppit ARTeam: A bit late, but this afternoon mediafire kept uploading and uploading over and over. I left their webpage, because off the error. I now looked and the tutorial was uploaded multiple times! Link removed. Edited September 17, 2013 by grizzmo
grizzmo Posted July 18, 2013 Posted July 18, 2013 What do you mean with: Can't load resource? You mean files needed by vb6.exe? I send you a pm, maybe wiht an answer.
StoneHeart Posted July 18, 2013 Author Posted July 18, 2013 (edited) What do you mean with: Can't load resource? You mean files needed by vb6.exe? I send you a pm, maybe wiht an answer. Can't load the vb6 app resource like string data, image etc. Thanks for the pm but still not solving the issues. Anyone who try the source do help find the fix. Thanks. Edited July 18, 2013 by StoneHeart
Nacho_dj Posted July 18, 2013 Posted July 18, 2013 As I told you, dump it to find if resources are at the right address, and addresses in the executable referencing resources are right also. To dump it: get CFF ExploreSuite, open Task manager, select your process and choose from contextual menu: "Dump PE" Then compare with dump of the executable loaded by system itself...
grizzmo Posted July 18, 2013 Posted July 18, 2013 (edited) Correct me, if I am wrong: You want to go programming in visual basic or start visual basic with the main exe = vb6.exe, loaded in memory instead of clicking on the file in your vb6 folder or the shortcut? Is this pure for the fact you can't get it to run yet, while other files do run, or do you want the file to run in memory for a purpose? To be more clear: with resources you mean resources of the vb6.exe or do you mean all the files vb6.exe is accessing when you are programming? Edit: I found this code, I am looking now too I hope this helps. lude <stdio.h> #include <windows.h> #include <cstdlib> #include <string> using namespace std; // [SRC] Patch ImageBase in PEB // http://www.ic0de.org/showthread.php?8435-SRC-Patch-ImageBase-in-PEB // // Coded by RTFLOL // Released on http://hackhound.org/ // Date: 2/1/2010 /* This application patches an ImageBase of an external executable and replaces it with the path of this file. Please give credits if you use. Don't be a ripper fag, k? */ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef struct _PROCESS_BASIC_INFORMATION { LONG ExitStatus; PVOID PebBaseAddress; ULONG_PTR AffinityMask; LONG BasePriority; ULONG_PTR UniqueProcessId; ULONG_PTR ParentProcessId; } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; typedef LONG (WINAPI *_NtQueryInformationProcess)( HANDLE ProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, DWORD ProcessInformationLength, PDWORD ReturnLength ); _NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); int Patch(DWORD dwPid, WCHAR *path, WCHAR *cmdLine) { // // Get Handle // HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); PROCESS_BASIC_INFORMATION pbi; NtQueryInformationProcess(hProcess, 0, &pbi, sizeof(pbi), NULL); PVOID peb = pbi.PebBaseAddress; PVOID rtlUserProcParamsAddress = NULL; if (!ReadProcessMemory(hProcess, (PCHAR)peb + 0x10, &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) { printf("ERROR: Could not read rtlUserProcParamsAddress!\n"); return GetLastError(); } UNICODE_STRING Current_ImageBase; if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x38, &Current_ImageBase, sizeof(Current_ImageBase), NULL)) { printf("ERROR: Could not read ImageBase of the target process.\n"); return GetLastError(); } // // Update data // WCHAR *input; LPVOID pNewAddr; // // <-- Path --> // input = path; Current_ImageBase.Length = lstrlenW(input) * 2; pNewAddr = VirtualAllocEx(hProcess, NULL, Current_ImageBase.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!pNewAddr) { printf("ERROR: Could not allocate memory in target process.\n"); return GetLastError(); } if(!WriteProcessMemory(hProcess, pNewAddr, input, Current_ImageBase.Length, NULL)) { printf("ERROR: Failed to write to address.\n"); return GetLastError(); } Current_ImageBase.Buffer = (WCHAR*)pNewAddr; if(!WriteProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x38, &Current_ImageBase, sizeof(Current_ImageBase), NULL)) { printf("ERROR: Failed to reflect change back to PEB.\n"); return GetLastError(); } // // <-- cmdLine --> // input = cmdLine; Current_ImageBase.Length = lstrlenW(input) * 2; pNewAddr = VirtualAllocEx(hProcess, NULL, Current_ImageBase.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!pNewAddr) { printf("ERROR: Could not allocate memory in target process.\n"); return GetLastError(); } if(!WriteProcessMemory(hProcess, pNewAddr, input, Current_ImageBase.Length, NULL)) { printf("ERROR: Failed to write to address.\n"); return GetLastError(); } Current_ImageBase.Buffer = (WCHAR*)pNewAddr; if(!WriteProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40, &Current_ImageBase, sizeof(Current_ImageBase), NULL)) { printf("ERROR: Failed to reflect change back to PEB.\n"); return GetLastError(); } // // Done // return 1; } int main(void) { wchar_t *path = L"c:\\windows\\aaa.cmd", *cmdLine = L"c:\\windows\\aaa.cmd test"; if (Patch( 3032, path, cmdLine)) { printf("\n... All done. <!>\n"); } else { printf("\n... Faile'd. <!>.\n"); } system("PAUSE"); return 0; } Edited July 18, 2013 by grizzmo
StoneHeart Posted July 19, 2013 Author Posted July 19, 2013 (edited) As I told you, dump it to find if resources are at the right address, and addresses in the executable referencing resources are right also. To dump it: get CFF ExploreSuite, open Task manager, select your process and choose from contextual menu: "Dump PE" Then compare with dump of the executable loaded by system itself... Here is the file for testing with the source ive posted above. If you run the file normally, all works fine but when loaded using the loader something went wrong with the resource. Hope you can help find the solution. TestForLoader.rar Here is the vb code for the test app. Option ExplicitPrivate Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As LongPrivate Sub Command1_Click() Dim s As String * 260 On Error GoTo Hell GetModuleFileName 0, s, 260 MsgBox s, , "Exe Path" Exit Sub Hell: MsgBox Err.Description, , "Error!"End SubPrivate Sub Command2_Click() Dim s As String On Error GoTo Hell s = LoadResString(101) 'Should return Hello World! MsgBox s, , "It works!" Exit Sub Hell: MsgBox Err.Description, , "Error!"End SubPrivate Sub Command3_Click() EndEnd Sub Correct me, if I am wrong: You want to go programming in visual basic or start visual basic with the main exe = vb6.exe, loaded in memory instead of clicking on the file in your vb6 folder or the shortcut? Is this pure for the fact you can't get it to run yet, while other files do run, or do you want the file to run in memory for a purpose? To be more clear: with resources you mean resources of the vb6.exe or do you mean all the files vb6.exe is accessing when you are programming? I made a vb6 app, store it inside loader as a resource data. I extract the exe bin to memory then execute it. Its much like runpe you told me but this method im using is somewhat different. It can run 2 exe in 1 process. Not using process howling/forking etc. Btw, thanks for the source but i already test it (same issues =\) before i post my problem here Edited July 19, 2013 by StoneHeart
grizzmo Posted July 21, 2013 Posted July 21, 2013 I just looked here again. "I made a vb6 app, store it inside loader as a resource data. I extract the exe bin to memory then execute it." Here is something which make me doubt: " I extract the exe bin to memory then execute it." I can do these things with vb.net and this is not how it works. grizzmo
StoneHeart Posted July 21, 2013 Author Posted July 21, 2013 I just looked here again. "I made a vb6 app, store it inside loader as a resource data. I extract the exe bin to memory then execute it." Here is something which make me doubt: " I extract the exe bin to memory then execute it. I can do these things with vb.net and this is not how it works. grizzmo I can do it too with c++ for .net app but its only working for .net based app though its a different story on what i wanna achieve here. My stuff works fine with other app but i dunno how to solve the issues with vb6 app =\ Since i have posted the source and sample app to test with, does anyone found any clue on what makes the issues?
grizzmo Posted July 21, 2013 Posted July 21, 2013 I think the answer is related in: injecting native to non native and vice versa etc.
StoneHeart Posted July 22, 2013 Author Posted July 22, 2013 I guess we cant inject vb6 app on our process
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now