A Simple API Monitor

This is a simple Windbg script to monitor common Win32 API calls and display the strings, IPs, Ports, Registry keys passed to the APIs. The Win32 API is huge and I have used common APIs used by programs and malware. I coded this for fun 🙂

Usage: ApiMon.wds run; g;

You can remove APIs as you wish to minimize the output or you can add any API you desire. For example

bp DLLName!APIName @"$$>a<${$arg0} APIName FileNamePtr

bp kernelbase!CreateFileA @"$$>a<${$arg0} CreateFileA 1";

This is a sample output that uses CreateProcess API.

This is from running netcat.

Download: https://github.com/OsandaMalith/ApiMon

$$ ApiMon -  A simple API Monitor for Windbg
$$ Author : Osanda Malith Jayathissa (@OsandaMalith)
$$ E-Mail: osanda[cat]unseen.is
$$ Website: https://osandamalith.com 

aS LogPath @"C:\temp\Output.txt";

.catch {

	.if ${/d:$arg1} == 0 {
		.printf "Usage: ApiMon.wds run; g;";

	.if @@masm(not($scmp("${$arg1}", "run"))) {
		 .logopen /t ${LogPath};
		.if @@c++(((unsigned char *)&@$PEB->BeingDebugged)[0]) == @@masm(0y1) {
			r? $t5 = @@c++((unsigned long *)&@$PEB->BeingDebugged);
			eb $t5 @@masm(0y0);

		.if @@c++(((unsigned char *)&@$PEB->NtGlobalFlag)[0]) == @@masm(0y1110000) {
			r? $t6 = @@c++((unsigned long *)&@$PEB->NtGlobalFlag);
			eb $t6 @@masm(0y0);

		$$ Registry
		bp Advapi32!RegOpenKeyA @"$$>a<${$arg0} RegOpenKeyA";
		bp Advapi32!RegOpenKeyW @"$$>a<${$arg0} RegOpenKeyW";

		bp Kernelbase!RegOpenKeyExA @"$$>a<${$arg0} RegOpenKeyExA";
		bp Kernelbase!RegOpenKeyExW @"$$>a<${$arg0} RegOpenKeyExW";

		bp Kernelbase!RegQueryValueExA @"$$>a<${$arg0} RegQueryValueExA";
		bp Kernelbase!RegQueryValueExW @"$$>a<${$arg0} RegQueryValueExW";		

		bp Advapi32!RegQueryValueA @"$$>a<${$arg0} RegQueryValueA";
		bp Advapi32!RegQueryValueW @"$$>a<${$arg0} RegQueryValueW";

		bp Advapi32!RegCopyTreeA @"$$>a<${$arg0} RegCopyTreeA";
		bp Kernelbase!RegCopyTreeW @"$$>a<${$arg0} RegCopyTreeW";

		bp Kernelbase!RegCreateKeyExA  @"$$>a<${$arg0} RegCreateKeyExA";
		bp Kernelbase!RegCreateKeyExW @"$$>a<${$arg0} RegCreateKeyExW";	

		bp Advapi32!RegDeleteKeyA @"$$>a<${$arg0} RegDeleteKeyA";
		bp Advapi32!RegDeleteKeyW @"$$>a<${$arg0} RegDeleteKeyW";

		bp Advapi32!RegDeleteKeyValueA @"$$>a<${$arg0} RegDeleteKeyValueA";
		bp Advapi32!RegDeleteKeyValueW @"$$>a<${$arg0} RegDeleteKeyValueW";

		bp Kernelbase!RegDeleteKeyExA  @"$$>a<${$arg0} RegDeleteKeyExA";
		bp Kernelbase!RegDeleteKeyExW @"$$>a<${$arg0} RegDeleteKeyExW";		

		bp Advapi32!RegDeleteKeyTransactedA @"$$>a<${$arg0} RegDeleteKeyTransactedA";
		bp Advapi32!RegDeleteKeyTransactedW @"$$>a<${$arg0} RegDeleteKeyTransactedW";	

		bp Kernelbase!RegDeleteTreeA @"$$>a<${$arg0} RegDeleteTreeA";
		bp Kernelbase!RegDeleteTreeW @"$$>a<${$arg0} RegDeleteTreeW";	

		bp Kernelbase!RegDeleteValueA @"$$>a<${$arg0} RegDeleteValueA";
		bp Kernelbase!RegDeleteValueW @"$$>a<${$arg0} RegDeleteValueW";	

		bp Kernelbase!RegRestoreKeyA @"$$>a<${$arg0} RegRestoreKeyA";
		bp Kernelbase!RegRestoreKeyW @"$$>a<${$arg0} RegRestoreKeyW";	

		bp Advapi32!RegReplaceKeyA @"$$>a<${$arg0} RegReplaceKeyA";
		bp Advapi32!RegReplaceKeyW @"$$>a<${$arg0} RegReplaceKeyW";	

		bp Advapi32!RegSaveKeyA @"$$>a<${$arg0} RegSaveKeyA";
		bp Advapi32!RegSaveKeyW @"$$>a<${$arg0} RegSaveKeyW";	

		$$ File Operations
		bp kernelbase!CreateFileA @"$$>a<${$arg0} CreateFileA 1";
		bp kernelbase!CreateFileW @"$$>a<${$arg0} CreateFileW 1";
		bp kernelbase!DeleteFileA @"$$>a<${$arg0} DeleteFileW 1";
		bp kernelbase!DeleteFileW @"$$>a<${$arg0} DeleteFileW 1";

		bp kernelbase!FindFirstFileA @"$$>a<${$arg0} FindFirstFileA 1";
		bp kernelbase!FindFirstFileW @"$$>a<${$arg0} FindFirstFileW 1";

		bp kernel32!MoveFileA @"$$>a<${$arg0} MoveFileA 1";
		bp kernel32!MoveFileW @"$$>a<${$arg0} MoveFileW 1";

		bp kernelbase!GetFileAttributesA @"$$>a<${$arg0} GetFileAttributesA 1";

		bp kernelbase!GetFileAttributesExA @"$$>a<${$arg0} GetFileAttributesExA 1";
		bp kernelbase!GetFileAttributesExW @"$$>a<${$arg0} GetFileAttributesExW 1";

		bp kernel32!CopyFileA @"$$>a<${$arg0} CopyFileA 1";
		bp kernel32!CopyFileW @"$$>a<${$arg0} CopyFileW 1";

		bp kernel32!GetTempPathA @"$$>a<${$arg0} GetTempPathA 2";
		bp kernelbase!GetTempPathW @"$$>a<${$arg0} GetTempPathW 2";

		$$ Networking APIs
		bp WS2_32!connect @"$$>a<${$arg0} connect";
		bp WS2_32!bind @"$$>a<${$arg0} bind";
		bp WS2_32!WSAConnect @"$$>a<${$arg0} WSAConnect";
		bp WS2_32!gethostname @"$$>a<${$arg0} gethostname 1";
		bp WS2_32!gethostbyname @"$$>a<${$arg0} gethostbyname 1";
		bp WININET!FtpPutFileA @"$$>a<${$arg0} FtpPutFileA 2";
		bp WININET!FtpPutFileW @"$$>a<${$arg0} FtpPutFileW 2";

		bp WININET!InternetOpenA @"$$>a<${$arg0} InternetOpenA 1";
		bp WININET!InternetOpenW @"$$>a<${$arg0} InternetOpenW 1";

		$$ Others
		bp kernel32!CreateMutexA @"$$>a<${$arg0} CreateMutexA 3";
		bp kernel32!CreateMutexW @"$$>a<${$arg0} CreateMutexW 3";

		bp kernelbase!OutputDebugStringA @"$$>a<${$arg0} OutputDebugStringA 1";
		bp kernelbase!OutputDebugStringW @"$$>a<${$arg0} OutputDebugStringW 1";

		bp kernel32!WinExec @"$$>a<${$arg0} WinExec 1";

		bp SHELL32!ShellExecuteA @"$$>a<${$arg0} ShellExecuteA 3";
		bp SHELL32!ShellExecuteW @"$$>a<${$arg0} ShellExecuteW 3";

		bp KERNELBASE!CreateProcessA @"$$>a<${$arg0} CreateProcessA 1";
		bp KERNELBASE!CreateProcessW @"$$>a<${$arg0} CreateProcessW 1";

		sxi ld;
	.if @@masm(not($scmp("${$arg1}", "bind"))) { 
		.printf /D "<col fg=\"srcnum\"><b>\n${$arg1}\n</b></col>";
 		r $t5 =  @@masm(hi(@@c++(((unsigned long *)(((unsigned long *)@$csp)[2]))[0])));
 		.printf /D "<col fg=\"srcspid\"><b>Port: </b></col>";
 		.printf /D "<col fg=\"srcspid\">%d\n\n</col>", @@masm(hi(@@c++((unsigned long *) (( @$t5 >> 24 ) | (( @$t5 << 8) & 0xff0000 ) | ((@$t5 >> 8) & 0xff00) | ( @$t5 << 24)))));

	.if @@masm($spat("${$arg1}", "*connect*")) {
		.printf /D "<col fg=\"srcnum\"><b>\n${$arg1}\n</b></col>";
		r? $t0 = @@c++(((unsigned long *)@$csp)[2]) + 4;
		.printf /D "<col fg=\"srcspid\"><b>IP:   </b></col>";
		.printf /D "<col fg=\"srcspid\">%d.%d.%d.%d\n</col>", @@c++(((unsigned char *)@$t0)[0]), @@c++(((unsigned char *)@$t0)[1]), @@c++(((unsigned char *)@$t0)[2]), @@c++(((unsigned char *)@$t0)[3])
		r $t5 =  @@masm(hi(@@c++(((unsigned long *)(((unsigned long *)@$csp)[2]))[0])));
 		.printf /D "<col fg=\"srcspid\"><b>Port: </b></col>";
 		.printf /D "<col fg=\"srcspid\">%d\n\n</col>", @@masm(hi(@@c++((unsigned long *) (( @$t5 >> 24 ) | (( @$t5 << 8) & 0xff0000 ) | ((@$t5 >> 8) & 0xff00) | ( @$t5 << 24)))));

	.if @@masm($spat("${$arg1}", "Reg*")) {
		r $t6 = @@c++(((unsigned long *)@$csp)[2]);
		r $t7 = @@masm(low(@@c++(((unsigned long *)@$csp)[1])));

		.printf /D "<col fg=\"srckw\"><b>\n${$arg1}\n</b></col>";

		.if @$t7 == 0x0 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_CLASSES_ROOT\n</col>";
		.if @$t7 == 0x1 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_CURRENT_USER\n</col>";
		.if @$t7 == 0x2 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_LOCAL_MACHINE\n</col>";
		.if @$t7 == 0x3 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_USERS\n</col>";
		.if @$t7 == 0x4 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_PERFORMANCE_DATA\n</col>";
		.if @$t7 == 0x50 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_PERFORMANCE_TEXT\n</col>";
		.if @$t7 == 0x60 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_PERFORMANCE_NLSTEXT\n</col>";
		.if @$t7 == 0x5 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_CURRENT_CONFIG\n</col>";
		.if @$t7 == 0x6 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_DYN_DATA\n</col>";
		.if @$t7 == 0x7 {
			.printf /D "<col fg=\"srcspid\"><b>HKEY</b>  : HKEY_CURRENT_USER_LOCAL_SETTINGS\n</col>";

		.if @@masm($spat("${$arg1}", "*A")) {
			.printf /D "<col fg=\"srcspid\"><b>Value</b>: %ma\n\n</col>", @$t6;

		.if  @@masm($spat("${$arg1}", "*W")) {
			.printf /D "<col fg=\"srcspid\"><b>Value</b>: %mu\n\n</col>", @$t6;
	.printf /D "<col fg=\"emphfg\"><b>${$arg1}:  </b></col>"

	r $t4 = @@c++(((unsigned long *)@$csp)[${$arg2}]);

	.if @@masm($spat("${$arg1}", "*A")) {
		.printf /D "<col fg=\"srcspid\">%ma\n</col>", @$t4;

	.if  @@masm($spat("${$arg1}", "*W")) {
		.printf /D "<col fg=\"srcspid\">%mu\n</col>", @$t4;

2 thoughts on “A Simple API Monitor

Leave a Reply