AccueilFAQStatistiquesDiversContact

Securité : Windows : wKillcx (fermer une connexion TCP sous Windows)

wKillcx est un utilitaire en ligne de commande permettant de fermer toute connexion TCP sous Windows XP/Vista/Seven ainsi que Windows Server 2003/2008. Le code source (assembleur) est inclus avec l'exécutable.


Dernière version : v1.0.1 (16-Juillet-2010)



I - Présentation :

wKillcx parcourt la table de connexion TCP pour rechercher l'IP et le port indiqués par l'utilisateur. Il fermera la connexion en changeant son état en MIB_TCP_STATE_DELETE_TCB à l'intérieur d'une structure MIB_TCPROW et enverra celle-ci avec l'API SetTcpEntry. La table de connection TCP se trouve en appelant soit l'API AllocateAndGetTcpExTableFromStack sous Windows XP SP1/Server 2003, soit GetExtendedTcpTable sous toute version plus récente de Windows.
Il va de soi que vous devez avoir les privileges administrateur pour fermer les connexions, faute de quoi wKillcx retournera une erreur.
Si vous recherchez un utilitaire identique mais sous Linux, consultez killcx.


II - Paramètres :


   syntaxe  : wkillcx [dest_ip:dest_port]

   exemple  : wkillcx 10.11.22.23:1234

dest_ip et dest_port correspondent à l'IP et port distants.


III - Source :

;=====================================================================
; [wkillcx] - (c) 2009 Jérôme Bruandet
;
; Sources + docs : http://spamcleaner.net/fr/misc/wkillcx.html
;
;---------------------------------------------------------------------
; Ferme une connexion TCP sous Windows
;
; OS           : Windows (XP/Vista/Seven + Windows Server 2003/2008)
; Langage      : Assembleur
; Compilateur  : Borland Tasm32
;
;---------------------------------------------------------------------
;Ce programme est libre, vous pouvez le redistribuer et/ou le modifier
;selon les termes de la Licence Publique Générale GNU publiée par
;la Free Software Foundation (version 3 ou bien toute autre version
;ultérieure choisie par vous).
;Ce programme est distribué car potentiellement utile, mais SANS AUCUNE
;GARANTIE, ni explicite ni implicite, y compris les garanties de
;commercialisation ou d'adaptation dans un but spécifique.
;Reportez-vous à la Licence Publique Générale GNU pour plus de détails.
;=====================================================================
.586p
locals
jumps
.model flat, STDCALL
; ====================================================================
; API :
extrn ExitProcess                : proc
extrn GetCommandLineA            : proc
extrn GetProcAddress             : proc
extrn GetProcessHeap             : proc
extrn GetStdHandle               : proc
extrn GlobalAlloc                : proc
extrn GlobalFree                 : proc
extrn GlobalLock                 : proc
extrn GlobalUnlock               : proc
extrn HeapFree                   : proc
extrn LoadLibraryA               : proc
extrn lstrlenA                   : proc
extrn WriteFile                  : proc
extrn _wsprintfA                 : proc
extrn htons                      : proc
extrn inet_addr                  : proc
extrn inet_ntoa                  : proc
; ====================================================================
.const
copyrightMsg   db 13,10, ' wkillcx - v1.0.1 - (c) 2009 Jerome Bruandet'
               db 13,10,13,10,0
syntaxMsg      db '   syntax   : wkillcx [dest_ip:dest_port]',13,10,13,10
               db '   example  : wkillcx 10.11.22.23:1234',13,10,13,10
               db '   full doc :  http://spamcleaner.net/en/misc/'
               db 'wkillcx.html',13,10,0
DLLname        db 'iphlpapi.dll',0
DLLnotfoundMsg db ' - error : cannot find [iphlpapi.dll] !',0
; XP / Windows Server 2003 :
winOldAPIname  db 'AllocateAndGetTcpExTableFromStack',0
; XP SP2 / Vista / Seven / Server 2003 SP1 & 2008 :
winNewApiName  db 'GetExtendedTcpTable',0
APInotfoundMsg db ' - error : your operating system is not compatible !'
               db ' Please read the doc file.',0
