Parsing PE header of sample analyzed by client

20 views
Skip to first unread message

Peter

unread,
Mar 21, 2025, 1:20:43 PMMar 21
to DynamoRIO Users
Hi Derek, Team,

stupid question, I am using the following code in my client (started via drrun). I tested it with 3-4 samples and it seems to work, but could you double check if you see any caveats or issues with the implementation ? The goal is to parse certain fields of the PE header of the sample which is instrumented with the DynamoRIO client app.

drrun.exe" -no_follow_children -c tracer.dll" -s 140001490 -e 1400014B9 -m hello_world_x64.exe -- hello_world_x64.exe

....

dr_insert_clean_call(drcontext, bb, instr, process_instr_trace_instr, FALSE, 2, OPND_CREATE_INTPTR(instr_addr), OPND_CREATE_INTPTR(trace_para));

....

void __cdecl process_instr_trace_instr(app_pc instr_addr_tmp, S_TRACE_PARA* tr)
{
void* drcontext;
size_t  instr_addr = (size_t) instr_addr_tmp;

drcontext = dr_get_current_drcontext();
dr_mcontext_t mc = { sizeof(mc),DR_MC_ALL };
dr_get_mcontext(drcontext, &mc);

if (instr_addr == tr->start) instr_trace_start_reached = TRUE;
if (instr_addr == tr->end)   instr_trace_end_reached = TRUE;

if ((instr_trace_start_reached == TRUE) && (first_time)) {

DWORD pid;
HMODULE hMods[1024];
DWORD cbNeeded;
IMAGE_DOS_HEADER dosHeader;
SIZE_T bytesRead;

pid = (DWORD) dr_get_process_id();

dr_printf("[TRACER] [DEBUG] [process_instr_trace_instr] Start address reached: instr_addr %zx Process PID %u (%s) Threat ID = %u \n",
            instr_addr, pid, dr_get_application_name(), dr_get_thread_id(drcontext), dr_lookup_module((byte *)instr_addr));

first_time = FALSE;

HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
if (hProcess == NULL) {
dr_printf("[ERROR] Get Process handle failed\n");
dr_exit_process(1);
}


if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {

LPVOID baseAddress = hMods[0];

// DOS Header
if (!ReadProcessMemory(hProcess, baseAddress, &dosHeader, sizeof(dosHeader), &bytesRead)) {
dr_printf("[ERROR] [process_instr_trace_instr] Reading DOS-Headers failed: %lu\n", GetLastError());
CloseHandle(hProcess);
dr_exit_process(1);
}

if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
dr_printf("[ERROR] [process_instr_trace_instr] Invalid DOS-Header.\n");
CloseHandle(hProcess);
dr_exit_process(1);
}

// NT Headers
IMAGE_NT_HEADERS ntHeaders;
LPVOID ntHeaderAddress = (LPBYTE)baseAddress + dosHeader.e_lfanew;
if (!ReadProcessMemory(hProcess, ntHeaderAddress, &ntHeaders, sizeof(ntHeaders), &bytesRead)) {
dr_printf("[ERROR] [process_instr_trace_instr] Reading NT-Headers failed: %lu\n", GetLastError());
CloseHandle(hProcess);
dr_exit_process(1);
}

if (ntHeaders.Signature != IMAGE_NT_SIGNATURE) {
dr_printf("[ERROR] [process_instr_trace_instr] Invalid NT-Header.\n");
CloseHandle(hProcess);
dr_exit_process(1);
}

dr_printf("[TRACER] [DEBUG] [process_instr_trace_instr] Image Base : %p\n", baseAddress);
dr_printf("[TRACER] [DEBUG] [process_instr_trace_instr] Entry Point: %p\n", (long long) baseAddress + ntHeaders.OptionalHeader.AddressOfEntryPoint);
dr_printf("[TRACER] [DEBUG] [process_instr_trace_instr] Image Size : 0x%X\n", ntHeaders.OptionalHeader.SizeOfImage);

}


}

thx a lot in advanced,
Peter

Enrico Deiana

unread,
Mar 24, 2025, 8:11:26 PMMar 24
to DynamoRIO Users
Hi Peter,

Your implementation seems ok (given my limited knowledge of windows).
Also, it seems that the output you get matches what you expect, correct?
A couple of very minor things: "instr_trace_end_reached" looks unused, "first_time" should be initialized to false (I guess it's a global, so likely it's already initialized to false by default, but good to double check).

Is this something you wanted to contribute to DynamoRIO? Or just a personal project?
If the former, there are a few guidelines you should follow before creating a pull request: https://dynamorio.org/page_contributing.html.
It would also be good to know what's the objective before making any pull request, to check whether or not we actually want to add it to the main DynamoRIO repo.

-Enrico

Peter

unread,
Mar 26, 2025, 2:21:12 AMMar 26
to DynamoRIO Users
Thx Enrico, for checking the code. Yes, the vars are globals. This is a project I was going to open source around May/June as a separate tool, but depending on where it goes, I could maybe build a separate project from it to contribute some PE parsing module to DynamoRio. I first need to finish this project, but I am absolutly willing to do that once this one is out of the door.

Derek Bruening

unread,
Mar 26, 2025, 11:45:37 AMMar 26
to Peter, DynamoRIO Users
DR already has PE parsing code and it exports module information for the application executable and all its libraries in an API https://dynamorio.org/dr__modules_8h.html for clients to use which seemingly already has all the information you are parsing here, right? If the goal is attributes of the application's modules, and some field is missing, it seems better to augment DR's existing API.

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/dynamorio-users/dd11f657-b785-40bc-8550-cbaa13721830n%40googlegroups.com.

Peter

unread,
Mar 27, 2025, 4:33:18 AMMar 27
to DynamoRIO Users
thx, Derek, I ll look into this. Maybe I can save some time.
Reply all
Reply to author
Forward
0 new messages