In Windows Assuming code as below is compiled without debugging info (no PDB) and loaded in ghidra.
disabled analysis on loading.
followed label entry to find the address of function main
went to main (0x140001000) and hit D to Disassemble and hit F to create a Function
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
int main(void)
{
PPEB mypeb = (PPEB)__readgsqword(0x60);
PRTL_USER_PROCESS_PARAMETERS proparm = mypeb->ProcessParameters;
printf("%S\n", proparm->ImagePathName.Buffer);
}
the decompiled function main would look as below with fuzzy pointer arithmetics and ugly casts
undefined8
FUN_140001000(undefined8 param_1,undefined8 param_2,undefined8 param_3,undefined8 param_4)
{
longlong unaff_GS_OFFSET;
FUN_1400010a0((longlong)&DAT_1400132e0,
*(undefined8 *)(*(longlong *)(*(longlong *)(unaff_GS_OFFSET + 0x60) + 0x20) + 0x68),
param_3,param_4);
return 0;
}
there are three pointer arithmetic
- (unaff_GS_OFFSET + 0x60)
- (unaff_GS_OFFSET + 0x60) + 0x20)
- (unaff_GS_OFFSET + 0x60) + 0x20) + 0x68)
so there must be three unknown structs/artifacts/something/anything...
lets start making this ugliness go away by adding structures
In DataTypeManager Select the binary -> right click ->new ->structure
create a new structure name it as unknown_struct_1 for now
under Description add a comment using only offset 0x60
enter 0x100 arbitrarily as size
create 2 more structs the same way unknown_struct_2
using offset 0x20 only
unknown_struct_3
using offset 0x68 only
edit unknown_struct_1 go to offset 0x60 and embed a pointer to unknown_struct_2 and give a Name say "Needs Name 1"
edit unknown_struct_2 go to offset 0x20 and embed a pointer to unknown_struct_3 and give a Name say "Needs Name 2"
after this select the longlong type of GS_OFFSET right click and retype the variable as pointer to unknown_struct_1
the decompilation will improve to
{
unknown_struct_1 *unaff_GS_OFFSET;
FUN_1400010a0((longlong)&DAT_1400132e0,
*(undefined8 *)&unaff_GS_OFFSET->NeedsName_1->NeedsName2->field_0x68,param_3,param_4
);
return 0;
}
now following 1400132e0 you get a tell tale sign of printf format string
DAT_1400132e0 XREF[1]: FUN_140001000:140001029(*)
1400132e0 25 ?? 25h %
1400132e1 53 ?? 53h S
1400132e2 0a ?? 0Ah
create a terminated c string at that address right click -> data -> terminatedcstring
s_%S_1400132e0 XREF[1]: FUN_140001000:140001029(*)
1400132e0 25 53 0a 00 ds "%S\n"
1400132e4 00 ?? 00h
the decompilation will further improve to
{
unknown_struct_1 *unaff_GS_OFFSET;
FUN_1400010a0((longlong)"%S\n",
*(undefined8 *)&unaff_GS_OFFSET->NeedsName_1->NeedsName2->field_0x68,param_3,param_4
);
return 0;
}
change the function signature of 0x1400010a0 to int __cdecl printf(char * formtstring,...) a vararg function
you will have a still better decompilation
{
unknown_struct_1 *unaff_GS_OFFSET;
printf("%S\n",*(undefined8 *)&unaff_GS_OFFSET->NeedsName_1->NeedsName2->field_0x68);
return 0;
}
the format string is %S so it must be printing a wide string (wchar_t *) or probably the buffer in a UNICODE_STRING structure
lets now go to the unknown_struct_3 at offset 0x68 embed a UNICODE_STRING * and give it a name
now the decompilation is almost nearer to the final shape
{
unknown_struct_1 *unaff_GS_OFFSET;
printf("%S\n",unaff_GS_OFFSET->NeedsName_1->NeedsName2->Some_wide_string);
return 0;
now after further reverse engineering you can infer unaff_GS_OFFSET is pointer to _TEB ->
whose 0ffset 0x60 Contains pointer to _PEB (Process Environemnt Block) ->
whose offset 0x20 contains a pointer to RTL_USER_PROCESS_PARAMETER ->
whose offset 0x68 contains a pointer to Unicode_string ImagePathName ->
whose offset 0x8 contains a pointer to wchar_t
so we need to shift the UNICODE_STRING * to 0x60 as UNICODE_STRING struct so that the member Buffer a wchar_t* will be at offset 0x68.
0:000> dt ntdll!_TEB ProcessEnvironmentBlock->ProcessParameters->ImagePathName.Buffer
+0x060 ProcessEnvironmentBlock :
+0x020 ProcessParameters :
+0x060 ImagePathName :
+0x008 Buffer : Ptr64 Wchar
0:000>
just rename the unknowns and need names
and you have a clean decompilation after changing the function signature of main to int main (void)
int main(void)
{
TEB *MyTeb;
printf("%S\n",(MyTeb->ProcessEnvironmentBlock->ProcessParameters->ImagePathName).Buffer);
return 0;
}