SetTcpEntry    db 'SetTcpEntry',0
SetTcpErrMsg   db ' - error : cannot find SetTcpEntry API !',0
NoCxMsg        db ' - error : there are currently no connection !',0
TotCxMsg       db ' - found [%i] connections, parsing them all',13,10,0
notFoundMsg    db ' - error : no matching connection found !',0
killOkMsg      db ' - success : connection has been closed !',0
killErr1Msg    db ' - error : you must have administrative privileges'
               db ' to kill a connection !',0
killErr2Msg    db ' - error : cannot kill the connection !',0
memErrMsg      db ' - error : GetExtendedTcpTable returned '
               db 'ERROR_INSUFFICIENT_BUFFER !',0
aagErrMsg      db " - error : AllocateAndGetTcpExTableFromStack didn't"
               db ' return ERROR_SUCCESS !',0
strErrMsg      db ' - error : cannot get TcpTable !',0
APIsizeBuffer  dd 10240
lookingMsg     db ' - looking for connection with [%s:%s]',13,10,0
endianErrMsg   db ' - error : network byte order conversion failed,'
               db ' check IP or port syntax.',0
foundFormat    db ' - found connection with [%s:%i]',13,10,0
Exiting        db 13,10,13,10, ' Exiting.',13,10,0

.data
MIB_TCP        struc
 dwState       dd ?
 dwLocalAddr   dd ?
 dwLocalPort   dd ?
 dwRemoteAddr  dd ?
 dwRemotePort  dd ?
MIB_TCP        ends
TCPtable       MIB_TCP <>
oldWinVer      db 0
APIaddress     dd 0
hProcess       dd 0
null           dd 0
APImemAlloc    dd 0
APIptr         dd 0
memAlloc       dd 0
SetTcpEntryAPI dd 0
bytesWritten   dd 0
stdout         dd 0
ip_string      db 16 dup (0)
port_string    db 5 dup (0)
searchRemAddr  dd 0
searchRemPort  dd 0
outBuffer      db 150 dup (0)

; ====================================================================
.code

start:
   ; récupère le handle de la console :
   call     GetStdHandle, -11
   mov      stdout, eax
   call     Write2Console, offset copyrightMsg

   ; charge iphlpapi.dll :
   call     LoadLibraryA, offset DLLname
   test     eax, eax
   jnz      DLL_found
   push     offset DLLnotfoundMsg
   jmp      quit

DLL_found:
   mov      null, eax
   ; recherche AllocateAndGetTcpExTableFromStack :
   call     GetProcAddress, eax, offset winOldAPIname
   test     eax, eax
   jz       isNewer
   mov      oldWinVer, 1
   mov      APIaddress, eax
   call     GetProcessHeap
   mov      hProcess, eax
   jmp      API_found

isNewer:
   ; recherche GetExtendedTcpTable :
   call     GetProcAddress, null, offset winNewApiName
   test     eax, eax
   jnz      isNewer2
   push     offset APInotfoundMsg
   jmp      quit

isNewer2:
   mov      APIaddress, eax
   ; alloue un buffer de 10Ko pour TcpTable :
   call     GlobalAlloc, 42h, 10240          ; GHND
   mov      APImemAlloc, eax
   call     GlobalLock, eax
   mov      APIptr, eax

API_found:
   ; recherche le point d'entrée de SetTcpEntry :
   call     GetProcAddress, null, offset SetTcpEntry
   test     eax, eax
   jnz      saveTcpEntry
   push     offset SetTcpErrMsg
   jmp      quit
saveTcpEntry:
   mov      SetTcpEntryAPI, eax

   ; récupère les paramètres de ligne de commande :
   call     GetCommandLineA
   ; récupère l'IP/port :
   call     ParseCmdLine
   test     eax, eax
   jz       display_lookingMsg
   push     offset syntaxMsg
   jmp      quit
