http://evilcodecave.blogspot.com/2009/11/dnascan-malicious-network-activity.html
DNAScan Malicious Network Activity Reverse Engineering
November 28, 2009Device Drivers Vulnerability Research, Avast a real case
September 24, 2009In the past days I worked intensively on Antivirus’s Device Drivers bugs, at the actual state of art the major part of well known AVs suffer of basical and more hidden bugs. The totality of AVs that I’ve checked presents defects that could be maliciously used to takeover an Antivirus Infrastructure and in some case the entire Operating System with attacks like DoS and/or Remote/Local Privilege Escalation.
I want to make a precisation here, exists an important difference between Bug and Vulnerability, simply bugs does not affects the integrity of a system and does not constitute a true danger. Vulnerabilities constitutes an effective risk for systems integrity, included informations contained inside it. When we are dealing with applications specifically devoted to security, every bug could be considered a vulnerability, because an attacker could block/kill overcome checks performed by the application itself and propagate in system and produce damages. Just think to a basical crash that could affect an Antivirus could be implemented into a malicious application that checks the presence of AVs and induces the bug.
In this little post we are going to see some defects of last device drivers used by Avast, I’m precisely talking of
- Build Number: 4.8.1351.0
Avast loads the following drivers:
- Aasvmker4.sys
- aswMon2.sys
- aswRdr.sys
- aswSP.sys
Avast loads the following Drivers could be tested by fuzzing IOCTLs, for this task could be used IOCTL Fuzzer and Kartoffel. Let’s disassemble the first driver, Aavmker4.sys that from DeviceIoControl hook appears to be heavy used. This is the DriverEntry()drivers
00010748 mov eax, [ebp+DriverObject]
0001074B push offset NotifyRoutine ; NotifyRoutine
00010750 mov dword ptr [eax+70h], offset sub_1098C ; DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_1098C;
00010757 call PsSetCreateProcessNotifyRoutine
sub_1098C contains the switch statement to handle various IOCTL notifications, essentially IOCTL check is structured in form of nested If and Switches.
001098C ; int __stdcall sub_1098C(int, PIRP Irp)
000109C4 mov ecx, 0B2D6002Ch
000109C9 cmp eax, ecx
000109CB ja loc_10D12
000109D1 jz loc_10CE9
Checks if IOCTL is less or equal to 0x0B2D6002C, if condition is true checks if IOCTL is exactly 0x0B2D6002C a certain task is performed by the device driver and finally ends with a classical
epilogue:
IofCompleteRequest(X, 0);
return value;
By monitoring Aavmker4.sys activity, with a DeviceIoControl hook emerges that the most used IOCTLs are:
- 0xB2D60030
- 0xB2D60034
Now we have two possibilities the first is to fuzz these IOCTLs and check crash dump if happens and after check code for more details, the second possibility is to invert the check order.
This the xml configuration to test Aavmker4.sys
<allow>
<drivers>
<entry>Aavmker4.sys</entry>
</drivers>
<devices>
<entry>\Device\AavmKer4</entry>
</devices>
<!–
IRP I/O Control Code
–>
<ioctls>
<entry>0xb2d60030</entry>
<entry>0xb2d60034</entry>
</ioctls>
<processes>
<entry>ashServ.exe</entry>
</processes>
</allow>
launch fuzzer and Avast Scan, as you can see Driver resists to Fuzzing attempts, its time to see code referred to 0xB2D60030 and 0xB2D60034.
0xB2D60030
00010D25 cmp eax, 0B2D60030h
00010D2A jz short loc_10DA8
00010D2C cmp eax, 0B2D60034h
00010D31 jz short loc_10D5B
00010DC5 mov edi, [ebx+0Ch]
00010DC8 cmp esi, 878h
00010DCE jz short loc_10DDA ;Check buffer size
00010DD0 push offset aIoctl_aavm_sta ; “******* IOCTL_AAVM_START_REQUEST_AND_SE”…
00010DD5 jmp loc_10ABA ;Jump to Io Completion
If buffer size differs from 878h Dbg Prints an error message, else supplied buffer is correctly sanitized via MmUserProbeAddress, MmIsAddressValid. We can say that this IOCTL is correctly handled.
0xB2D60034:
00010D5B cmp esi, 8
00010D5E jnz loc_10AC0 ;If differs from 8 return STATUS_INVALID_PARAMETER
00010D64 call PsGetCurrentProcessId
Now let’s test aswSP.sys. In Device Driver vulnerabilty research it’s fundamental to have a complete log of all activities of a driver, this can be obtained by correctly planning a battery of test unit. Each test should correspond to a primitive logic operation performed by an application that makes use of driver. I usually build several mini logs for each activity and finally a complete log. Here a little list of monitoring primitives:
- On Load
- On apparent Idle
- On Working
- On Shutdown
- Various, like On Surprise Stop
This will give us a complete report of all activities and involved IOCTL. In the specific case of aswMon2.sys we can isolate the following:
- 0xb2c80018
- 0xb2c80014
- 0xb2c80020
- 0xB2c800C0
- 0xB2c800C4
- 0xB2c800C8
From IOCTL Logger we can see that 0xB2c800C0 is heavly used, time to locate Ioctl Dispatcher:
0001178B and dword ptr [ebx+34h], 0
0001178F mov dword ptr [ebx+6Ch], offset sub_11FB6
00011796 mov dword ptr [ebx+28h], offset off_18988
C like:
v2->DriverUnload = 0;
v2->MajorFunction[13] = (PDRIVER_DISPATCH)sub_11FB6;
v2->FastIoDispatch = (PFAST_IO_DISPATCH)&unk_18988;
with a bit of research we land to sub_10B82 that contains the switch for Ioctls.
00010BBD mov eax, 0B2C80018h
00010BC2 cmp ecx, eax
00010BC4 push edi
00010BC5 ja loc_11066
00010BCB jz loc_10F70
00010BD1 cmp ecx, 0B2C80008h
00010BD7 jz short loc_10C3C
00010BD9 cmp ecx, 0B2C8000Ch
00010BDF jz short loc_10C16
00010BE1 cmp ecx, 0B2C80010h
00010BE7 jz short loc_10BFF
00010BE9 cmp ecx, 0B2C80014h
00010BEF jnz loc_111AC
00010BF5 call sub_108BC
00010BFA jmp loc_11055
From logs emerged that the most frequently used is 0B2C8000C so it’s obvious that we will study this for first:
0xB2C8000C:
00010C16 cmp [ebp+arg_C], 1448h
00010C1D jnz loc_111AC ;check len
00010C23 mov esi, [ebp+SourceString]
00010C26 mov ecx, 512h
00010C2B mov edi, offset dword_18A58
00010C30 rep movsd
00010C32 call sub_108F0
00010C37 jmp loc_112C1 ;go out
In this case user supplied input is correctly sanitized, so 0xB2C8000C can be excluded from fuzz testing. From the log On Shutdown emerged the massive presence of 0xB2c80018, so let’s fuzz it. Here the configuration for IOCTL Fuzzer:
<?xml version=”1.0″ encoding=”windows-1251″?>
<cfg>
<log_file>C:\ioctls.txt</log_file>
<hex_dump>true</hex_dump>
<log_requests>true</log_requests>
<debug_log_requests>true</debug_log_requests>
<fuze_requests>true</fuze_requests>
<fuze_size>true</fuze_size>
<allow>
<drivers>
<entry>aswMon2.SYS</entry>
</drivers>
<devices>
<entry>\Device\aswMon</entry>
</devices>
<ioctls>
<entry>0xb2c80018</entry>
</ioctls>
<processes>
<entry>ashServ.exe</entry>
</processes>
</allow>
<deny>
<drivers>
<entry>aswSP.SYS</entry>
<entry>Aavmker4.SYS</entry>
<entry>aswTDI.SYS</entry>
</drivers>
<ioctls>
<entry>0xb2c8000c</entry>
<entry>0xb2c80014</entry>
<entry>0xb2c80020</entry>
</ioctls>
</deny>
</cfg>
The config script allows only 0xB2c80018 sent from aswMon, other drivers are locked. Obviously fuzzing need to follow the log unit that evidenced out IOCTL, so run fuzzer and stop all Avast services.
Bang..a BSOD, discovered an Avast vulnerability into aswMon2.sys 🙂
From crashdump:
kd> !analyze -v
UNEXPECTED_KERNEL_MODE_TRAP_M
Arguments:
Arg1: 00000008, EXCEPTION_DOUBLE_FAULT
Arg2: 80042000
Arg3: 00000000
Arg4: 00000000_KERNEL_MODE_TRAP_M (1000007f)
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
f76f3234 8053d251 f76f3250 00000000 f76f32a4 nt+0x600fa
f76f32a4 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f3328 8052c793 41414141 00000000 f76f377c nt+0x55712
f76f33a4 804fc700 f76f377c f76f3478 05050505 nt+0x55793
f76f3760 8053d251 f76f377c 00000000 f76f37d0 nt+0x25700
f76f37d0 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f3854 8052c793 41414141 00000000 f76f3ca8 nt+0x55712
f76f38d0 804fc700 f76f3ca8 f76f39a4 05050505 nt+0x55793
f76f3c8c 8053d251 f76f3ca8 00000000 f76f3cfc nt+0x25700
f76f3cfc 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f3d80 8052c793 41414141 00000000 f76f41d4 nt+0x55712
f76f3dfc 804fc700 f76f41d4 f76f3ed0 05050505 nt+0x55793
f76f41b8 8053d251 f76f41d4 00000000 f76f4228 nt+0x25700
f76f4228 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f42ac 8052c793 41414141 00000000 f76f4700 nt+0x55712
f76f4328 804fc700 f76f4700 f76f43fc 05050505 nt+0x55793
f76f46e4 8053d251 f76f4700 00000000 f76f4754 nt+0x25700
f76f4754 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f47d8 8052c793 41414141 00000000 f76f4c2c nt+0x55712
f76f4854 804fc700 f76f4c2c f76f4928 05050505 nt+0x55793
f76f4c10 8053d251 f76f4c2c 00000000 f76f4c80 nt+0x25700
f76f4c80 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f4d04 8052c793 41414141 00000000 f76f5158 nt+0x55712
f76f4d80 804fc700 f76f5158 f76f4e54 05050505 nt+0x55793
f76f513c 8053d251 f76f5158 00000000 f76f51ac nt+0x25700
f76f51ac 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0x66251
f76f5230 8052c793 41414141 00000000 f76f5684 nt+0x55712
f76f52ac 804fc700 f76f5684 f76f5380 41414141 nt+0x55793
f76f5668 8053d251 f76f5684 00000000 f76f56d8 nt+0x25700
f76f56d8 f7756a04 badb0d00 8055b256 00000000 nt+0x66251
f76f576c 41414141 41414141 41414141 41414141 aswMon2+0xa04
f76f5770 41414141 41414141 41414141 41414141 0x41414141
f76f5774 41414141 41414141 41414141 41414141 0x41414141
f76f5778 41414141 41414141 41414141 41414141 0x41414141
f76f577c 41414141 41414141 41414141 41414141 0x41414141
etc..
here the evidece of buffer corruption.
0xB2D60018:
00010F70 cmp [ebp+arg_C], 288h ;Insufficent input validation
00010F77 jnz loc_111AC
00010F7D mov esi, [ebp+SourceString]
00010F80 cmp [esi], ebx
00010F82 mov [ebp+arg_C], ebx
00010F85 jz short loc_10FEB
00010F87 mov eax, dword_18A48
00010F8C cmp eax, 80h
00010F91 jge loc_11055
00010F97 lea eax, [eax+eax*4]
00010F9A lea eax, unk_231A4[eax*4]
00010FA1 mov [ebp+arg_10], eax
00010FA4 lea eax, [esi+8]
00010FA7 mov [ebp+arg_18], eax
00010FAA jmp short loc_10FAF
Privates, Companies and/or Software House interested into a security review of their Device Drivers can contact me for Professional Consulting, please use PGP key that you can obtain here:
http://evilcry.netsons.org/contacts.html
Regards,
Giuseppe ‘Evilcry’ Bonfa’
Vista Tp* Thread Pool Functions
September 7, 2009Malware – 26xpl SSH Propagating Exploit Pack
August 25, 2009Redirection to my second blog:
http://evilcodecave.blogspot.com/2009/08/malware-26xpl-ssh-propagating-exploit.html
Regards,
Giuseppe ‘Evilcry’ Bonfa’
Reversing in Pills – Fast Notes around Infostealer.Banker.C
June 7, 2009Notes about Reverse Engineering of Malware Banker Infostealer.Banker.C with OllyDbg 2
Fast Notes About Infostealer.Banker.C
Regards,
Giuseppe ‘Evilcry’ Bonfa’
Determina PDB plugin
June 5, 2009Hi,
This is a replacement for the IDA PDB plugin which significantly improves the analysis of Microsoft binaries with public debugging symbols. The algorithm used by the PDB plugin is described in the Reverse Engineering Microsoft Binaries presentation at Recon 2006.
Download plugin here: detpdb-1.0.zip
Regards,
Giuseppe ‘Evilcry’ Bonfa’
EventPairs Reversing – EventPairHandle as Anti-Dbg Trick
May 6, 2009Hi,
I’ve published
EventPairs Reversing – EventPairHandle as Anti-Dbg Trick
The paper is here:
http://evilcry.netsons.org/tuts/EventPairsHandle.pdf
Have a nice read 🙂
Giuseppe ‘Evilcry’ Bonfa’
RtlQueryProcessHeapInformation As Anti-Dbg Trick
April 14, 2009Hi,
Directly derived from the previous trick, RtlQueryProcessHeapInformation could be used as Anti-Dbg Trick.
Starting by RtlQueryProcessDebugInformation.
NTSTATUS
NTAPI
RtlQueryProcessDebugInformation(
IN ULONG ProcessId,
IN ULONG DebugInfoClassMask,
IN OUT PDEBUG_BUFFER DebugBuffer);
This function loads all heap blocks of the process into DebugBuffer according to the informations that we want and that could be specified throughout DebugInfoClassMask. If we implement RtlQueryProcessDebugInformation in this way
void QueryDbgBufferMethod(void)
{
PDEBUG_BUFFER buffer;
NTSTATUS ntStatus;
buffer = RtlCreateQueryDebugBuffer(0,FALSE);
ntStatus = RtlQueryProcessDebugInformation(GetCurrentProcessId(),
PDI_HEAPS|PDI_HEAP_BLOCKS,
buffer);
The function according to the chosen mask will internally execute an call for heap functions, let’s see what happens inside this function.
__stdcall RtlQueryProcessDebugInformation(x, x, x)
7C9638EB mov edi, edi
7C9638ED push ebp
7C9638EE mov ebp, esp
7C9638F0 sub esp, 44h
7C9638F3 mov eax, [ebp+14] ;EAX = DebugMassk
7C9638F6 push ebx
7C9638F7 push esi
7C9638F8 mov esi, [ebp+arg_8] ;ESI = DEBUG_BUFFER
7C9638FB xor ebx, ebx
7C9638FD mov [esi+20h], eax
7C963900 mov eax, [esi+24h]
7C963903 cmp eax, ebx
7C963905 push edi
7C963906 mov [ebp+var_4], ebx
7C963909 mov [ebp+var_8], ebx
7C96390C jz short loc_7C963924
..
7C963924 mov dword ptr [esi+24h], 60h
7C96392B mov eax, large fs:18h
7C963931 mov edi, [ebp+arg_0]
7C963934 cmp [eax+20h], edi
7C963937 jz short loc_7C963987
7C963939 test byte ptr [ebp+arg_4+3], 80h
7C96393D jz short loc_7C963987
7C96393F test byte ptr [ebp+0Ch], 41h
7C963943 jz short loc_7C963987
..
7C963987 mov eax, large fs:18h
7C96398D cmp [eax+20h], edi
7C963990 jz loc_7C963A8E
7C963996 cmp [ebp+var_8], ebx
..
Here DebugMask Switch Cases:
7C963AA7 test byte ptr [ebp+arg_4], 2
7C963AAB jz short loc_7C963ABA
7C963AAD push esi
7C963AAE call _RtlQueryProcessBackTraceInformation
7C963AB3 cmp eax, ebx
7C963AB5 mov [ebp+var_4], eax
7C963AB8 jnz short loc_7C963ADC
7C963ABA test byte ptr [ebp+arg_4], 20h
7C963ABE jz short loc_7C963ACD
7C963AC0 push esi
7C963AC1 call _RtlQueryProcessLockInformation
7C963AC6 cmp eax, ebx
7C963AC8 mov [ebp+var_4], eax
7C963ACB jnz short loc_7C963ADC
7C963ACD test byte ptr [ebp+arg_4], 1Ch ; DebugMask = PDI_HEAPS|PDI_HEAP_BLOCKS (Our Case)
7C963AD1 jz short loc_7C963ADC
7C963AD3 push esi ;DEBUG_BUFFER
7C963AD4 call _RtlQueryProcessHeapInformation
7C963AD9 mov [ebp+var_4], eax
As you can see when we use DebugMask = PDI_HEAPS|PDI_HEAP_BLOCKS, is only called
RtlQueryProcessHeapInformation, function that takes only DEBUG_BUFFER as parameter, this means that this function is only applicable for the Current Process since does not take PID.
; __stdcall RtlQueryProcessHeapInformation(x)
7C963249 push 58h
7C96324B push offset stru_7C963708
7C963250 call __SEH_prolog
7C963255 push 4
7C963257 mov ebx, [ebp+arg_0]
7C96325A push ebx ;DEBUG_BUFFER
7C96325B call _RtlpCommitQueryDebugInfo
7C963260 mov edi, eax
7C963262 mov [ebp+var_48], edi
7C963265 test edi, edi
7C963267 jnz short loc_7C963270
7C963269 mov eax, C0000017h ;EAX = STATUS_NO_MEMORY
7C96326E jmp short loc_7C9632CD
7C963270 mov [ebx+38h], edi
7C963273 call _RtlpAcquireHeapListLock
7C963278 and [ebp+ms_exc.disabled], 0
7C96327C push ebx
7C96327D push offset _RtlpQueryProcessEnumHeapsRoutine 7C963282 call _RtlEnumProcessHeaps
7C963287 mov [ebp+var_20], eax
7C96328A test eax, eax
7C96328C jl loc_7C963422
7C963292 test byte ptr [ebx+20h], 8
7C963296 jz loc_7C963426
7C96329C mov esi, _RtlpGlobalTagHeap
7C9632A2 mov [ebp+var_28], esi
7C9632A5 cmp dword ptr [esi+3Ch], 0
7C9632A9 jz short loc_7C9632E5
7C9632AB push 40h
7C9632AD push ebx
7C9632AE call _RtlpCommitQueryDebugInfo
7C9632B3 mov [ebp+var_4C], eax
7C9632B6 test eax, eax
7C9632B8 jnz short loc_7C9632D5
7C9632BA mov [ebp+var_20], 0C0000017h
7C9632C1 or [ebp+ms_exc.disabled], 0FFFFFFFFh
7C9632C5 call sub_7C9636FE ; RtlpReleaseHeapListLoc
7C9632CA mov eax, [ebp+var_20]
7C9632CD call __SEH_epilog
7C9632D2 retn 4
RtlQueryProcessHeapInformation essentially fills DEBUG_BUFFER by taking informations from heap blocks. RtlpCommitQueryDebugInfo prepairs buffer by calling NtAllocateVirtualMemory, if RtlpCommitQueryDebugInfo fails the error
(0xC0000017 – STATUS_NO_MEMORY with consequent corrupted DEBUG_BUFFER) propagates throughout RtlQueryProcessHeapInformation and finally (if used) RtlQueryProcessDebugInformation. So if you use these functions it’s a best practice to implement a check for this error, especially if you are working in applications that walks heap. Finally here the check anti-dbg.
void QueryProcessHeapMethod(void)
{
PDEBUG_BUFFER buffer;
buffer = RtlCreateQueryDebugBuffer(0,FALSE);
RtlQueryProcessHeapInformation(buffer);
if (buffer->RemoteSectionBase == (PVOID) 0x50000062)
MessageBoxA(NULL,”Debugged”,”Warning”,MB_OK);
else
MessageBoxA(NULL,”Not Debugged”,”Warning”,MB_OK);
}
defs.h
extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlQueryProcessHeapInformation(
IN PDEBUG_BUFFER DebugBuffer
);
The presence of RemoteXxx members is given to the fact that we need to avoid ther risk of a DeadLock that could happen when RtlQueryProcessDebugInformation request a remote information and consequently the debugger receives the thread start routine.
See you to the next post.. 🙂
Something about RtlQueryProcessDebugInformation
April 12, 2009Hi,
Just a precisation, as you can see in the code I used psapi.lib, this is obviously not necessary for the code that I reported here, but can be used to enumerate all processes and by passing their PID to RtlQueryProcessDebugInformation we can inspect if there are debugged running processes It’s important to implement a check for the return value of RtlQueryProcessDebugInformation cause, for some PIDs it fails and we have a non sense DEBUG_BUFFER and a consequent non sense DEBUG_HEAP_INFORMATION. Implement a check for 0xC0000008 and 0xC0000017
See you to the next post.. 🙂
RtlQueryProcessDebugInformation as Anti-Dbg Trick
April 11, 2009The Essay
The following paper will uncover some interesting undocumented
functions relative to Windows Heap Enumeration.
RtlCreateQueryDebugBuffer
RtlQueryProcessDebugInformation
RtlDestroyQueryDebugBuffer
Here the prototypes for each function:
PDEBUG_BUFFER
NTAPI
RtlCreateQueryDebugBuffer(
IN ULONG Size,
IN BOOLEAN EventPair);
NTSTATUS
NTAPI
RtlQueryProcessDebugInformation(
IN ULONG ProcessId,
IN ULONG DebugInfoClassMask,
IN OUT PDEBUG_BUFFER DebugBuffer);
NTSTATUS
NTAPI
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER DebugBuffer);
RtlCreateQueryDebugBuffer allocates buffer for storing heap data in case of success, it returns pointer to allocated debug buffer. Here the declaration of debug buffer:
typedef struct _DEBUG_BUFFER {
HANDLE SectionHandle;
PVOID SectionBase;
PVOID RemoteSectionBase;
ULONG SectionBaseDelta;
HANDLE EventPairHandle;
ULONG Unknown[2];
HANDLE RemoteThreadHandle;
ULONG InfoClassMask;
ULONG SizeOfInfo;
ULONG AllocatedSize;
ULONG SectionSize;
PVOID ModuleInformation;
PVOID BackTraceInformation;
PVOID HeapInformation;
PVOID LockInformation;
PVOID Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;
After the buffer allocation we can call the Heap Process Debug Information, we can call RtlQueryProcessDebugInformation to load all heap blocks of the process. This function loads entire heap nodes and corresponding heap blocks of the process. Debug Buffer contains the pointer to heap information structure at offset 0x38. First parameter of this heap structure is node count and after that it contains array of DEBUG_HEAP_INFORMATION structure which represent each heap node.
typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0x00
ULONG Flags; // 0x04
USHORT Granularity; // 0x08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0x10
ULONG TagCount; // 0x14
ULONG BlockCount; // 0x18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0x38
PVOID Blocks; // 0x3C Heap block pointer for this node.
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
As you should know a debugged process presents different flags respect a not debugged one, here the sample anti-dbg code:
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Psapi.h>
#include “defs.h”
#pragma comment(lib,”ntdll.lib”)
#pragma comment(lib,”psapi.lib”)
void QueryDbgBufferMethod(void)
{
PDEBUG_BUFFER buffer;
NTSTATUS ntStatus;
buffer = RtlCreateQueryDebugBuffer(0,FALSE);
ntStatus = RtlQueryProcessDebugInformation(GetCurrentProcessId(),
PDI_HEAPS|PDI_HEAP_BLOCKS,
buffer);
PDEBUG_HEAP_INFORMATION heapInfo = PDEBUG_HEAP_INFORMATION(PULONG(buffer->HeapInformation) + 1);
if (heapInfo->Flags == 0x50000062)
MessageBoxA(NULL,”Debugged”,”Warning”,MB_OK);
else
MessageBoxA(NULL,”Not Debugged”,”Warning”,MB_OK);
RtlDestroyQueryDebugBuffer(buffer);
}
and here ‘defs.h‘
typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
typedef struct _DEBUG_BUFFER {
HANDLE SectionHandle;
PVOID SectionBase;
PVOID RemoteSectionBase;
ULONG SectionBaseDelta;
HANDLE EventPairHandle;
ULONG Unknown[2];
HANDLE RemoteThreadHandle;
ULONG InfoClassMask;
ULONG SizeOfInfo;
ULONG AllocatedSize;
ULONG SectionSize;
PVOID ModuleInformation;
PVOID BackTraceInformation;
PVOID HeapInformation;
PVOID LockInformation;
PVOID Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;
typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0x00
ULONG Flags; // 0x04
USHORT Granularity; // 0x08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0x10
ULONG TagCount; // 0x14
ULONG BlockCount; // 0x18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0x38
PVOID Blocks; // 0x3C
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
// RtlQueryProcessDebugInformation.DebugInfoClassMask constants
#define PDI_MODULES 0x01
#define PDI_BACKTRACE 0x02
#define PDI_HEAPS 0x04
#define PDI_HEAP_TAGS 0x08
#define PDI_HEAP_BLOCKS 0x10
#define PDI_LOCKS 0x20
extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlQueryProcessDebugInformation(
IN ULONG ProcessId,
IN ULONG DebugInfoClassMask,
IN OUT PDEBUG_BUFFER DebugBuffer);
extern “C”
__declspec(dllimport)
PDEBUG_BUFFER
__stdcall
RtlCreateQueryDebugBuffer(
IN ULONG Size,
IN BOOLEAN EventPair);
extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER DebugBuffer);
See you to the next post.. 🙂