Malware development trick - part 36: Enumerate process modules. Simple C++ example.

cocomelonc.github.io · cocomelonc · 2 years ago · tutorial
quality 7/10 · good
0 net
Malware development trick - part 36: Enumerate process modules. Simple C++ example. - cocomelonc You are using an outdated browser. Please upgrade your browser to improve your experience. cocomelonc cybersec enthusiast. mathematician. author. speaker. hacker Follow Istanbul Email Twitter GitHub LinkedIn Custom Social Profile Link --> ﷽ Hello, cybersecurity enthusiasts and white hackers! Today, this post is the result of my own research on another popular malware development trick: get list of modules of target process. Let’s say we created successfully DLL injection to process. How to check if DLL in list of modules of our process? practical example First of all, we just use one of the methods to find target process PID. For example I used this one : typedef NTSTATUS ( NTAPI * fNtGetNextProcess )( _In_ HANDLE ph , _In_ ACCESS_MASK DesiredAccess , _In_ ULONG HandleAttributes , _In_ ULONG Flags , _Out_ PHANDLE Newph ); int findMyProc ( const char * procname ) { int pid = 0 ; HANDLE current = NULL ; char procName [ MAX_PATH ]; // resolve function address fNtGetNextProcess myNtGetNextProcess = ( fNtGetNextProcess ) GetProcAddress ( GetModuleHandle ( "ntdll.dll" ), "NtGetNextProcess" ); // loop through all processes while ( ! myNtGetNextProcess ( current , MAXIMUM_ALLOWED , 0 , 0 , & current )) { GetProcessImageFileNameA ( current , procName , MAX_PATH ); if ( lstrcmpiA ( procname , PathFindFileName (( LPCSTR ) procName )) == 0 ) { pid = GetProcessId ( current ); break ; } } return pid ; } Then, just use Module32First and Module32Next functions from Windows API. // function to list modules loaded by a specified process int listModulesOfProcess ( int pid ) { HANDLE mod ; MODULEENTRY32 me32 ; mod = CreateToolhelp32Snapshot ( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 , pid ); if ( mod == INVALID_HANDLE_VALUE ) { printf ( "CreateToolhelp32Snapshot error :( \n " ); return - 1 ; } me32 . dwSize = sizeof ( MODULEENTRY32 ); if ( ! Module32First ( mod , & me32 )) { CloseHandle ( mod ); return - 1 ; } printf ( "modules found: \n " ); printf ( "name \t\t\t base address \t\t\t size \n " ); printf ( "================================================================================= \n " ); do { printf ( "%#25s \t\t %#10llx \t\t %#10d \n " , me32 . szModule , me32 . modBaseAddr , me32 . modBaseSize ); } while ( Module32Next ( mod , & me32 )); CloseHandle ( mod ); return 0 ; } As you can see, the code is a bit similar to the PID search logic with CreateToolHelp32Snapshot , Process32First and Process32Next . So, the full source code is looks like this ( hack.c ): /* * hack.c - get the list of modules of the process. C++ implementation * @cocomelonc * https://cocomelonc.github.io/malware/2023/09/25/malware-tricks-36.html */ #include #include #include #include #include #include #pragma comment(lib, "ntdll.lib") #pragma comment(lib, "shlwapi.lib") typedef NTSTATUS ( NTAPI * fNtGetNextProcess )( _In_ HANDLE ph , _In_ ACCESS_MASK DesiredAccess , _In_ ULONG HandleAttributes , _In_ ULONG Flags , _Out_ PHANDLE Newph ); int findMyProc ( const char * procname ) { int pid = 0 ; HANDLE current = NULL ; char procName [ MAX_PATH ]; // resolve function address fNtGetNextProcess myNtGetNextProcess = ( fNtGetNextProcess ) GetProcAddress ( GetModuleHandle ( "ntdll.dll" ), "NtGetNextProcess" ); // loop through all processes while ( ! myNtGetNextProcess ( current , MAXIMUM_ALLOWED , 0 , 0 , & current )) { GetProcessImageFileNameA ( current , procName , MAX_PATH ); if ( lstrcmpiA ( procname , PathFindFileName (( LPCSTR ) procName )) == 0 ) { pid = GetProcessId ( current ); break ; } } return pid ; } // function to list modules loaded by a specified process int listModulesOfProcess ( int pid ) { HANDLE mod ; MODULEENTRY32 me32 ; mod = CreateToolhelp32Snapshot ( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 , pid ); if ( mod == INVALID_HANDLE_VALUE ) { printf ( "CreateToolhelp32Snapshot error :( \n " ); return - 1 ; } me32 . dwSize = sizeof ( MODULEENTRY32 ); if ( ! Module32First ( mod , & me32 )) { CloseHandle ( mod ); return - 1 ; } printf ( "modules found: \n " ); printf ( "name \t\t\t base address \t\t\t size \n " ); printf ( "================================================================================= \n " ); do { printf ( "%#25s \t\t %#10llx \t\t %#10d \n " , me32 . szModule , me32 . modBaseAddr , me32 . modBaseSize ); } while ( Module32Next ( mod , & me32 )); CloseHandle ( mod ); return 0 ; } int main ( int argc , char * argv []) { int pid = 0 ; // process ID pid = findMyProc ( argv [ 1 ]); printf ( "%s%d \n " , pid > 0 ? "process found at pid = " : "process not found. pid = " , pid ); if ( pid != 0 ) listModulesOfProcess ( pid ); return 0 ; } You can use this code to check if a DLL is in the list of modules of the target process. demo Let’s go to see this logic in action. Compile it: x86_64-w64-mingw32-g++ -O2 hack.c -o hack.exe -I /usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc ++ -static-libgcc -fpermissive -lshlwapi Then, open target process in the victim’s machine: And just run our hack.exe : . \hack.exe mspaint.exe Also, check with DLL injection logic: As you can see, everything is worked perfectly! =^..^= Keep in mind that this code may have limitations and dependencies on specific Windows APIs. Additionally, it relies on the process name for identification, which may not be unique. This trick is used by 4H RAT and Aria-body in the wild. I hope this post spreads awareness to the blue teamers of this interesting malware dev technique, and adds a weapon to the red teamers arsenal. Find process ID by name and inject to it Find PID via NtGetNextProcess 4H RAT Aria-body source code in github This is a practical case for educational purposes only. Thanks for your time happy hacking and good bye! PS. All drawings and screenshots are mine Share on Twitter Facebook LinkedIn You may also enjoy MacOS malware persistence 9: emond (The Event Monitor Daemon). Simple C example 3 minute read ﷽ MacOS malware persistence 8: periodic scripts. Simple C example 3 minute read ﷽ MacOS hacking part 13: sysinfo stealer via VirusTotal API. Simple C example 4 minute read ﷽ MacOS malware persistence 7: Re-opened applications. Simple C example 7 minute read ﷽