Skip to content

Tracing syscalls

hasherezade edited this page Dec 10, 2024 · 16 revisions

Tracing syscalls

Tracing syscalls can be enabled in TinyTracer.ini, by setting:

TRACE_SYSCALL=True

analogously, it can be disabled by:

TRACE_SYSCALL=False

Syscalls Table

Syscalls Table allows to map syscall ID to the corresponding function's name. Thanks to this feature, we get the results in more human-readable form. Tiny Tracer is shipped with a helper tool syscall_extract.exe that allows to automatically generate the syscalls table for a current Windows version. This tool is automatically called by run_me.bat at the beginning of tracing. The relevant fragment:

https://github.com/hasherezade/tiny_tracer/blob/461c5ce8978cf9d6c521c9a993124d108d7a209b/install32_64/run_me.bat#L60

if NOT exist %SYSCALLS_TABLE% (
	if exist %PIN_TOOLS_DIR%\syscall_extract.exe (
		%PIN_TOOLS_DIR%\syscall_extract.exe %SYSCALLS_TABLE%
	)
)

Watching syscall parameters

Tracing parameters of selected syscalls can be enabled similarly to tracing parameters of functions.

In order to enable this option, you need to:

  1. Create a list of syscalls that you want to watch, in the following format:
<SYSCALL>;[syscal number];[params_count]

Example:

<SYSCALL>;0x36;4
<SYSCALL>;0x20;2
  1. Append it to the same file that is used to watch parameters of functions, i.e. params.txt.

Note, that if the syscalls table is loaded, syscalls parameters can also be traced by the corresponding function's name.

Example:

params.txt

ntdll;NtSetInformationThread;4
<SYSCALL>;0x19;4

Fragment of the tracelog generated with the above settings:

[...]
7605;SYSCALL:0xd(NtSetInformationThread)
NtSetInformationThread:
	Arg[0] = 0xfffffffffffffffe = 18446744073709551614
	Arg[1] = 0x0000000000000011 = 17
	Arg[2] = 0
	Arg[3] = 0

75c1;SYSCALL:0x19(NtQueryInformationProcess)
SYSCALL:0x19:
	Arg[0] = 0xffffffffffffffff = 18446744073709551615
	Arg[1] = 0x0000000000000007 = 7
	Arg[2] = ptr 0x000000f6befcf690 -> {\x00\x00\x00\x00\x00\x00\x00\x00}
	Arg[3] = 0x0000000000000004 = 4
[...]

Demo

Indirect syscalls

Tiny Tracer allows also to trace syscalls that were called indirectly, by the method described i.e. here.

Executed functions are logged along with the function that was used as a proxy. For example:

17caf8;kernel32.GetStartupInfoW
1850;kernel32.GetModuleHandleA
1ead;ntdll.[ZwResumeThread+12]* -> NtCreateSection

As we can read from the tracelog, the function NtCreateSection was called at RVA = 0x1ead, by a jump to the end of Nt/ZwResumeThread function.

The role of this jump was just to execute the syscall that was passed via RAX:

We can trace the arguments of indirect syscalls just like any other syscalls, by listing them in the params.txt file.

Example - params.txt:

<SYSCALL>;0x28;10
ntdll;NtCreateSection;7

Result:

17cb7b;kernel32.SetUnhandledExceptionFilter
17caf8;kernel32.GetStartupInfoW
1850;kernel32.GetModuleHandleA
1ead;ntdll.[ZwResumeThread+12]* -> NtCreateSection
NtCreateSection:
	Arg[0] = ptr 0x000000000014f3d8 -> {\x00\x00\x00\x00\x00\x00\x00\x00}
	Arg[1] = 0x00000000000f001f = 983071
	Arg[2] = 0
	Arg[3] = ptr 0x000000000014f3c0 -> {\xf6\xee\x01\x00\x00\x00\x00\x00}
	Arg[4] = 0x0000000000000040 = 64
	Arg[5] = 0x0000000008000000 = 134217728
	Arg[6] = 0

1ead;ntdll.[ZwOpenProcessTokenEx+12]* -> NtMapViewOfSection
SYSCALL:0x28:
	Arg[0] = 0x00000000000001a8 = 424
	Arg[1] = 0xffffffffffffffff = 18446744073709551615
	Arg[2] = ptr 0x000000000014f3c8 -> {\x00\x00\x00\x00\x00\x00\x00\x00}
	Arg[3] = 0
	Arg[4] = 0
	Arg[5] = 0
	Arg[6] = ptr 0x000000000014f3a0 -> {\xf6\xee\x01\x00\x00\x00\x00\x00}
	Arg[7] = 0x0000000000000002 = 2
	Arg[8] = 0
	Arg[9] = 0x0000000000000004 = 4