När jag såg fram emot att fortsätta diskutera detta ämne, låt mig berätta lite historia, teori och övning om sårbarheter. Vi har alla hört nu att säkerhetsfel kan kosta mycket, vi vet alla att vi behöver hålla vår programvara uppdaterad, vi vet alla att många uppdateringar orsakas av säkerhetsfel. Men idag berättar jag lite om hur dessa fel hittas och utnyttjas 🙂 Men innan detta ska vi förtydliga några detaljer för att få en bättre överblick.
Innan du börjar
Först vill jag säga att vi kommer att fokusera på den första sårbarheten som jag lärde mig att utnyttja, den kända Buffertöverflöden, i denna sårbarhet utnyttjar vi brist på minnesverifiering för att göra roliga saker 🙂 Men låt oss klargöra lite mer om det.
Detta kommer inte att bli ett verkligt världsscenario
Jag har inte råd att lära dem att bryta något program de ser 🙂 först eftersom det är farligt för deras datorer, för det andra eftersom det tar mer än min vanliga ordkvot.
Vi åker på en resa till 80-talet
Vad jag ska visa dig kan jag göra på min bärbara dator, men det betyder inte att det kan göras idag på ett enkelt sätt 🙂 många av dessa begrepp har redan utnyttjats så många gånger att nya skyddsmetoder och nya metoder att undvika dem har dykt upp 😛 men det ger oss tillbaka till samma plats, det finns inget utrymme att berätta allt that
Det kanske inte fungerar på din processor
Även om jag ska använda ett mycket enkelt exempel vill jag att det ska vara helt klart från början att detaljerna i detta är så många och så varierade att precis som det kan komma ut på samma sätt som jag, om du vill prova det kan den önskade effekten inte heller uppnås 🙂 Men ni kan föreställa er att jag inte kan förklara det i detta utrymme, speciellt för att jag med denna introduktion redan har tagit mer än 300 ord, så vi kommer direkt till vår punkt.
Vad är en Buffer-överflöde
För att svara på detta måste vi först förstå den första halvan av denna kombination.
buffertar
Eftersom allt handlar om minne i en dator är det logiskt att det måste finnas någon typ av informationsbehållare. När vi pratar om ingångar o utgångar, kommer vi direkt till begreppet buffertar. För att hålla det kort, a buffert Det är ett minnesutrymme av definierad storlek där vi ska lagra en mängd information, enkelt 🙂
Överflöden uppstår, som namnet antyder, när en buffert fylls med mer information än den kan hantera. Men varför är detta viktigt?
Stack
Även kända som stackar, de är en abstrakt datatyp som vi kan stack information är deras huvudsakliga kännetecken att de har en beställning LIFO (Sist in, först ut). Låt oss tänka en sekund på en stapel tallrikar, vi lägger dem ovanpå en efter en, och sedan tar vi ut dem en efter en uppifrån, detta gör den sista plattan som vi har lagt (den som är högst upp ) är den första plattan som vi ska ta ut, uppenbarligen om vi bara kan ta ut en tallrik i taget och vi bestämmer oss för att göra det i den ordningen: P.
Nu när du känner till dessa två begrepp måste vi ordna dem. Stackar är viktiga eftersom varje program vi kör har sina egna körningsstack. Men den här stacken har en särskild egenskap, växer ner. Det enda du behöver veta om detta är att medan ett program körs, när en funktion anropas, går stacken från ett nummer X i minnet till ett nummer (Xn). Men för att fortsätta måste vi förstå ytterligare ett koncept.
Pekare
Detta är ett koncept som gör många programmerare galna när de börjar i C-världen, faktiskt beror den stora kraften i C-programmering delvis på att använda pekare. För att hålla det enkelt, en pekare pekar på en minnesadress. Det här låter komplext, men det är inte så komplicerat, vi har alla RAM i våra maskiner, eller hur? Detta kan definieras som en på varandra följande arrangemang av block, uttrycks dessa platser normalt i hexadecimala tal (från 0 till 9 och sedan från A till F, såsom 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Här som en nyfiken anteckning, 0x10 NEJ är lika med 10 😛 om vi konverterar det till decimalordning skulle det vara detsamma som att säga 15. Detta är något som också förvirrar mer än en i början, men låt oss komma till det.
Uppgifter
Processorer arbetar med ett antal register, som arbetar för att överföra platser från fysiskt minne till processorn, för arkitekturer som använder 64-bitar är antalet register stort och svårt att beskriva här, men för att få idén är registren som pekare, de indikerar bland annat , ett minnesutrymme (plats).
Öva nu
Jag vet att det har varit mycket information att bearbeta fram till nu, men i själva verket är det något komplexa frågor som jag försöker förklara på ett mycket enkelt sätt, vi kommer att se ett litet program som använder buffertar och vi ska bryta det för att förstå detta om överflöd, det är uppenbarligen inte det här Det är ett riktigt program, och vi kommer att "undvika" många av de motåtgärder som används idag, bara för att visa hur saker gjordes tidigare 🙂 och för att några av dessa principer är nödvändiga för att kunna lära sig mer komplexa saker 😉
GDB
Ett fantastiskt program som utan tvekan är ett av de mest använda av programmerare C. Bland dess många dygder har vi det faktum att det tillåter oss att se allt detta som vi hittills har pratat om, register, stacken, buffertar etc., Låt oss se det program som vi ska använda för vårt exempel.
återinmatning.c
Detta är ett ganska enkelt program, vi ska använda biblioteket stdio.h
för att kunna få information och visa den i en terminal. Vi kan se en funktion som kallas return_input
som genererar en buffert kallade array, som har en längd på 30 byte (char-datatypen är 1 byte lång).
Funktionen gets(array);
begär information via konsol och funktion printf()
returnerar innehållet i matrisen och visar det på skärmen.
Varje program som skrivs i C börjar med funktionen main()
, detta kommer bara att ha ansvaret för att ringa return_input, nu ska vi sammanställa programmet.
Låt oss ta lite av det jag just gjorde. Alternativet -ggdb
berättar för gcc att kompilera programmet med information för att gdb ska kunna felsöka korrekt. -fno-stack-protector
Det är ett alternativ som vi naturligtvis inte borde använda, men som vi ska använda för annars skulle det vara möjligt att generera buffertöverflödet i stacken. Till slut har jag testat resultatet. ./a.out
den kör bara vad jag just sammanställt, den ber om information och returnerar den. Löpande 🙂
Varningar
En annan anteckning här. Kan du se varningarna? klart det är något att ta hänsyn till när vi arbetar med kod eller kompilering, detta är lite uppenbart och det finns få program som idag har funktionen gets()
I koden. En fördel med Gentoo är att genom att sammanställa varje program kan jag se vad som kan vara fel, ett "idealt" program borde inte ha dem, men du skulle bli förvånad över hur många stora program som har dessa varningar eftersom de bara är MYCKET stora och det är svårt att hålla reda på dem farliga funktioner när det finns många varningar samtidigt. Nu om vi fortsätter
Felsökning av programmet
Nu kan den här delen vara lite förvirrande, men eftersom jag redan har skrivit en hel del har jag inte råd att förklara allt, så ledsen om du ser att jag går för fort 🙂
Avaktiverar koden
Låt oss börja med att titta på vårt kompilerade maskinspråkprogram.
Detta är koden för vår huvudfunktion i Montage, det här är vad vår processor förstår, raden till vänster är den fysiska adressen i minnet <+ n> är känd som offset, i princip avståndet från början av funktionen (huvud) till det uttalandet (känt som opkod). Sedan ser vi typen av instruktion (push / mov / callq ...) och ett eller flera register. Sammanfattningsvis kan vi säga att det är indikationen följt av källa / ursprung och destination. <return_input>
hänvisar till vår andra funktion, låt oss ta en titt.
return_input
Det här är lite mer komplicerat, men jag vill bara att du ska kontrollera ett par saker, det finns en tagg som heter <gets@plt>
och en sista opcode som heter retq
som anger slutet på funktionen. Vi ska sätta ett par brytpunkter, en i funktionen gets
och en annan i retq
.
Körning
Nu ska vi köra programmet för att se hur åtgärden börjar.
Vi kan se att en liten pil visas som indikerar opkoden där vi är, jag vill att de ska ta hänsyn till riktningen 0x000055555555469b
, detta är adressen efter samtalet till return_input
i funktion main
, detta är viktigt eftersom det är här programmet ska återvända när du är klar att ta emot ingång, låt oss gå in i funktionen. Nu ska vi kontrollera minnet innan vi går in i funktionen gets
.
Jag har lagt tillbaka huvudfunktionen för dig och jag har markerat koden jag hänvisade till, som du kan se, på grund av livskraft har delats in i två segment, vill jag att de ska ta hänsyn till riktningen 0x7fffffffdbf0
(den första från vänster efter kommandot x/20x $rsp
) eftersom det här är platsen vi måste använda för att kontrollera resultaten av get, låt oss fortsätta:
Bryter programmet
Jag har markerat dem 0x44444444
eftersom de representerar våra Ds 🙂 nu har vi börjat lägga till ingång till programmet, och som du ser är vi bara två rader från vår önskade adress, vi kommer att fylla den tills vi är precis före adresserna som vi markerade i föregående steg.
Ändra returvägen
Nu när vi har lyckats ange det här avsnittet i koden där det indikerar funktionens återkomst, låt oss se vad som händer om vi ändrar adressen 🙂 istället för att gå till platsen för opkoden som följer den vi hade för ett ögonblick sedan, vad tycker du om vi går tillbaka till return_input
? Men för detta är det nödvändigt att skriva adressen vi vill ha i binär, vi ska göra det med funktionen printf
från bash 🙂
Nu har vi fått informationen två gånger 😀 programmet var säkert inte gjort för det, men vi har lyckats bryta koden och få den att upprepa något som den inte skulle göra.
Reflektioner
Denna enkla förändring kan betraktas som en exploatera väldigt grundläggande 🙂 han har lyckats bryta programmet och göra något vi vill att han ska göra.
Detta är bara första steget i en nästan oändlig lista över saker att se och lägga till, det finns sätt att lägga till fler saker än att bara upprepa en beställning, men den här gången har jag skrivit mycket och allt som rör skalkodning Det är ett ämne att skriva mer än artiklar, kompletta böcker skulle jag säga. Ledsen om jag inte har kunnat gräva lite mer i ämnen som jag skulle ha velat, men det kommer säkert att finnas en chans 🙂 Hälsningar och tack för att ni kom hit.
Var mer direkt. Skriv mindre och fokusera på det som betyder något
Hej, tack för kommentaren.
För att säga sanningen har jag skurit en bra del av idéerna, men ändå tycktes det att det lämnade minimum så att någon som inte har programmeringskunskap kan få en idé.
hälsningar
Problemet är att de som inte har programmeringskunskap inte kommer att få reda på någonting eftersom det är för komplicerat till att börja med, men de som vet hur man programmerar uppskattar att vara mer direkta.
Jag antar att du inte kan nå alla, du måste välja, och i det här fallet har du syndat för att täcka mycket.
Förresten, jag säger dig som en konstruktiv kritik, jag älskar dessa ämnen och jag vill att du ska fortsätta skriva artiklar, grattis!
Jag tror detsamma.
Tack så mycket till båda !! Det är verkligen svårt att förstå hur man når målgruppen när sanningen är att antalet personer med en avancerad programmeringsnivå som läser dessa artiklar är litet (åtminstone kan man dra slutsatsen utifrån kommentarerna)
Jag har verkligen syndat från att vilja förenkla något som kräver en bred kunskapsbas för att förstås. Jag hoppas att du förstår att eftersom jag just började blogga, har jag ännu inte upptäckt den exakta punkten där mina läsare vet och förstår vad jag säger. Det skulle göra det mycket lättare att säga sanningen 🙂
Jag kommer att försöka bli kortare när det förtjänar utan att personifiera formatet, eftersom det är lite mer komplicerat att skilja sättet att skriva från innehållet än man kan föreställa sig, jag har åtminstone dem ganska länkade, men jag antar att jag i slutändan kommer att kunna för att lägga till rader istället för att skära innehåll.
hälsningar
Var kunde du ta reda på mer om ämnet? Någon rekommenderad bok?
Exemplet togs från The Shellcoder's Handbook av Chris Anley, John Heasman, Felix Linder och Gerardo Richarte, men för att göra 64-bitarsöversättningen var jag tvungen att lära mig om min arkitektur, Intel-utvecklarhandboken, volym 2 och 3 är en ganska pålitlig källa för det. Det är också bra att läsa GDB-dokumentationen, som kommer med kommandot 'info gdb'. För att lära sig montering och C finns det många mycket bra böcker, förutom att församlingsböckerna är lite gamla så det finns ett gap att fylla med en annan typdokumentation.
Själva skalkoden är inte längre lika effektiv dessa dagar av olika skäl, men det är fortfarande intressant att lära sig nya tekniker.
Hoppas det hjälper lite 🙂 Hälsningar
Bra artikel, gammal blogg desdelinux har blivit pånyttfödd igen =)
När du säger att fjärrskalet inte är så effektivt menar du motåtgärder som är utformade för att mildra attacker, de kallar det stötande säkerhet.
Hälsningar och fortsätt
Tack så mycket Franz 🙂 mycket vänliga ord, egentligen menade jag att Shellcoding idag är mycket mer komplex än vad vi ser här. Vi har ASLR (random memory location generator) stackskyddet, de olika måtten och motåtgärder som begränsar antalet opkoder som kan injiceras i ett program, och det är bara början.
hälsningar,
Hej, kommer du att göra en annan del som utvidgar ämnet? Det är intressant
Hej, ämnet är verkligen ganska intressant, men den komplexitet som vi skulle ta skulle bli väldigt hög, antagligen med ett stort antal inlägg för att förklara de olika förutsättningarna för att förstå den andra. Jag kommer antagligen skriva om det, men det kommer inte att vara följande inlägg, jag vill skriva några ämnen innan jag fortsätter med det här.
Hälsningar och tack för att ni delar
Mycket bra che! Du bidrar med bra inlägg! En fråga, jag börjar med den här IT-säkerhetssaken genom att läsa en bok som heter "Säkerställa säkerhet genom penningtestning". Rekommenderas den här boken? Hur föreslår du att jag börjar fråga om dessa frågor?
Hej kaktus, det är ett helt universum om sårbarheter och andra, för att säga sanningen beror det mycket på vad som fångar din uppmärksamhet, och de behov du har, en IT-chef behöver inte veta detsamma som en penna-testare, Eller en sårbarhetsforskare eller en kriminalteknisk analytiker, ett katastrofåterställningsteam har en helt annan uppsättning färdigheter. Uppenbarligen kräver var och en av dem en annan nivå av teknisk kunskap, jag rekommenderar att du börjar upptäcka exakt vad du gillar och börjar sluka böcker, artiklar och andra, och viktigast av allt, öva allt du läser, även om det är föråldrat, det kommer att göra skillnad i slutändan.
hälsningar,
Hej.
Tack så mycket för att du förklarade detta ämne, samt kommenterade att vi har "The Shellcoder's Handbook" för extra information. Jag har redan en väntande läsning 😉