Winsock Reversing

décembre 29th, 2006 at 05:28 admin

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.

Entry Filed under: Non classé

12 Comments

  • 1. TrOuBLe StarTeR  |  décembre 29th, 2006 at 18:15

    Bien beau l’article …

    :)))


  • 2. Christophe  |  février 13th, 2007 at 16:49

    Très bon article, en effet :-)


  • 3. Aemeath  |  avril 16th, 2007 at 23:00

    Fun =)


  • 4. Ivanlef0u’s Blog &r&hellip  |  juillet 10th, 2007 at 17:33

    [...] http://ivanlef0u.free.fr/?p=5 [...]


  • 5. o0Zz  |  mars 18th, 2008 at 18:11

    Très bon article qui m’a beaucoup aidé ! ;)

    Cependant j’ai une petite question : Serais-tu où trouver l’adresse de la fonction AcceptEx qui, a priori, serais dans la DLL mswsock.dll.

    J’aimerais la hooker, mais je n’ai pas réussi à récupérer sont adresse.

    Aurais tu le temps d’y jeter un petit coup d’oeil ? ;)

    Merci d’avance et bonne continuation pour ton blog ;)


  • 6. admin  |  mars 19th, 2008 at 00:42

    Yo

    AcceptEx est directement exportée par mswsock.dll. Pour avoir son adresse il suffit donc de faire un :
    GetProcAdress(GetModuleHandle(« mswsock.dll »), « AcceptEx »);

    Après pour la hooker il suffit de mettre un hook dans l’IAT de ton module qui l’importe.


  • 7. o0Zz  |  mars 19th, 2008 at 11:21

    Salut,

    Bon voila il suffi que tu le dise pour que ça marche.
    Très bizarre surtout que ça à était la première chose que j’ai testé avant de venir te voir…

    Enfin bref, en tout cas merci beaucoup et bonne continuation dans ton record de mangé de chocapics tapz ;)


  • 8. Cyb  |  août 13th, 2008 at 10:53

    Plop.

    Bon, sous Microsoft Windows Vista Business
    Edition, 32-bit Service Pack 1 [version 6.0.6001],
    il semble que les fonctions du Windows Socket
    Provider ne soient pas appelées. J’ai fait une
    petite DLL de Detours pour en être sûr, et on
    ne voit rien ….. Je vais donc faire la même chose
    que toi dans la bibliothèque WS2_32.DLL pour
    voir si j’y vois plus clair. Si tu l’as déjà fait, tiens
    moi au courant. Merci.

    Cyb


  • 9. admin  |  août 13th, 2008 at 11:14

    Yo, je trouve cela étonnant, j’ai plus le problème en tête je te conseil de lire la doc, dsl :p Transport Service Providers


  • 10. Cyb  |  août 13th, 2008 at 13:12

    Bon, en fait, je devais pas être bien réveillé ce
    matin. Il y a un décalage en dur dans ton code,
    le fameux 0×260. Sur ma machine, cet offset est
    de 0x3D8. Je vais regarder pourquoi, et si je peux
    pas rendre ca un peu plus hacky pour que ca
    marche sur mon XP et mon Vista à la fois.
    Merci pour le lien…

    Cyb.


  • 11. admin  |  août 13th, 2008 at 13:30

    Ok, chose normale sous Windows :) Au pire tu regarde la version de l’os sur laquelle tu te trouves et tu définis les offsets en fonction … Il doit surement avoir un moyen de retrouver cette table dynamiquement par exemple en cherchant dans mswsock.dll une fonction qui la référence puis d’en extraire l’offset, à voir …


  • 12. Cyb  |  août 13th, 2008 at 13:39

    Visiblement, WSPStartup s’y prend toujours de la
    même manière :


    .text:6C9489CA mov edi, [ebp+lpProcTable]
    .text:6C9489CD push 1Eh
    .text:6C9489CF pop ecx
    .text:6C9489D0 mov esi, offset off_6C9753D8
    .text:6C9489D5 rep movsd

    on le sent bien le 0x3D8 là …..
    Faut que je trouve comment récupérer ce truc.
    Merci pour tout, ton blog est super.

    Cyb


Trackback this post


Calendar

octobre 2021
L Ma Me J V S D
« fév    
 123
45678910
11121314151617
18192021222324
25262728293031

Most Recent Posts