Plop, c’est les vacances et IvanleMad ne peut s’arrêter de coder, toujours en
quête de satisfation personnelle, la masturbation ne lui suffit plus il doit
coder, toujours plus vite, toujours plus loin, toujours plus profond.
Ainsi dans ces pérégrinations il jouait avec le fameux tools de Mark
Russinovitch, Process Explorer, et tombe sur une fonction permettant de voir la
pile d’appel d’un Thread, son esprit commenca à entré en éruption. « Comment ce
put1 de b4t@rd de ca race de programme fonctionne ffs ?! ». Cet ainsi qu’il
décida à reverse l’irréversible (O_o).
Effectivement après cette superbe intro réalisée par mon Dr Hide, je vous
propose un tool, codé par mes soins. Son objectif ! Etre capable de lire la
mémoire d’un autre process afin de parcourir la pile de chaque thread et d’y
retrouver les fonctions utilisées. Cela paraît dingue mais c’est faisable, si le
tool du ruskoff est capable de le faire alors pourquoir pas le mien :]
Bon en lisant la doc des API d’aide au débuggage je suis tombé sur
StackWalk64(), une API permettant de retrouver les appels à partir de la pile,
il suffit de lui donner un HANDLE sur le process, un autre sur le Thread stopé
au préalable, quelques infos sur l’état du Thread et hop (burp!) elle se
débrouille pour nous retrouver les saved eip, W00t.
Comme c’est nowel je me suis que c’etait bien joli d’avoir les addr d’appel,
mais que ca serait encore mieux d’avoir les noms de ces fonctions. Le programme
utilise donc les symbols, fournit par MS, qui doivent être downloader sur son
site avec les debugings tools, ici :
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
Je peux vous dire que cela ma pas prit la tête pour faire marcher ce petit bout
de code, la doc sur le net n’étant pas foisonnante ….
————CUT HERE——————–
#include <windows.h>
#include <tlhelp32.h>
#include <dbghelp.h>
#include <stdio.h>
#pragma comment (lib, "advapi32.lib")
#pragma comment (lib, "dbghelp.lib")
int NameToPid(char *ProcessName)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap==INVALID_HANDLE_VALUE)
{
printf("Error with CreateToolhelp32Snapshot: 0x%xn",GetLastError() );
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if( !Process32First(hProcessSnap, &pe32 ))
{
printf("Error with Process32First: %dn",GetLastError());
CloseHandle(hProcessSnap);
}
while(Process32Next(hProcessSnap,&pe32)!=0)
{
if(_stricmp(pe32.szExeFile,ProcessName)==0) //_stricmp fuck la case sensitive
{
CloseHandle(hProcessSnap);
return pe32.th32ProcessID;
}
}
CloseHandle(hProcessSnap);
return 0;
}
DWORD EnablePrivilege(char *Privilege)
{
HANDLE hToken;
DWORD Ret=1;
TOKEN_PRIVILEGES TP;
LUID Luid;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
printf("Error with OpenProcessToken: %dn", GetLastError());
Ret=0;
goto bye;
}
if(!LookupPrivilegeValue(NULL, Privilege, &TP.Privileges[0].Luid))
{
printf("Error with LookupPrivilegeValue: %dn", GetLastError());
Ret=0;
goto bye;
}
TP.PrivilegeCount=1;
TP.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken,
false,
&TP,
NULL,
NULL,
NULL))
{
printf("Error with AdjustTokenPrivileges: %dn", GetLastError());
Ret=0;
goto bye;
}
bye:
if(hToken)
CloseHandle(hToken);
return Ret;
}
int main(int argc, char * argv[])
{
HANDLE hProcess, hThread, hThreadSnap;
DWORD PID, TID;
DWORD64 Displacement;
THREADENTRY32 Th32;
STACKFRAME64 StackFrame;
IMAGEHLP_MODULE64 IM;
CONTEXT Context;
PSYMBOL_INFO pSI;
SymSetOptions(SYMOPT_UNDNAME|SYMOPT_DEFERRED_LOADS);
RtlSecureZeroMemory(&Th32, sizeof(THREADENTRY32));
RtlSecureZeroMemory(&IM, sizeof(IMAGEHLP_MODULE64));
IM.SizeOfStruct=sizeof(IMAGEHLP_MODULE64);
if(argc!=2)
return 0;
PID=NameToPid(argv[1]);
if(!PID)
{
printf("Error with NameToPid : %dn", GetLastError());
return 0;
}
//pour les process system
EnablePrivilege("SeDebugPrivilege");
hProcess=OpenProcess(PROCESS_VM_OPERATION|
PROCESS_VM_WRITE|
PROCESS_VM_READ|
PROCESS_CREATE_THREAD|
PROCESS_QUERY_INFORMATION,
FALSE, PID);
if(!hProcess)
{
printf("Error with OpenProcess : %dn", GetLastError());
goto cleanup;
}
/*
fInvadeProcess
[in] If this value is TRUE, enumerates the loaded modules for the process and effectively
calls the SymLoadModule64 function for each module.
*/
if(!SymInitialize(hProcess, NULL, true))
{
printf("Error with SymInitialize : %xn", GetLastError());
goto cleanup;
}
hThreadSnap=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
Th32.dwSize=sizeof(THREADENTRY32);
if(!Thread32First(hThreadSnap,&Th32))
{
printf("Error with Thread32First : %dn", GetLastError());
goto cleanup;
}
//on se place sur le 1er thread de notre process
while(Th32.th32OwnerProcessID!=PID)
Thread32Next(hThreadSnap,&Th32);
pSI=(PSYMBOL_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SYMBOL_INFO)+MAX_SYM_NAME);
if(!pSI)
goto cleanup;
//tant que le thread appartient au process
while(Th32.th32OwnerProcessID==PID)
{
TID=Th32.th32ThreadID;
printf("nThread ID : %dn", TID);
RtlSecureZeroMemory(pSI, sizeof(SYMBOL_INFO)+MAX_SYM_NAME);
pSI->SizeOfStruct=sizeof(SYMBOL_INFO);
pSI->MaxNameLen=MAX_SYM_NAME;
RtlSecureZeroMemory(&Context, sizeof(CONTEXT));
//EIP, EBP, ESP
Context.ContextFlags=CONTEXT_CONTROL;
RtlSecureZeroMemory(&StackFrame, sizeof(STACKFRAME64));
hThread=OpenThread(THREAD_QUERY_INFORMATION|THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, false, TID);
if(!hThread)
{
printf("Error with OpenThread : %dn", GetLastError());
goto cleanup;
}
//met en pause le thread
SuspendThread(hThread);
if(!GetThreadContext(hThread, &Context))
{
printf("Error with GetThreadContext : %dn", GetLastError());
goto cleanup;
}
StackFrame.AddrPC.Offset=Context.Eip;
StackFrame.AddrPC.Mode=AddrModeFlat;
StackFrame.AddrFrame.Offset=Context.Ebp;
StackFrame.AddrFrame.Mode=AddrModeFlat;
StackFrame.AddrStack.Offset=Context.Esp;
StackFrame.AddrStack.Mode=AddrModeFlat;
StackFrame.AddrReturn.Mode=AddrModeFlat;
/*
printf("Eip : 0x%xn", Context.Eip);
printf("Esp : 0x%xn", Context.Esp);
printf("Ebp : 0x%xn", Context.Ebp);
*/
//parcourt la pile
do
{
//printf("AddrReturn : 0x%xn", StackFrame.AddrReturn.Offset);
//va fouiller la stack
if(!StackWalk64(IMAGE_FILE_MACHINE_I386,
hProcess,
hThread,
&StackFrame,
&Context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL))
{
// Note that StackWalk64 generally does not set the last error code.
printf("Error with StackWalk");
//return 0;
}
if(SymFromAddr(hProcess, (DWORD)StackFrame.AddrReturn.Offset, &Displacement, pSI))
{
if(SymGetModuleInfo64(hProcess, pSI->ModBase, &IM))
printf("0x%x : %s!%s+0x%xn",(DWORD)pSI->Address, IM.ModuleName, pSI->Name, Displacement);
}
//else
//printf("Error with SymFromAddr : %dn", GetLastError());
}while(StackFrame.AddrReturn.Offset!=0);
//relance le thread
ResumeThread(hThread);
CloseHandle(hThread);
Thread32Next(hThreadSnap,&Th32);
}
cleanup:
if(hProcess)
CloseHandle(hProcess);
SymCleanup(hProcess);
return 0;
}
————CUT HERE——————–
A l’utilisation ca donne :
C:ProgHackc>StackWatcher cmd.exe
Thread ID : 392
0x7c91e9b4 : ntdll!ZwWaitForSingleObject+0xc
0x7c802540 : kernel32!WaitForSingleObjectEx+0xa8
0x7c802520 : kernel32!WaitForSingleObject+0x12
0x4ad02cf4 : CMD!WaitProc+0x18
0x4ad02ff8 : CMD!ExecPgm+0x3fa
0x4ad02d42 : CMD!ECWork+0x84
0x4ad02dcb : CMD!ExtCom+0x40
0x4ad0145d : CMD!FindFixAndRun+0xcf
0x4ad01375 : CMD!Dispatch+0x137
0x4ad03ff1 : CMD!main+0x216
0x4ad05056 : CMD!mainCRTStartup+0x125
0x7c816fb4 : kernel32!BaseProcessStart+0x23
Impressive n’est-il pas ? :}
L’intéret ca peut être de savoir par ou est passé un code pour éxecuté une
action. Dans l’exemple suivant j’ai mit un BP sur l’API native ZwCreateProcessEx
qui vous vous en doutez sert a crée à process, je l’ai mit dans explorer.exe,
donc quand je vais lancer un process le programme va être stopé par le
breakpoint et si on lance StackWatcher on peut voir :
[...]
Breakpoint sur ZwCreateProcessEx de ntdll.dll l'api native qui call le noyau
pour lancer un process
Thread ID : 2008
0x7c819513 : kernel32!CreateProcessInternalW+0x1327
0x7c802332 : kernel32!CreateProcessW+0x2c
0x7ca11f93 : SHELL32!_SHCreateProcess+0x387
0x7ca11e7a : SHELL32!CShellExecute::_DoExecCommand+0xb4
0x7ca11e21 : SHELL32!CShellExecute::_TryInvokeApplication+0x49
0x7ca118b9 : SHELL32!CShellExecute::ExecuteNormal+0xb1
0x7ca11866 : SHELL32!ShellExecuteNormal+0x30
0x7ca117cb : SHELL32!ShellExecuteExW+0x8d
0x7ca1e4e4 : SHELL32!_InvokePidl+0x9f
0x7ca1e421 : SHELL32!CShellExecMenu::_InvokeOne+0xa0
0x7ca1e347 : SHELL32!CShellExecMenu::InvokeCommand+0xa7
0x7ca1e2ad : SHELL32!HDXA_LetHandlerProcessCommandEx+0xa5
0x7ca1e1b5 : SHELL32!CDefFolderMenu::InvokeCommand+0x17f
0x7ca300b2 : SHELL32!CShellLink::TargetContextMenu::InvokeCommand+0x22
0x7ca2fe91 : SHELL32!CShellLink::_InvokeCommandAsync+0x337
0x7ca2fe57 : SHELL32!CShellLink::InvokeCommand+0x259
0x7ca1e2ad : SHELL32!HDXA_LetHandlerProcessCommandEx+0xa5
0x7ca1e1b5 : SHELL32!CDefFolderMenu::InvokeCommand+0x17f
0x77f98355 : SHLWAPI!SHInvokeCommandsOnContextMenu+0x174
0x77f9926d : SHLWAPI!SHInvokeCommand+0x63
0x77f9932d : SHLWAPI!SHInvokeDefaultCommand+0x15
0x102c9a0 : explorer!CStartMenuHost::ExecItem+0x17
0x7cb6d9d7 : SHELL32!CStartMenuCallback::_ExecItem+0x17
0x7cb6f32e : SHELL32!CStartMenuCallback::CallbackSM+0xe0
0x7ca23edd : SHELL32!CMenuSFToolbar::CallCB+0xd9
0x7cba7520 : SHELL32!CMenuSFToolbar::v_ExecItem+0x8e
0x7cba40bf : SHELL32!CMenuToolbarBase::_DropDownOrExec+0xa6
0x7ca24a04 : SHELL32!CMenuToolbarBase::_OnNotify+0x2bf
0x7ca24401 : SHELL32!CMenuSFToolbar::_OnNotify+0x109
0x7ca2439a : SHELL32!CMenuToolbarBase::OnWinEvent+0x60
0x7ca2435a : SHELL32!CMenuSFToolbar::OnWinEvent+0x6b
0x7ca2428f : SHELL32!CMenuBand::OnWinEvent+0x1f8
0x7ca24159 : SHELL32!CMenuSite::v_WndProc+0xd9
0x7ca30e35 : SHELL32!CImpWndProc::s_WndProc+0x65
0x77d1870c : USER32!InternalCallWinProc+0x28
0x77d1875f : USER32!UserCallWinProcCheckWow+0x150
0x77d1b7d3 : USER32!SendMessageWorker+0x4a5
0x77d1b8ba : USER32!SendMessageW+0x7f
0x773aa3d1 : comctl32!CCSendNotify+0xc20
0x773ff831 : comctl32!TBSendUpClick+0x5f
0x77404778 : comctl32!TBOnLButtonUp+0x13b
0x77404bdb : comctl32!ToolbarWndProc+0xb30
0x77d1870c : USER32!InternalCallWinProc+0x28
0x77d1875f : USER32!UserCallWinProcCheckWow+0x150
0x77d1c5ee : USER32!CallWindowProcAorW+0x98
0x77d1c64a : USER32!CallWindowProcW+0x1b
0x773a1b3d : comctl32!CallOriginalWndProc+0x1a
0x773a1e6e : comctl32!CallNextSubclassProc+0x3c
0x773a2026 : comctl32!DefSubclassProc+0x46
0x7ca0ef96 : SHELL32!CSFToolbar::_DefWindowProc+0xb8
0x7ca0ef46 : SHELL32!CNotifySubclassWndProc::_SubclassWndProc+0x7d
0x773a1e6e : comctl32!CallNextSubclassProc+0x3c
0x773a207b : comctl32!MasterSubclassProc+0x54
0x77d1870c : USER32!InternalCallWinProc+0x28
0x77d1875f : USER32!UserCallWinProcCheckWow+0x150
0x77d188f1 : USER32!DispatchMessageWorker+0x306
0x77d18a01 : USER32!DispatchMessageW+0xf
0x100199d : explorer!CTray::_MessageLoop+0xd9
0x1011e62 : explorer!CTray::MainThreadProc+0x29
0x77f5422b : SHLWAPI!WrapperThreadProc+0x94
0x7c80b64c : kernel32!BaseThreadStart+0x37
Thread Id : XXX
[...]
Ouf ca fait de la peur :]
En tout cas je pense qu’il y moyen de bien s’amuser avec ce tools on peut
apprendre de bonne chose sur le fonctionnement de certains binaire system. Par
contre mieux vaut avoir les symbols pour ceux-ci si vous voulez des résultats
probants.
Enfin en reversant Process Explorer j’ai remarqué que le mofo utilisait un
driver afin de lire aussi la pile d’appel du thread dans le noyau, je suis
en train de continuer le combat afin que mon code le fasse aussi. Il m’a fallut
reverser le binaire, dumper le driver, reverse le driver …Bref ca ma bien
prit la tete pour capter le bordel. Je suis en train de recoder un tool qui
reprend son fonctionnement mais code est over crade, avec des bouts d’asm
partout et du DeviceIoControl() à la pelle donc celui la ca m’etonnerais que je le montre :]
En attendant vous avez de quoi vous amuser. Je vous file un .rar avec le binaire
les sources et les dll requises, enjoy !
http://membres.lycos.fr/moi118118/StackWatcher.rar
Ivanlef0u
« je te fist comme ca, comme ca et comme ca ! »
décembre 29th, 2006
Winsock Reversing
Yo all. Pour commencer je tiens à mettre en garde sur le contenu de cet article
pouvant causer mass cerebrals damages à vos petits neurones. En plus qu’il
commence a faire froid je vous recommande de caler sur votre tête un poulpe
sortit du micro-ondes afin que tout ça reste bien en place. Pour encore vous
faire plus de peur l’article va causer de Reverse Engineering sous Windows. Je
m’excuse d’avance pour l’emploi massif de la première personne du singuler
surement du a l’absorption de quantité non réglementé de chocapics périmés
qui font que le raisonnement qui va suivre pourra me faire passer pour un ouf
malade incompréhensible. J’écris donc ceci sous l’influence de substances
illicites ce qui me permet de décliner toute responsabilité dans les conneries
que je pourrais dire.
——–[Là où tout a commencé
Année 2006, mois de novembre, journée grise et vide, routinière. Je suis assis à
suivre les paroles sans intérêts d’irc, l’esprit vide et noir. Un BIP, une
lueur apparait, un message en PV, surement encore un boulay qui veut savoir
comment hacker un msn. Grosse erreur la question n’est pas idiote, cette
personne voulant garder l’anonymat à cause de ses précédents psychiatrique me
demande s’il est possible de capturer le traffic réseau d’un processus. Je lui
répond que cela est faisable et qu’il suffit de hooker les différentes fonctions
réseau, rien de difficile en apparence. Cela éveille ma curiosité, un doute
subsiste, quelles fonctions faudrait-il hooker. Apparait in my brain alors :
-send()
-recv()
-sento()
-recvfrom()
-WSASend()
-WSASenTo()
-WSARecv()
-WSARecvFrom
Argh, 8 fonctions à hooker mais avec tellement de point en commun que cela doit
être plus simple. Les 4 fonctions qui send, doivent surment avoir une fonction
commune, il suffirait de hooker cette fonction mère pour récup tout ce qui sort
du process. BANG IDA est lancé sur ws2_32.dll la librairie qui contient ces
fonctions. Une goute de sueur coule de ma tempe, 30 mins que je n’arrive pas a
trouver de point commun évident entre ces fonctions. Mince, c’est plus compliqué
que je le pensais. Bille en tête, la curiosité est plus forte, je veux
comprendre pour trouver un moyen de hooker simplement ces fonctions.
——–[« And tides of darkness swept over the world »
Délirant je lance mes outils favoris. IDA, OllyDbg, Live Kernel Debugger avec
les symbols configurer. Hop Hop Hop, j’examine le code ligne par lignes,
toujours plus vite, je trace avec Olly et j’arrive à comprendre que ces quelques
lignes d’asm on un rôle crucial.
in ws2_32.dll functions send(), WSASend()
[...]
.text:719F625F push [ebp+s]
.text:719F6262 call ?GetCountedDSocketFromSocket@DSOCKET@@
SGPAV1@I@Z ; DSOCKET::GetCountedDSocketFromSocket(uint)
.text:719F6267 mov esi, eax
.text:719F6269 test esi, esi
.text:719F626B jz loc_719FB706
.text:719F6271 push edi
.text:719F6272 mov eax, [esi+0Ch]
.text:719F6275 lea ecx, [ebp+dwErrCode]
.text:719F6278 push ecx
.text:719F6279 push [ebp+var_8]
.text:719F627C push [ebp+lpCompletionRoutine]
.text:719F627F push [ebp+lpOverlapped]
.text:719F6282 push [ebp+dwFlags]
.text:719F6285 push [ebp+lpNumberOfBytesSent]
.text:719F6288 push [ebp+dwBufferCount]
.text:719F628B push [ebp+lpBuffers]
.text:719F628E push [ebp+s]
.text:719F6291 call dword ptr [eax+64h]
Le dernier call appel un code qui se trouve dans mswsock.dll, voyons ca avec
l’aide des symbols.
.text:71995847 ; __stdcall WSPSend(x, x, x, x, x, x, x, x, x)
Bigre qu’est ce que c’est cette fonction WSPSEND, bon je me dis que p-e MS nous
l’a documenté je matte dans le SDK :
int WSPSend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno
);
W00t mega happy. J’ai trouvé la fonction mère à send() et WSASend(), je n’est
plus qu’à poser un hook, foutre ma cagoule et le tour sera joué. Avant de poser
le hook, il faudrait p-e connaitre l’adresse de cette fonction, dans mon cas
c’est 0×71995847 (windows xp pro sp2 avec les dernières updates) mais il y a de
forte chance quelle ne soit pas égale sur toutes les version de Win. FFS ! Il me
faut son addr, alors schéma classique comme la plupart des fonctions de DLL
celle ci doit être exportée et donc pour savoir ou elle est il suffit de faire :
GetProcAddress(GetModuleHandle(« mswsock.dll », « WSPSend »);
Et là, c’est le drame GetProcAddress renvoie 0, je matte l’Export Table de
mswsock.dll et je n’y trouve pas WSPSend !!! Brain Panic !!!
Bon après avoir pleurer toutes le liquide lacrymal de mon corps. Je me dis que
rien n’est magique et que ws2_32.dll doit se demerder à récup l’adresse de
WSPSend. Observons le code de plus prés :
.text:719F6291 call dword ptr [eax+64h]
D’ou vient la valeur de EAX, si on peut trouver ca on est bon.
.text:719F6272 mov eax, [esi+0Ch]
Now on cherche d’ou vient ESI.
.text:719F6267 mov esi, eax
text:719F6262 call ?GetCountedDSocketFromSocket@DSOCKET@@
SGPAV1@I@Z ; DSOCKET::GetCountedDSocketFromSocket(uint)
Eax est la valeur du retour du Call, donc le secret serait dans
GetCountedDSocketFromSocket (le nom en mousse ffs)
Allay on disass cette fonction :
.text:719F2B41 ; public: static class DSOCKET * __stdcall DSOCKET::GetCountedDSocketFromSocket(unsigned int)
.text:719F2B41 ?GetCountedDSocketFromSocket@DSOCKET@@SGPAV1@I@Z proc near
.text:719F2B41 ; CODE XREF: sendto+45p
.text:719F2B41 ; recvfrom+45p ...
.text:719F2B41
.text:719F2B41 arg_0 = dword ptr 8
.text:719F2B41
.text:719F2B41 ; FUNCTION CHUNK AT .text:719F6388 SIZE 00000006 BYTES
.text:719F2B41
.text:719F2B41 mov edi, edi
.text:719F2B43 push ebp
.text:719F2B44 mov ebp, esp
.text:719F2B46 push [ebp+arg_0]
.text:719F2B49 push ?sm_context_table@DSOCKET
@@0PAU_CONTEXT_TABLE@@A ; _CONTEXT_TABLE * DSOCKET::sm_context_table
.text:719F2B4F call ds:__imp__WahReferenceContextByHandle@8 ;
WahReferenceContextByHandle(x,x)
.text:719F2B55 test eax, eax
.text:719F2B57 jz loc_719F6388
.text:719F2B5D pop ebp
.text:719F2B5E retn 4
.text:719F2B5E ?GetCountedDSocketFromSocket@DSOCKET@@SGPAV1@I@Z endp
.text:719F2B5E
Cool fonction super courte, on push un truc qui s’appel sm_context_table et puis
la valeur du socket, sisi ebp+arg_0 est l’adresse dans la pile de l’argument
numéro 0 (le premier quoi) qui avant le call sur GetCountedDSocketFromSocket est
.text:719F625F push [ebp+s] (s etant définit dans le SDK,
voir le prototype de WSPSend plus haut)
Bref cette fonction utilise notre socket et une sorte de table pour nous sortir
l’adresse d’un truc qui nous permettra d’appeler WPSSend. Bon voyons un peu ca
avec le LKD.
lkd> uf WS2_32!DSOCKET::GetCountedDSocketFromSocket
WS2_32!DSOCKET::GetCountedDSocketFromSocket:
719f2b41 8bff mov edi,edi
719f2b43 55 push ebp
719f2b44 8bec mov ebp,esp
719f2b46 ff7508 push dword ptr [ebp+8]
719f2b49 ff353040a071 push dword ptr [WS2_32!DSOCKET::sm_context_table (71a04030)]
719f2b4f ff15b8109f71 call dword ptr [WS2_32!_imp__WahReferenceContextByHandle (719f10b8)]
719f2b55 85c0 test eax,eax
719f2b57 0f842b380000 je WS2_32!DSOCKET::GetCountedDSocketFromSocket+0x18 (719f6388)
WS2_32!DSOCKET::GetCountedDSocketFromSocket+0x1e:
719f2b5d 5d pop ebp
719f2b5e c20400 ret 4
WS2_32!DSOCKET::GetCountedDSocketFromSocket+0x18:
719f6388 5d pop ebp
[....]
Mauvaise nouvelle la sm_context_table est un pointeur hardcodé. Donc impossible
de savoir cette adresse sur tout les Windows. Essayons quand meme de coder
quelque chose. Car la bonne nouvelle est que WahReferenceContextByHandle() est
une fonction exportée par ws2help.dll, Apres moult réflexions je pond ca :
————CUT HERE——————–
#include <windows.h>
//#include <winsock2.h>
#include <stdio.h>
#pragma comment (lib, "ws2_32.lib")
PDWORD PSM_CONTEXT_TABLE=(PDWORD)0x71a04030; //ca suxx ffs
PDWORD
(__stdcall * pWahReferenceContextByHandle)(
PDWORD sm_context_table,
SOCKET handle);
int main(int argc, char * argv[])
{
HMODULE hLib;
SOCKET sock;
WSADATA wsadata;
PDWORD pWSP;
if((WSAStartup(MAKEWORD(2,2), &wsadata))!=NO_ERROR)
{
printf("Error with WSAStartup: %dn", GetLastError());
return 0;
}
hLib=LoadLibrary("ws2help.dll");
*(FARPROC *)&pWahReferenceContextByHandle=GetProcAddress(
GetModuleHandle("ws2help.dll"),
"WahReferenceContextByHandle");
if(!pWahReferenceContextByHandle)
return 0;
sock=socket(AF_INET,SOCK_STREAM,0);
pWSP=pWahReferenceContextByHandle((PDWORD)(*PSM_CONTEXT_TABLE), sock);
if(!pWSP)
return 0;
//.text:719F2CB3 mov esi, eax <-
//.text:719F2CDF mov eax, [esi+0Ch] <-
//.text:719F2CEC call dword ptr [eax+64h] <-WSPSend() !!
//send : call dword ptr [eax+64h] -> WSPSend
//WSASend : call dword ptr [eax+64h] -> WSPSend
//sento : call dword ptr [eax+6Ch] -> WSPSendTo
//WSASendTo : call dword ptr [eax+6Ch] -> WSPSendTo
//recv : call dword ptr [eax+54h] -> WSPRecv
//WSARecv :call dword ptr [eax+54h] -> WSPRecv
//recvfrom : call dword ptr [eax+5Ch] ->WSPRecvFrom
//WSARecvFrom call dword ptr [eax+5Ch] ->WSPRecvFrom
pWSP=(PDWORD)*(PDWORD)((PBYTE)pWSP+0xC);
printf("WSPSend: 0x%xn", *(PDWORD)((PBYTE)pWSP+0x64));
printf("WSPSendTo: 0x%xn", *(PDWORD)((PBYTE)pWSP+0x6C));
printf("WSPRecv: 0x%xn", *(PDWORD)((PBYTE)pWSP+0x54));
printf("WSPRecvFrom: 0x%xn", *(PDWORD)((PBYTE)pWSP+0x5C));
if(sock)
closesocket(sock);
return 0;
}
————CUT HERE——————–
Ce qui sort :
C:\ProgHack\c>WahReferenceContextByHandle
WSPSend: 0×71995847
WSPSendTo: 0x71992e85
WSPRecv: 0×71994342
WSPRecvFrom: 0×71993145
W00T on à les adresses de ces foutue fonctions. Les prototypes étant dans le SDK
poser un inline hook dessus suffira à intercepter tout leurs appels et ensuite
il suffit de traiter les données envoyés ou reçu. J’ai codé tout ca mais je ne
fournit pas le code parce qu’il est encore un peu expérimental. Plus tard
surement vous aurez quelque chose, ouais je suis méchant et alors !
——–[Need more hardcore stuff ?
Arrivé là je sais ou sont ces fonctions mais je suis obligé d’utilisé une
adresse hardcodé ce qui n’est pas portable. Je lance mon brain :
Chez moi lors du call a WSPSend eax vaut 0×00147330 voyons la mémoire à cet
endroit :
00147330 01 00 00 00 00 00 99 71 D9 B5 9A 71 98 69 99 71 .....™qÙµšq˜i™q
00147340 0F 7F 9A 71 A1 4D 99 71 54 AE 9A 71 4D 77 9A 71 šq¡M™qT®šqMwšq
00147350 5F 40 99 71 D0 53 99 71 B3 AE 9A 71 29 67 99 71 _@™qÐS™q³®šq)g™q
00147360 EF 64 99 71 21 B0 9A 71 31 B1 9A 71 49 3D 99 71 ïd™q!°šq1±šqI=™q
00147370 E5 5F 99 71 D5 AD 9A 71 DB 5C 99 71 90 A3 9A 71 å_™qÕšqÛ™q£šq
00147380 5D 76 99 71 42 43 99 71 93 9A 9A 71 45 31 99 71 ]v™qBC™q“ššqE1™q
00147390 58 2D 99 71 47 58 99 71 71 9C 9A 71 85 2E 99 71 X-™qGX™qqœšq….™q
001473A0 BB 51 99 71 D1 98 9A 71 15 46 99 71 0E 94 99 71 »Q™qјšqF™q”™q
Ca ressemble bien à une table contenant les adresses des différentes
fonctions. Reste a savoir comment a été pondu cette table.
Je reprendre le code d’un petit client TCP et pose un breakpoint en écriture
n’importe ou à partir de 0×00147330 et je regarde la pile d’appel :]
Toute la pile n’est pas interessant mais ca !
mswsock.dll!WSPStartup+0x14c
WS2_32.dll!DPROVIDER::Initialize+0×181
WS2_32.dll!DCATALOG::LoadProvider+0x6d
WS2_32.dll!DCATALOG::GetCountedCatalogItemFromAttributes+0xf5
WS2_32.dll!WSASocketW+0×89
WS2_32.dll!socket+0×73
Ca se lit du bas vers le haut:
socket() fait appel à WSASocketW(), elle méme appel
GetCountedCatalogItemFromAttributes() qui lance une fonction avec le joli nom
de LoadProvider() qui launch Initialize() et enfin WSPStartup() de mswsock.dll.
Donc en brainant 2 sec on devine que le provideur doit remplir la table avec
l’adresse des fonctions, regardons ca sous IDA.
.text:719F48E2 ; private: int __thiscall DCATALOG::LoadProvider(class PROTO_CATALOG_ITEM *)
.text:719F48E2 ?LoadProvider@DCATALOG@@AAEHPAVPROTO_CATALOG_ITEM@@@Z proc near
.text:719F48E2
.text:719F48E2 lpCriticalSection= dword ptr -4
.text:719F48E2 arg_0 = dword ptr 8
[....]
lea eax, [esi+10h]
push eax ; int
lea eax, [esi+284h]
push eax ; lpSrc
mov ecx, edi
call ?Initialize@DPROVIDER@@QAEHPADPAU_WSAPROTOCOL_INFOW@@@Z ;
DPROVIDER::Initialize(char *,_WSAPROTOCOL_INFOW *)
mov ebx, eax
test ebx, ebx
jnz short loc_719F495B
[....]
Si ca parle pas ca, la fonction initialise un provideur qui va remplir la table
pour savoir l’adresse des fonctions:
lkd> uf WS2_32!DPROVIDER::Initialize
WS2_32!DPROVIDER::Initialize:
719f73ea 685c030000 push 35Ch
719f73ef 6898769f71 push offset WS2_32!`string'+0xc (719f7698)
719f73f4 e8e79dffff call WS2_32!_SEH_prolog (719f11e0)
719f73f9 a13440a071 mov eax,dword ptr [WS2_32!__security_cookie (71a04034)]
719f73fe 8945e4 mov dword ptr [ebp-1Ch],eax
719f7401 8bd9 mov ebx,ecx
719f7403 899dd4fcffff mov dword ptr [ebp-32Ch],ebx
719f7409 8b5508 mov edx,dword ptr [ebp+8]
719f740c 8b450c mov eax,dword ptr [ebp+0Ch]
719f740f 8985d0fcffff mov dword ptr [ebp-330h],eax
719f7415 83a5d8fcffff00 and dword ptr [ebp-328h],0
719f741c 8d7308 lea esi,[ebx+8]
719f741f 6a1e push 1Eh
719f7421 59 pop ecx
719f7422 33c0 xor eax,eax
719f7424 8bfe mov edi,esi
719f7426 f3ab rep stos dword ptr es:[edi]
719f7428 6a0f push 0Fh
719f742a 59 pop ecx
719f742b 8dbd94fcffff lea edi,[ebp-36Ch]
719f7431 f3ab rep stos dword ptr es:[edi]
719f7433 c78594fcffff951ba071 mov dword ptr [ebp-36Ch],offset WS2_32!WPUCloseEvent (71a01b95)
719f743d c78598fcffff700ea071 mov dword ptr [ebp-368h],offset WS2_32!WPUCloseSocketHandle (71a00e70)
719f7447 c7859cfcffffc11ba071 mov dword ptr [ebp-364h],offset WS2_32!WPUCreateEvent (71a01bc1)
719f7451 c785a0fcffff4810a071 mov dword ptr [ebp-360h],offset WS2_32!WPUCreateSocketHandle (71a01048)
719f745b c785acfcffff103d9f71 mov dword ptr [ebp-354h],offset WS2_32!WPUModifyIFSHandle (719f3d10)
719f7465 c785b4fcffffe6409f71 mov dword ptr [ebp-34Ch],offset WS2_32!WPUQueryBlockingCallback (719f40e6)
719f746f c785b8fcffff0a0fa071 mov dword ptr [ebp-348h],offset WS2_32!WPUQuerySocketHandleContext (71a00f0a)
719f7479 c785bcfcffff4a1ca071 mov dword ptr [ebp-344h],offset WS2_32!WPUQueueApc (71a01c4a)
719f7483 c785c0fcfffff21ba071 mov dword ptr [ebp-340h],offset WS2_32!WPUResetEvent (71a01bf2)
719f748d c785c4fcffff1e1ca071 mov dword ptr [ebp-33Ch],offset WS2_32!WPUSetEvent (71a01c1e)
719f7497 c785b0fcffffb51da071 mov dword ptr [ebp-350h],offset WS2_32!WPUPostMessage (71a01db5)
719f74a1 c785a8fcffff328a9f71 mov dword ptr [ebp-358h],offset WS2_32!WPUGetProviderPath (719f8a32)
719f74ab c785a4fcffff6909a071 mov dword ptr [ebp-35Ch],offset WS2_32!WPUFDIsSet (71a00969)
719f74b5 c785c8fcffff071da071 mov dword ptr [ebp-338h],offset WS2_32!WPUOpenCurrentThread (71a01d07)
719f74bf c785ccfcffff5e1da071 mov dword ptr [ebp-334h],offset WS2_32!WPUCloseThread (71a01d5e)
719f74c9 6804010000 push 104h
719f74ce 8d85e0feffff lea eax,[ebp-120h]
719f74d4 50 push eax
719f74d5 52 push edx
719f74d6 ff152c119f71 call dword ptr [WS2_32!_imp__ExpandEnvironmentStringsA (719f112c)]
719f74dc 85c0 test eax,eax
719f74de 0f84f82f0000 je WS2_32!DPROVIDER::Initialize+0xf6 (719fa4dc)
WS2_32!DPROVIDER::Initialize+0x105:
719f74e4 8d85e0feffff lea eax,[ebp-120h]
719f74ea 50 push eax
719f74eb ff1568119f71 call dword ptr [WS2_32!_imp__LoadLibraryA (719f1168)]
719f74f1 894304 mov dword ptr [ebx+4],eax
719f74f4 85c0 test eax,eax
719f74f6 0f84ef2f0000 je WS2_32!DPROVIDER::Initialize+0x119 (719fa4eb)
WS2_32!DPROVIDER::Initialize+0x147:
719f74fc 688c769f71 push offset WS2_32!`string' (719f768c)
719f7501 50 push eax
719f7502 ff155c119f71 call dword ptr [WS2_32!_imp__GetProcAddress (719f115c)]
719f7508 85c0 test eax,eax
719f750a 0f84ef2f0000 je WS2_32!DPROVIDER::Initialize+0x12d (719fa4ff)
WS2_32!DPROVIDER::Initialize+0x157:
719f7510 8365fc00 and dword ptr [ebp-4],0
719f7514 56 push esi
719f7515 83ec3c sub esp,3Ch
719f7518 6a0f push 0Fh
719f751a 59 pop ecx
719f751b 8db594fcffff lea esi,[ebp-36Ch]
719f7521 8bfc mov edi,esp
719f7523 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
719f7525 ffb5d0fcffff push dword ptr [ebp-330h]
719f752b 8d8ddcfcffff lea ecx,[ebp-324h]
719f7531 51 push ecx
719f7532 be02020000 mov esi,202h
719f7537 56 push esi
719f7538 ffd0 call eax
[....]
Le call eax, lance la fonction WSPStartup et comme de par hasard WSPStartup est
une fonction exportée par mswsock.dll de prototype :
int WSPStartup(
WORD wVersionRequested,
LPWSPDATA lpWSPData,
LPWSAPROTOCOL_INFO lpProtocolInfo,
WSPUPCALLTABLE UpcallTable,
LPWSPPROC_TABLE lpProcTable
);
Tient lpProcTable de type LPWSPPROC_TABLE une table ?!!!!! mais qu’est ce donc !
from ws2spi.h
/*
* A service provider proc table. This structure is returned by value
* from the service provider's WSPStartup() entrypoint.
*/
typedef struct _WSPPROC_TABLE {
LPWSPACCEPT lpWSPAccept;
LPWSPADDRESSTOSTRING lpWSPAddressToString;
LPWSPASYNCSELECT lpWSPAsyncSelect;
LPWSPBIND lpWSPBind;
LPWSPCANCELBLOCKINGCALL lpWSPCancelBlockingCall;
LPWSPCLEANUP lpWSPCleanup;
LPWSPCLOSESOCKET lpWSPCloseSocket;
LPWSPCONNECT lpWSPConnect;
LPWSPDUPLICATESOCKET lpWSPDuplicateSocket;
LPWSPENUMNETWORKEVENTS lpWSPEnumNetworkEvents;
LPWSPEVENTSELECT lpWSPEventSelect;
LPWSPGETOVERLAPPEDRESULT lpWSPGetOverlappedResult;
LPWSPGETPEERNAME lpWSPGetPeerName;
LPWSPGETSOCKNAME lpWSPGetSockName;
LPWSPGETSOCKOPT lpWSPGetSockOpt;
LPWSPGETQOSBYNAME lpWSPGetQOSByName;
LPWSPIOCTL lpWSPIoctl;
LPWSPJOINLEAF lpWSPJoinLeaf;
LPWSPLISTEN lpWSPListen;
LPWSPRECV lpWSPRecv;
LPWSPRECVDISCONNECT lpWSPRecvDisconnect;
LPWSPRECVFROM lpWSPRecvFrom;
LPWSPSELECT lpWSPSelect;
LPWSPSEND lpWSPSend;
LPWSPSENDDISCONNECT lpWSPSendDisconnect;
LPWSPSENDTO lpWSPSendTo;
LPWSPSETSOCKOPT lpWSPSetSockOpt;
LPWSPSHUTDOWN lpWSPShutdown;
LPWSPSOCKET lpWSPSocket;
LPWSPSTRINGTOADDRESS lpWSPStringToAddress;
} WSPPROC_TABLE, FAR * LPWSPPROC_TABLE;
Hooooo mais c’est la table qui contient les adresses de nos fonctions ca.
L’autre table UpcallTable ne m’interesse pas.
Dans WSPStartup apparait :
7199c46f 6a1e push 1Eh
7199c471 59 pop ecx //ECX=0x1E
7199c472 be60729c71 mov esi,offset mswsock!SockProcTable (719c7260)
7199c477 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
edi étant lpProcTable.
Cela veut dire que l’on recopie 0x1E adresses dans notre lpProcTable, et les
adresses originales sont stocké en mémoire à l’adresse virtuelle 0x719c7260
(SockProcTable), ce qui veut dire quelle ne sont en aucun cas générés mais
hardcodés ! Et donc quelles sont dans la section .data (donnés initialisées) de
mswsock.dll.
section .data en mémoire
719C7000 C7 72 9B 71 BB 72 9B 71 DF 72 9B 71 AF 72 9B 71 Çr›q»r›qßr›q¯r›q
719C7010 A3 72 9B 71 97 72 9B 71 8B 72 9B 71 7F 72 9B 71 £r›q—r›q‹r›qr›q
719C7020 62 72 9B 71 D3 72 9B 71 67 89 9B 71 58 89 9B 71 br›qÓr›qg‰›qX‰›q
719C7030 76 89 9B 71 00 00 00 00 D6 C9 99 71 44 74 9B 71 v‰›q....ÖÉ™qDt›q
719C7040 12 CA 99 71 03 CA 99 71 E5 C9 99 71 2A 74 9B 71 Ê™qÊ™qåÉ™q*t›q
719C7050 F4 C9 99 71 00 00 00 00 A5 8A 99 71 B7 89 99 71 ôÉ™q....¥Š™q·‰™q
719C7060 C6 87 9B 71 E0 87 9B 71 FA 87 9B 71 00 00 00 00 Ƈ›qà‡›qú‡›q....
719C7070 31 88 9B 71 14 88 9B 71 3D 88 9B 71 49 88 9B 71 1ˆ›qˆ›q=ˆ›qIˆ›q
719C7080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C70F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7180 00 00 00 00 84 71 9C 71 84 71 9C 71 8C 71 9C 71 ....„qœq„qœqŒqœq
719C7190 8C 71 9C 71 00 00 00 00 00 00 00 00 00 00 99 71 Œqœq..........™q
719C71A0 00 00 99 71 00 00 14 00 FE FF FF FF 00 00 00 00 ..™q...þÿÿÿ....
719C71B0 C8 73 14 00 00 00 00 00 01 00 00 00 58 0C 00 00 Ès........X...
719C71C0 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ............ÿÿÿÿ
719C71D0 00 00 00 00 00 00 00 00 C0 78 9C 71 01 00 00 00 ........Àxœq...
719C71E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C71F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7200 00 00 00 00 00 00 00 00 00 00 00 00 A0 88 14 00 ............ ˆ.
719C7210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
719C7220 00 00 00 00 00 00 00 00 00 00 00 00 7D 29 00 00 ............})..
719C7230 70 74 14 00 FF FF FF FF 00 00 00 00 00 00 00 00 pt.ÿÿÿÿ........
719C7240 00 00 00 00 00 00 00 00 38 74 14 00 FF FF FF FF ........8t.ÿÿÿÿ
719C7250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
Ici commence la SockProcTable
719C7260 D9 B5 9A 71 98 69 99 71 0F 7F 9A 71 A1 4D 99 71 Ùµšq˜i™qšq¡M™q
719C7270 54 AE 9A 71 4D 77 9A 71 5F 40 99 71 D0 53 99 71 T®šqMwšq_@™qÐS™q
719C7280 B3 AE 9A 71 29 67 99 71 EF 64 99 71 21 B0 9A 71 ³®šq)g™qïd™q!°šq
719C7290 31 B1 9A 71 49 3D 99 71 E5 5F 99 71 D5 AD 9A 71 1±šqI=™qå_™qÕšq
719C72A0 DB 5C 99 71 90 A3 9A 71 5D 76 99 71 42 43 99 71 Û™q£šq]v™qBC™q
719C72B0 93 9A 9A 71 45 31 99 71 58 2D 99 71 47 58 99 71 “ššqE1™qX-™qGX™q
719C72C0 71 9C 9A 71 85 2E 99 71 BB 51 99 71 D1 98 9A 71 qœšq….™q»Q™qјšq
719C72D0 15 46 99 71 0E 94 99 71 00 00 00 00 00 00 00 00 F™q”™q........
719C72E0 2C 00 00 00 01 00 00 00 01 00 00 00 51 90 99 71 ,.........Q™q
719C72F0 AA 1E 99 71 5B 19 99 71 06 1D 99 71 3C CE 9A 71 ª™q[™q™q<Κq
719C7300 4F CE 9A 71 4F CE 9A 71 65 CE 9A 71 00 00 00 00 OΚqOΚqeΚq....
719C7310 00 A8 02 00 00 00 00 00 C0 00 00 00 00 00 00 46 .¨.....À......F
719C7320 01 A8 02 00 00 00 00 00 C0 00 00 00 00 00 00 46 ¨.....À......F
719C7330 02 A8 02 00 00 00 00 00 C0 00 00 00 00 00 00 46 ¨.....À......F
719C7340 03 A8 02 00 00 00 00 00 C0 00 00 00 00 00 00 46 ¨.....À......F
Alors la ce qu'il faut faire c'est izi, on load la lib en mémoire on cherche la
section .data, on va a 0x260 dedans et PAF on a notre table :]
BOOM le code dans ta face !
------------CUT HERE--------------------
#include <ws2spi.h>
#include <windows.h>
#include <stdio.h>
int main(int argc, char * argv[])
{
HMODULE hMswsock;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS32 pNtHeaders;
PIMAGE_SECTION_HEADER pDataSection;
LPWSPPROC_TABLE SockProcTable;
hMswsock=LoadLibrary("mswsock.dll");
if(!hMswsock)
return 0;
pDosHeader=(PIMAGE_DOS_HEADER)hMswsock;
pNtHeaders=(PIMAGE_NT_HEADERS32)((PBYTE)pDosHeader->e_lfanew + (DWORD)pDosHeader);
// la section data est la 3 eme section
pDataSection=(PIMAGE_SECTION_HEADER)((PBYTE)pNtHeaders
+sizeof(IMAGE_NT_HEADERS32)
+2*sizeof(IMAGE_SECTION_HEADER));
SockProcTable=(LPWSPPROC_TABLE)((PBYTE)hMswsock+pDataSection-
>VirtualAddress+0x260);
printf("WSPSend: 0x%xn", SockProcTable->lpWSPSend);
printf("WSPSendTo: 0x%xn", SockProcTable->lpWSPSendTo);
printf("WSPRecv: 0x%xn", SockProcTable->lpWSPRecv);
printf("WSPRecvFrom: 0x%xn", SockProcTable->lpWSPRecvFrom);
return 0;
}
------------CUT HERE--------------------
C:\ProgHack\c>SockProcTable
WSPSend: 0x71995847
WSPSendTo: 0x71992e85
WSPRecv: 0x71994342
WSPRecvFrom: 0x71993145
W00T
Maintenant qu'on connait les adresses de facon un peu plus fiable, on peut
mettres nos hooks et jouer avec ces jolies fonctions, mais ca ca sera pour plus
tard :=]. J'ai trouvé un peu de doc sur le net à ce sujet mais je ne l'est
découvert qu'après tout ca, si ca peut vous aider a capter :
http://www.microsoft.com/msj/0599/LayeredService/LayeredService.aspx
J'espère que vous n'avez rien compris à cet article et que le temps que vous
avez mit a lire me permet de penser que vous ne l'avez pas perdu à le foutre en
l'air pour Noel.
Ivanlef0u
Merci a BufferBob pour m'avoir donné l'idée, ca ma permit d'oublier qu'il
faisait -8000 dehors.
décembre 29th, 2006
Yo, c’est nowel alors je poste un petit code avec lequel vous pourrez jouer
pendant les vacs. Vous le savez lorsque un programme sous Windows plante il
demande si vous voulez envoyer un rapport à MS. Mais c’est quoi ce rapport ffs
?! C’est tout simplement un Crash Dump de votre programme qui à planté, un
fichier qui contient des infos sur le process, ses threads, les dll loadées,
l’OS etc …
Pour avoir notre propre crash dump c’est simple, il suffit d’utiliser l’API
MiniDumpWriteDump() de Dbghelp.dll fournit avec les debugging tools de Windows
et dispo gratos sur leur site. Après c’est tout con, on dit au gestionnaire
d’exceptions de lancer notre fonction en cas d’exception non gérée (vous savez
le msg qui dit que votre prog à teplan) puis de crée le dump.
————CUT HERE——————–
#include
#include
#include
//pour linker avec la lib
#pragma comment (lib, "Dbghelp.lib")
/* exception non gérée, on crée un dump */
LONG WINAPI UnhandledExceptionDump(struct _EXCEPTION_POINTERS* ExceptionInfo)
{
HANDLE hFile;
_MINIDUMP_EXCEPTION_INFORMATION ExceptInfo;
hFile=CreateFile("C:ExceptDump.dmp",
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
ExceptInfo.ThreadId=GetCurrentThreadId();
ExceptInfo.ExceptionPointers=ExceptionInfo;
ExceptInfo.ClientPointers=NULL;
MiniDumpWriteDump(GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
MiniDumpNormal,
&ExceptInfo,
NULL,
NULL);
CloseHandle(hFile);
//termine le programme en affichant la msgbox 'le prog à teplan'
return EXCEPTION_CONTINUE_SEARCH;
}
int main(int argc, char *argv[])
{
// filtre les execpt non handlé
SetUnhandledExceptionFilter(UnhandledExceptionDump);
// exception
*((PBYTE)0)=1;
return 0;
}
————CUT HERE——————–
Now qu’on a le dump. Il suffit de l’analyser, avec Windbg par exemple
(Minidump est le nom de mon .exe)
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************FAULTING_IP:
MiniDump+920
00400920 c6050000000001 mov byte ptr ds:[0],1
EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 00400920 (MiniDump+0x00000920)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 00000000
Attempt to write to address 00000000
DEFAULT_BUCKET_ID: NULL_DEREFERENCE
PROCESS_NAME: MiniDump.exe
ERROR_CODE: (NTSTATUS) 0xc0000005 - L'instruction "0x%08lx" emploie l'adresse
mémoire "0x%08lx".
La mémoire ne peut pas être "%s".
WRITE_ADDRESS: 00000000
BUGCHECK_STR: ACCESS_VIOLATION
LAST_CONTROL_TRANSFER: from 004009e6 to 00400920
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
0012ff80 004009e6 00000001 00510ed0 00510e30 MiniDump+0x920
0012ffc0 7c816fd7 00000018 00000000 7ffdf000 MiniDump+0x9e6
0012fff0 00000000 00400932 00000000 00000000 kernel32!BaseProcessStart+0x23
STACK_COMMAND: ~0s; .ecxr ; kb
FAULTING_THREAD: 0000048c
FOLLOWUP_IP:
MiniDump+920
00400920 c6050000000001 mov byte ptr ds:[0],1
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: MiniDump+920
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: MiniDump
IMAGE_NAME: MiniDump.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 458e997b
FAILURE_BUCKET_ID: ACCESS_VIOLATION_MiniDump+920
BUCKET_ID: ACCESS_VIOLATION_MiniDump+920
Followup: MachineOwner
---------
On a l’instruction ou a teplan le prog :
00400920 c6050000000001 mov byte ptr ds:[0],1
Après pour ceux qui ont pas Windbg j’ai trouvé un tool en surfant je vous le
donne :
http://www.debuginfo.com/tools/minidumpview.html
En fait il fonctionne avec l’API MiniDumpReadDumpStream() pour aller récup les
infos dans le fichier.
Tout est documenté sur le SDK, amusez vous bien.
Sur ce, bon noel à tous et vous bourrez pas trop la gueule :=]
Ivanlef0u
décembre 29th, 2006