display_lookingMsg:
   ; affiche ce que l'on cherche :
   call     _wsprintfA, offset outBuffer, offset lookingMsg, \
            offset ip_string, offset port_string
   add      esp, 4*4
   call     Write2Console, offset outBuffer

   ; conversion IP/port => network byte order :
   call     inet_addr, offset ip_string
   cmp      eax, 0ffffffffh
   jne      convert_port
   push     offset endianErrMsg
   jmp      quit
convert_port:
   mov      searchRemAddr, eax
   mov      esi, offset port_string
   xor      ecx, ecx
   xor      eax, eax
   mov      bl, 9
   cld
convert_port_loop:
   lodsb
   sub      al, '0'
   js       convert_port_end_loop
   cmp      al, bl
   ja       convert_port_end_loop
   lea      ecx, [ecx+4*ecx]
   lea      ecx, [2*ecx+eax]
   jmp      short convert_port_loop
convert_port_end_loop:
   push     ecx
   call     htons
   cmp      eax, 0ffffffffh
   jne      convert_port2
   push     offset endianErrMsg
   jmp      quit
convert_port2:
   mov      searchRemPort, eax

   cmp      oldWinVer, 1
   jnz      GetExtendedTcpTable
   ; AllocateAndGetTcpExTableFromStack :
   call     dword ptr [APIaddress], offset APIptr, 0, \
            hProcess, 0, 2
   test     eax, eax                         ; ERROR_SUCCESS ?
   je       APIok
   push     offset aagErrMsg
   jmp      quit

GetExtendedTcpTable:
   ; GetExtendedTcpTable :
   call     dword ptr [APIaddress], [APIptr], offset APIsizeBuffer, \
            0, 2, 5, 0
   cmp      eax, 122                         ; ERROR_INSUFFICIENT_BUFFER
   jne      APIok
   push     offset memErrMsg
   jmp      quit

APIok:
   mov      esi, [APIptr]                    ; notre structure
   test     esi, esi
   jne      fetch_cx
   push     offset strErrMsg
   jmp      quit

fetch_cx:
   ; nombre de connexions actives :
   mov      ecx, [esi]
   test     ecx, ecx                         ; aucune ?
   jne      display_totcx
   push     offset NoCxMsg
   jmp      quit
display_totcx:
   push     ecx
   call     _wsprintfA, offset outBuffer, offset TotCxMsg, ecx
   add      esp, 4*3
   call     Write2Console, offset outBuffer
   pop      ecx

next_cx:
   push     ecx                              ; compteur
   push     esi                              ; pointeur

   ; recherche notre IP/port :
   mov      eax, dword ptr [esi+10h]         ; dwRemoteAddr
   cmp      eax, searchRemAddr
   jne      unwanted
   mov      TCPtable.dwRemoteAddr, eax
   mov      eax, dword ptr [esi+14h]         ; dwRemotePort
   cmp      eax, searchRemPort
   jne      unwanted
   mov      TCPtable.dwRemotePort, eax

   ; on a trouvé la connexion :
   mov      eax, dword ptr [esi+0Ch]         ; dwLocalPort
   mov      TCPtable.dwLocalPort, eax
   ; échange le contenu de ax :
   xchg     ah, al
   push     eax
   mov      eax, dword ptr [esi+08h]         ; dwLocalAddr
   mov      TCPtable.dwLocalAddr, eax
   ; conversion IP => ASCII :
   call     inet_ntoa, eax
   push     eax
   push     offset foundFormat
   push     offset outBuffer
   call     _wsprintfA
   add      esp, 4*4
   call     Write2Console, offset outBuffer

   pop      esi
   pop      ecx

   ; force la fermeture de la connexion :
   mov      TCPtable.dwState, 12             ; MIB_TCP_STATE_DELETE_TCB
   call     dword ptr [SetTcpEntryAPI], offset TCPtable
   test     eax, eax
   jnz      kill_error
   push     offset killOkMsg
   jmp      quit

