-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
352e61c
commit b920fc2
Showing
10 changed files
with
229 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
--- | ||
title: "Malware development trick - part 36: Enumerate process modules. Simple C++ example." | ||
date: 2023-09-25 03:30:00 +0300 | ||
header: | ||
teaser: "/assets/images/108/2023-09-25_13-38.png" | ||
categories: | ||
- malware | ||
tags: | ||
- windows | ||
- malware | ||
- red team | ||
- blue team | ||
- win32api | ||
--- | ||
|
||
﷽ | ||
|
||
Hello, cybersecurity enthusiasts and white hackers! | ||
|
||
![hack](/assets/images/108/2023-09-25_13-38.png){:class="img-responsive"} | ||
|
||
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? | ||
|
||
![hack](/assets/images/108/2023-09-25_13-10.png){:class="img-responsive"} | ||
|
||
### practical example | ||
|
||
First of all, we just use one of the methods to find target process PID. For example I used [this one](/malware/2023/05/26/malware-tricks-30.html): | ||
|
||
```cpp | ||
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, ¤t)) { | ||
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. | ||
```cpp | ||
// 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\tsize\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: | ||
|
||
```cpp | ||
/* | ||
* 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 <windows.h> | ||
#include <stdio.h> | ||
#include <winternl.h> | ||
#include <tlhelp32.h> | ||
#include <shlwapi.h> | ||
#include <psapi.h> | ||
|
||
#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, ¤t)) { | ||
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\tsize\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: | ||
```bash | ||
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 | ||
``` | ||
|
||
![hack](/assets/images/108/2023-09-25_12-47_1.png){:class="img-responsive"} | ||
|
||
Then, open target process in the victim's machine: | ||
|
||
![hack](/assets/images/108/2023-09-25_12-40.png){:class="img-responsive"} | ||
|
||
![hack](/assets/images/108/2023-09-25_12-41.png){:class="img-responsive"} | ||
|
||
And just run our `hack.exe`: | ||
|
||
```powershell | ||
.\hack.exe mspaint.exe | ||
``` | ||
|
||
![hack](/assets/images/108/2023-09-25_12-41_1.png){:class="img-responsive"} | ||
|
||
![hack](/assets/images/108/2023-09-25_12-47.png){:class="img-responsive"} | ||
|
||
![hack](/assets/images/108/2023-09-25_12-44.png){:class="img-responsive"} | ||
|
||
Also, check with DLL injection logic: | ||
|
||
![hack](/assets/images/108/2023-09-25_13-36.png){:class="img-responsive"} | ||
|
||
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. | ||
|
||
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](/pentest/2021/09/29/findmyprocess.html) | ||
[Find PID via NtGetNextProcess](/malware/2023/05/26/malware-tricks-30.html) | ||
[source code in github](https://github.com/cocomelonc/meow/tree/master/2023-09-25-malware-trick-36) | ||
|
||
> 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* |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.