Archive for décembre 29th, 2006

StackWatcher

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 ! »

1 comment décembre 29th, 2006

Winsock Reversing

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.

12 comments décembre 29th, 2006

Crash Dump

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

Add comment décembre 29th, 2006

Ouverture

Hello all, ca y est j’ai décidé de faire comme tout le monde, j’ai ouvert mon blog !

Dans celui ci vous découvrirez ma passion pour les courses d’escargots et je vous tiendrais au courant de l’évolution de ma collection de capsules de bières allemandes :]

Plus sérieusement j’exposerais mes trips (tripes?) dans lesquels je pond du code surtout au niveau RE, mes découvertes, mes projets, mes whines, bref geek’s life.

3 comments décembre 29th, 2006


Calendar

décembre 2006
L Ma Me J V S D
    jan »
 123
45678910
11121314151617
18192021222324
25262728293031

Posts by Month

Posts by Category