kill_error:
   cmp      eax, 5                           ; ERROR_ACCESS_DENIED
   jne      unknown_err
   push     offset killErr1Msg
   jmp      quit
unknown_err:
   push     offset killErr2Msg
   jmp      quit

unwanted:
   pop      esi
   pop      ecx
   dec      ecx
   jcxz     noMoreCX
   add      esi, 18h                         ; structure suivante
   jmp      next_cx
noMoreCX:
   push     offset notFoundMsg

quit:
   call     Write2Console

   cmp      oldWinVer, 1
   jnz      noHeapFree
   ; libère la mémoire allouée si on a utilisé
   ; AllocateAndGetTcpExTableFromStack :
   call     HeapFree, hProcess, 0, [APIptr]
   jmp      noGlobalFree

noHeapFree:
   cmp      APImemAlloc, 0
   jz       noGlobalFree
   call     GlobalUnlock, [APImemAlloc]
   call     GlobalFree, [APImemAlloc]

noGlobalFree:
   push     offset Exiting
   call     Write2Console
   call     ExitProcess, 0

endp

; ====================================================================
; affiche le texte dans la console
; param :  [esp+4] : message à afficher

Write2Console proc

   call     lstrlenA, dword ptr [esp+4]
   call     WriteFile, stdout, dword ptr [esp+4*4], eax, bytesWritten, 0
   ; réajuste la pile
   retn     4

Write2Console endp

; ====================================================================
; récupère l'IP et le port dans les param.
; ret : succès (eax == 0) or erreur (eax == 1)

ParseCmdLine      proc

   ; vérifie s'il y a des quotes (") :
   cmp      byte ptr [eax], 22h
   jne      check_next
find_last_quote:
   inc      eax
   cmp      byte ptr [eax], 22h
   jne      find_last_quote

check_next:
   inc      eax
   ; recherche d'un caractère NULL/espace
   cmp      byte ptr [eax], 20h
   je       space_found
   cmp      byte ptr [eax], 00h
   je       cmdLineError
   jmp      check_next
space_found:
   ; certaines versions de Windows mettent 2 espaces
   ; entre le nom du programme et ses paramètres :
   cmp      byte ptr [eax+1], 20h
   je       check_next
   inc      eax
   mov      esi, eax
   push     eax
   call     lstrlenA
   ; la taille totale doit être comprise entre 9 to 21 :
   cmp      eax, 9
   jb       cmdLineError
   cmp      eax, 21
   ja       cmdLineError
   mov      edi, offset ip_string
next_ip_char:
   test     eax, eax
   jz       cmdLineError
   cmp      byte ptr [esi], 3ah              ; ":" ?
   je       fetch_port
   cmp      byte ptr[esi], 39h
   ja       cmdLineError
   cmp      byte ptr[esi], 30h
   jb       is_dot
   jmp      copy_ip
is_dot:
   cmp      byte ptr [esi], 2eh              ; "."?
   jne      cmdLineError
copy_ip:
   movsb                                     ; sauvegarde l'IP
   dec      eax
   jmp      next_ip_char
fetch_port:
   inc      esi
   mov      edi, offset port_string
next_port_char:
   dec      eax
   test     eax, eax
   je       test_port
   cmp      byte ptr [esi], 39h
   ja       cmdLineError
   cmp      byte ptr[esi], 30h
   jb       cmdLineError
   movsb                                     ; sauvegarde le port
   jmp      next_port_char

test_port:
   cmp      byte ptr [port_string], 0
   jne      endcmdLine

cmdLineError:
   mov      eax, 1
   ret
endcmdLine:
   xor      eax, eax
   ret

ParseCmdLine      endp

end start
; ====================================================================
; EOF



IV - Téléchargement :

    wkillcx.tgz - v1.0.1