Wednesday, December 28, 2005
ANTI DLL INJECTION - A "C++" PORT
since i released the asm version of it some time ago i thought it's maybe a nice gift to also release a C port of it...
the following source will display every injected dll / thread that exists in the process
compiled output should be like this below, if you notice more dll's in the process or more threads this can be of more reasons:
1. anti-dialer/trojan/virus software is installed / or some firewall app
2. you got infected by some malware
this can also be used to detect virus infections...
-------------------------------------------------------
Detecting injected DLL's v0.1
Process Environment Block found @ 0x7FFDF000
PEB_LDR_DATA found @ 0x00241E90
InLoadOrderModuleListHead found @ 0x00241EC0
===[ THIS MODULE ]===
ExeModuleFileName found @ 0x00020A28
ExeModuleName = G:\readtree.exe
===[ MODULES ]===
ModuleFileName found @ 0x77FB1618
ModuleName = E:\WINDOWS\System32\ntdll.dll - DLL OKAY!
ModuleFileName found @ 0x00241F70
ModuleName = E:\WINDOWS\system32\kernel32.dll - DLL OKAY!
===[ THREADS ]===
Active TH_CTR : 00000001
-------------------------------------------------------
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
DWORD GetPEB();
DWORD result;
//NTSTATUS NtQuerySystemInformation(
// SYSTEM_INFORMATION_CLASS SystemInformationClass,
// PVOID SystemInformation,
// ULONG SystemInformationLength,
// PULONG ReturnLength
//);
typedef BOOL (__stdcall *_NtQuerySystemInformation)(DWORD x,DWORD y,DWORD z,DWORD b);
_NtQuerySystemInformation NtQuerySystemInformation;
int main(int argc, char* argv[])
{
printf ("Detecting injected DLL's v0.1\n\n");
// GRAB PEB
DWORD pPEB = GetPEB ();
printf ("Process Environment Block found @ 0x%8.8X\n",pPEB);
DWORD PEB_LDR_DATA = (unsigned long)*(DWORD*)(pPEB+0x0C);
printf ("PEB_LDR_DATA found @ 0x%8.8X\n",PEB_LDR_DATA);
DWORD InLoadOrderModuleListHead = (unsigned long)*(DWORD*)(PEB_LDR_DATA+0x0C);
printf ("InLoadOrderModuleListHead found @ 0x%8.8X\n\n",InLoadOrderModuleListHead);
// CURRENT FILE -- FIRST ENTRY
printf ("===[ THIS MODULE ]===\n\n");
DWORD ModuleFileName = (unsigned long)*(PDWORD*)(InLoadOrderModuleListHead+0x28);
printf ("ExeModuleFileName found @ 0x%8.8X\n",ModuleFileName);
InLoadOrderModuleListHead = *(DWORD*)(InLoadOrderModuleListHead);
int a = 255;
char *ansistr = new char[a];
WideCharToMultiByte(CP_ACP,0,(const unsigned short *)ModuleFileName,-1,ansistr,a,NULL,NULL);
printf ("ExeModuleName = %s\n",ansistr);
// START LOOPING
printf ("\n\n===[ MODULES ]===\n\n");
while (*(DWORD*)(InLoadOrderModuleListHead) != (unsigned long)*(PDWORD*)(PEB_LDR_DATA+0x0C))
{
DWORD ModuleFileName = (unsigned long)*(PDWORD*)(InLoadOrderModuleListHead+0x28);
printf ("ModuleFileName found @ 0x%8.8X\n",ModuleFileName);
InLoadOrderModuleListHead = *(DWORD*)(InLoadOrderModuleListHead);
int a = 255;
char *ansistr = new char[a];
WideCharToMultiByte(CP_ACP,0,(const unsigned short *)ModuleFileName,-1,ansistr,a,NULL,NULL);
printf ("ModuleName = %s",ansistr);
_strlwr(ansistr);
if (strstr (ansistr,"kernel32.dll") strstr (ansistr,"ntdll.dll"))
{
printf (" - DLL OKAY!\n");
}
else
{
printf (" - DLL INJECTED!\n");
}
}
//
// DETECT AND DISPLAY NUMBER OF RUNNING THREADS
//
HINSTANCE aHandle = LoadLibrary ("ntdll.dll");
if (aHandle != 0)
{
NtQuerySystemInformation = (_NtQuerySystemInformation) GetProcAddress ((HINSTANCE)aHandle,"NtQuerySystemInformation");
if (NtQuerySystemInformation != 0)
{
printf ("\n\n===[ THREADS ]===\n");
DWORD BufX = (DWORD) GlobalAlloc (GMEM_ZEROINIT,0x50000);
NtQuerySystemInformation (5,BufX,0x50000,0);
DWORD xPID = GetCurrentProcessId ();
while (*(DWORD*)BufX != 0)
{
// CHECK ACTUAL RECORD's PID
if (*(DWORD*)(BufX+0x44) == xPID)
{
printf (" active thread count : %8.8X\n",*(DWORD*)(BufX+4));
}
// FORWARD TO NEXT RECORD
BufX = BufX + *(DWORD*)BufX;
}
// CHECK ACTUAL RECORD's PID
if (*(DWORD*)(BufX+0x44) == xPID)
{
printf ("\nActive TH_CTR : %8.8X\n",*(DWORD*)(BufX+4));
}
}
}
return 0;
}
DWORD GetPEB()
{
__asm
{
mov eax,dword ptr fs:[0x30]
mov result,eax;
}
return result;
}
the following source will display every injected dll / thread that exists in the process
compiled output should be like this below, if you notice more dll's in the process or more threads this can be of more reasons:
1. anti-dialer/trojan/virus software is installed / or some firewall app
2. you got infected by some malware
this can also be used to detect virus infections...
-------------------------------------------------------
Detecting injected DLL's v0.1
Process Environment Block found @ 0x7FFDF000
PEB_LDR_DATA found @ 0x00241E90
InLoadOrderModuleListHead found @ 0x00241EC0
===[ THIS MODULE ]===
ExeModuleFileName found @ 0x00020A28
ExeModuleName = G:\readtree.exe
===[ MODULES ]===
ModuleFileName found @ 0x77FB1618
ModuleName = E:\WINDOWS\System32\ntdll.dll - DLL OKAY!
ModuleFileName found @ 0x00241F70
ModuleName = E:\WINDOWS\system32\kernel32.dll - DLL OKAY!
===[ THREADS ]===
Active TH_CTR : 00000001
-------------------------------------------------------
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
DWORD GetPEB();
DWORD result;
//NTSTATUS NtQuerySystemInformation(
// SYSTEM_INFORMATION_CLASS SystemInformationClass,
// PVOID SystemInformation,
// ULONG SystemInformationLength,
// PULONG ReturnLength
//);
typedef BOOL (__stdcall *_NtQuerySystemInformation)(DWORD x,DWORD y,DWORD z,DWORD b);
_NtQuerySystemInformation NtQuerySystemInformation;
int main(int argc, char* argv[])
{
printf ("Detecting injected DLL's v0.1\n\n");
// GRAB PEB
DWORD pPEB = GetPEB ();
printf ("Process Environment Block found @ 0x%8.8X\n",pPEB);
DWORD PEB_LDR_DATA = (unsigned long)*(DWORD*)(pPEB+0x0C);
printf ("PEB_LDR_DATA found @ 0x%8.8X\n",PEB_LDR_DATA);
DWORD InLoadOrderModuleListHead = (unsigned long)*(DWORD*)(PEB_LDR_DATA+0x0C);
printf ("InLoadOrderModuleListHead found @ 0x%8.8X\n\n",InLoadOrderModuleListHead);
// CURRENT FILE -- FIRST ENTRY
printf ("===[ THIS MODULE ]===\n\n");
DWORD ModuleFileName = (unsigned long)*(PDWORD*)(InLoadOrderModuleListHead+0x28);
printf ("ExeModuleFileName found @ 0x%8.8X\n",ModuleFileName);
InLoadOrderModuleListHead = *(DWORD*)(InLoadOrderModuleListHead);
int a = 255;
char *ansistr = new char[a];
WideCharToMultiByte(CP_ACP,0,(const unsigned short *)ModuleFileName,-1,ansistr,a,NULL,NULL);
printf ("ExeModuleName = %s\n",ansistr);
// START LOOPING
printf ("\n\n===[ MODULES ]===\n\n");
while (*(DWORD*)(InLoadOrderModuleListHead) != (unsigned long)*(PDWORD*)(PEB_LDR_DATA+0x0C))
{
DWORD ModuleFileName = (unsigned long)*(PDWORD*)(InLoadOrderModuleListHead+0x28);
printf ("ModuleFileName found @ 0x%8.8X\n",ModuleFileName);
InLoadOrderModuleListHead = *(DWORD*)(InLoadOrderModuleListHead);
int a = 255;
char *ansistr = new char[a];
WideCharToMultiByte(CP_ACP,0,(const unsigned short *)ModuleFileName,-1,ansistr,a,NULL,NULL);
printf ("ModuleName = %s",ansistr);
_strlwr(ansistr);
if (strstr (ansistr,"kernel32.dll") strstr (ansistr,"ntdll.dll"))
{
printf (" - DLL OKAY!\n");
}
else
{
printf (" - DLL INJECTED!\n");
}
}
//
// DETECT AND DISPLAY NUMBER OF RUNNING THREADS
//
HINSTANCE aHandle = LoadLibrary ("ntdll.dll");
if (aHandle != 0)
{
NtQuerySystemInformation = (_NtQuerySystemInformation) GetProcAddress ((HINSTANCE)aHandle,"NtQuerySystemInformation");
if (NtQuerySystemInformation != 0)
{
printf ("\n\n===[ THREADS ]===\n");
DWORD BufX = (DWORD) GlobalAlloc (GMEM_ZEROINIT,0x50000);
NtQuerySystemInformation (5,BufX,0x50000,0);
DWORD xPID = GetCurrentProcessId ();
while (*(DWORD*)BufX != 0)
{
// CHECK ACTUAL RECORD's PID
if (*(DWORD*)(BufX+0x44) == xPID)
{
printf (" active thread count : %8.8X\n",*(DWORD*)(BufX+4));
}
// FORWARD TO NEXT RECORD
BufX = BufX + *(DWORD*)BufX;
}
// CHECK ACTUAL RECORD's PID
if (*(DWORD*)(BufX+0x44) == xPID)
{
printf ("\nActive TH_CTR : %8.8X\n",*(DWORD*)(BufX+4));
}
}
}
return 0;
}
DWORD GetPEB()
{
__asm
{
mov eax,dword ptr fs:[0x30]
mov result,eax;
}
return result;
}
Tuesday, December 27, 2005
STREAM BABY STREAM
The following example shows an idea a friend and me had some time ago, iam 100% sure others had this idea earlier and maybe there's implementations of it available on the net as well, though neither me or ma friend ever came across it, it's sort of a stream encryption... when you look closely at the source you will see what "we" mean... this below is though just an example app which shows what the idea was.... (not a final implementation)
.386P
Locals
jumps
.Model Flat ,StdCall
extrn LoadLibraryA :PROC
extrn GetProcAddress :PROC
extrn MessageBoxA :PROC
extrn ExitProcess :PROC
;-----------------------------------------------------------------------------
.Data
caption db "test application",0
text2 db "test 2",0
msgbox dd ?
.Code
code_block_1_start equ $
mov eax,offset MessageBoxA
mov eax,[eax+2]
mov eax,[eax]
mov dword ptr [msgbox],eax
ret
code_block_1_ends equ $
fill_space_1 db 1000h - (code_block_1_ends-code_block_1_start) dup (00h)
code_block_2_start equ $
push 0
lea eax,dword ptr [ebp+caption]
push eax
lea eax,dword ptr [ebp+caption]
push eax
push 0
call dword ptr [ebp+msgbox]
ret
code_block_2_ends equ $
fill_space_2 db 1000h - (code_block_2_ends-code_block_2_start) dup (00h)
code_block_3_start equ $
xor eax,dword ptr [ebp+msgbox]
mov eax,[eax]
xor ebx,ebx
rol eax,cl
rol eax,cl
xor eax,012345678h
xor dword ptr [ebp+msgbox],ebx
ret
code_block_3_ends equ $
fill_space_3 db 1000h - (code_block_3_ends-code_block_3_start) dup (00h)
block_x dd offset code_block_1_start
block_x_2 dd offset code_block_1_start
block_ctx dd 3
get_shit dd ?
Main:
;// ENCRYPT STREAM BLOCKS
mov esi,offset code_block_2_start
mov edi,offset code_block_3_start
call encrypt_block_x
mov esi,offset code_block_1_start
mov edi,offset code_block_2_start
call encrypt_block_x
;// CALL & DECRYPT STREAMING
call $+5
pop ebp
sub ebp,offset $-1
call_next_block:
call dword ptr [block_x]
mov ecx,0400h
mov esi,offset code_block_1_start
add dword ptr [block_x_2],01000h
mov edi,dword ptr [block_x_2]
decrypt_stream:
lodsd
xor eax,[edi]
mov dword ptr [esi-4],eax
add edi,04h
loop decrypt_stream
dec dword ptr [block_ctx]
jne call_next_block
call ExitProcess
encrypt_block_x:
mov ecx,1000h
sar ecx,02h
encrypt_code_blocks:
lodsd
xor [edi],eax
add edi,04h
loop encrypt_code_blocks
ret
End Main ;end of code, JUMP-spot (main)
.386P
Locals
jumps
.Model Flat ,StdCall
extrn LoadLibraryA :PROC
extrn GetProcAddress :PROC
extrn MessageBoxA :PROC
extrn ExitProcess :PROC
;-----------------------------------------------------------------------------
.Data
caption db "test application",0
text2 db "test 2",0
msgbox dd ?
.Code
code_block_1_start equ $
mov eax,offset MessageBoxA
mov eax,[eax+2]
mov eax,[eax]
mov dword ptr [msgbox],eax
ret
code_block_1_ends equ $
fill_space_1 db 1000h - (code_block_1_ends-code_block_1_start) dup (00h)
code_block_2_start equ $
push 0
lea eax,dword ptr [ebp+caption]
push eax
lea eax,dword ptr [ebp+caption]
push eax
push 0
call dword ptr [ebp+msgbox]
ret
code_block_2_ends equ $
fill_space_2 db 1000h - (code_block_2_ends-code_block_2_start) dup (00h)
code_block_3_start equ $
xor eax,dword ptr [ebp+msgbox]
mov eax,[eax]
xor ebx,ebx
rol eax,cl
rol eax,cl
xor eax,012345678h
xor dword ptr [ebp+msgbox],ebx
ret
code_block_3_ends equ $
fill_space_3 db 1000h - (code_block_3_ends-code_block_3_start) dup (00h)
block_x dd offset code_block_1_start
block_x_2 dd offset code_block_1_start
block_ctx dd 3
get_shit dd ?
Main:
;// ENCRYPT STREAM BLOCKS
mov esi,offset code_block_2_start
mov edi,offset code_block_3_start
call encrypt_block_x
mov esi,offset code_block_1_start
mov edi,offset code_block_2_start
call encrypt_block_x
;// CALL & DECRYPT STREAMING
call $+5
pop ebp
sub ebp,offset $-1
call_next_block:
call dword ptr [block_x]
mov ecx,0400h
mov esi,offset code_block_1_start
add dword ptr [block_x_2],01000h
mov edi,dword ptr [block_x_2]
decrypt_stream:
lodsd
xor eax,[edi]
mov dword ptr [esi-4],eax
add edi,04h
loop decrypt_stream
dec dword ptr [block_ctx]
jne call_next_block
call ExitProcess
encrypt_block_x:
mov ecx,1000h
sar ecx,02h
encrypt_code_blocks:
lodsd
xor [edi],eax
add edi,04h
loop encrypt_code_blocks
ret
End Main ;end of code, JUMP-spot (main)
THE AWAKENING
for those who understand, the following snippet, will make a grin on their face...
for those who don't... doesn't really matter ;)
the following source is just for educational purposes!
typedef BOOL (_stdcall *_Export3)(int nr_of_device,char * buffer,char * buffer2);
_Export3 MyExport3;
typedef BOOL (_stdcall *_Export7)(char * buffer);
_Export7 MyExport7;
typedef BOOL (_stdcall *_Export1)();
_Export1 MyExport1;
HANDLE aHandle;
static char DEVCNT[255];
static char DEVCNT2[255];
static char DEVCNT3[255];
static char msgbox[255];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
aHandle = LoadLibrary ("daemon.dll");
MyExport1 = (_Export1)(GetProcAddress ((HINSTANCE)aHandle,(const char *)1));
MyExport1 ();
MyExport3 = (_Export3)(GetProcAddress ((HINSTANCE)aHandle,(const char *)3));
MyExport7 = (_Export7)(GetProcAddress ((HINSTANCE)aHandle,(const char *)7));
if (MyExport7 != 0)
{
if (MyExport7 (DEVCNT) != 0)
{
MessageBox (0,"failed to retrieve count of present virtual devices","error",0);
return -1;
}
sprintf (msgbox,"found %d virtual devices",DEVCNT[0]);
MessageBox (0,msgbox,"",0);
for (int i=0;i i< DEVCNT[0];i++)
{
if (MyExport3 (i,DEVCNT2,DEVCNT3) != 0)
{
MessageBox (0,"failed to retrieve drive letter!","error",0);
return -1;
}
DEVCNT2[1]+=0x40;
sprintf (msgbox,"drive %d -> assigned with drive letter : %s",i,&DEVCNT2[1]);
MessageBox (0,msgbox,"",0); }MessageBox (0,msgbox,"",0);
}
}
else
{
MessageBox (0,"failed to either retrieve export3 or daemon.dll","error",0);
}
return 0;
}
for those who don't... doesn't really matter ;)
the following source is just for educational purposes!
typedef BOOL (_stdcall *_Export3)(int nr_of_device,char * buffer,char * buffer2);
_Export3 MyExport3;
typedef BOOL (_stdcall *_Export7)(char * buffer);
_Export7 MyExport7;
typedef BOOL (_stdcall *_Export1)();
_Export1 MyExport1;
HANDLE aHandle;
static char DEVCNT[255];
static char DEVCNT2[255];
static char DEVCNT3[255];
static char msgbox[255];
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
aHandle = LoadLibrary ("daemon.dll");
MyExport1 = (_Export1)(GetProcAddress ((HINSTANCE)aHandle,(const char *)1));
MyExport1 ();
MyExport3 = (_Export3)(GetProcAddress ((HINSTANCE)aHandle,(const char *)3));
MyExport7 = (_Export7)(GetProcAddress ((HINSTANCE)aHandle,(const char *)7));
if (MyExport7 != 0)
{
if (MyExport7 (DEVCNT) != 0)
{
MessageBox (0,"failed to retrieve count of present virtual devices","error",0);
return -1;
}
sprintf (msgbox,"found %d virtual devices",DEVCNT[0]);
MessageBox (0,msgbox,"",0);
for (int i=0;i
{
if (MyExport3 (i,DEVCNT2,DEVCNT3) != 0)
{
MessageBox (0,"failed to retrieve drive letter!","error",0);
return -1;
}
DEVCNT2[1]+=0x40;
sprintf (msgbox,"drive %d -> assigned with drive letter : %s",i,&DEVCNT2[1]);
}
}
else
{
MessageBox (0,"failed to either retrieve export3 or daemon.dll","error",0);
}
return 0;
}
Saturday, December 24, 2005
Merry Christmas
yet another year passes by... i wish all of you a merry christmas!
Wednesday, December 07, 2005
DEEPDOWN in the SHIT
I thought it might be useful / handy for the one or other it's part of my driver routine to "GetProcAddress"... simple lookup via ExportTable scanning, so it's really nothing special nor optimized.... take it or let it be ;)
example -> ULONG Blub = GetAddress ("NtDeviceIoControlFile",base_of_ntoskrnl);
ULONG GetAddress (char * ApiAscii,ULONG ModuleBase)
{
PIMAGE_DOS_HEADER DosHdr;
PIMAGE_NT_HEADERS32 NTHdr;
PIMAGE_EXPORT_DIRECTORY ExportTable;
PIMAGE_THUNK_DATA32 ThunkData;
BYTE * AddressNameOrd;
BYTE * AddressFns;
ULONG ApiOffset;
unsigned int ApiCounter;
DosHdr = (PIMAGE_DOS_HEADER) ModuleBase;
NTHdr = (PIMAGE_NT_HEADERS32) (BYTE *)(ModuleBase+DosHdr->e_lfanew);
ExportTable = (PIMAGE_EXPORT_DIRECTORY) (BYTE *)(ModuleBase+*(ULONG*)(NTHdr->OptionalHeader.DataDirectory));
ThunkData = (PIMAGE_THUNK_DATA32) (BYTE *)(ExportTable->AddressOfNames+ModuleBase);
AddressNameOrd = (BYTE *)(ExportTable->AddressOfNameOrdinals+ModuleBase);
AddressFns = (BYTE *)(ExportTable->AddressOfFunctions+ModuleBase);
for (ApiCounter=1;ApiCounter <= ExportTable->NumberOfNames;ApiCounter++)
{
if (strcmp (ApiAscii,(const char *)ThunkData->Ascii+ModuleBase) == 0)
{
ApiOffset = (*(ULONG*)(AddressNameOrd+ApiCounter*2)) & 0xFFFF;
return (ULONG)((ApiOffset-1)*4+AddressFns);
}
ThunkData++;
}
return 0;
}
example -> ULONG Blub = GetAddress ("NtDeviceIoControlFile",base_of_ntoskrnl);
ULONG GetAddress (char * ApiAscii,ULONG ModuleBase)
{
PIMAGE_DOS_HEADER DosHdr;
PIMAGE_NT_HEADERS32 NTHdr;
PIMAGE_EXPORT_DIRECTORY ExportTable;
PIMAGE_THUNK_DATA32 ThunkData;
BYTE * AddressNameOrd;
BYTE * AddressFns;
ULONG ApiOffset;
unsigned int ApiCounter;
DosHdr = (PIMAGE_DOS_HEADER) ModuleBase;
NTHdr = (PIMAGE_NT_HEADERS32) (BYTE *)(ModuleBase+DosHdr->e_lfanew);
ExportTable = (PIMAGE_EXPORT_DIRECTORY) (BYTE *)(ModuleBase+*(ULONG*)(NTHdr->OptionalHeader.DataDirectory));
ThunkData = (PIMAGE_THUNK_DATA32) (BYTE *)(ExportTable->AddressOfNames+ModuleBase);
AddressNameOrd = (BYTE *)(ExportTable->AddressOfNameOrdinals+ModuleBase);
AddressFns = (BYTE *)(ExportTable->AddressOfFunctions+ModuleBase);
for (ApiCounter=1;ApiCounter <= ExportTable->NumberOfNames;ApiCounter++)
{
if (strcmp (ApiAscii,(const char *)ThunkData->Ascii+ModuleBase) == 0)
{
ApiOffset = (*(ULONG*)(AddressNameOrd+ApiCounter*2)) & 0xFFFF;
return (ULONG)((ApiOffset-1)*4+AddressFns);
}
ThunkData++;
}
return 0;
}
Adjusted the layout
well i just adjusted the layout a bit more, i find it now better to look through...
actually iam working on a small driver written in C... might get published soon'ish
actually iam working on a small driver written in C... might get published soon'ish