Help - Search - Members - Calendar
Full Version: Exploits, shellcodes och overflows
SweRAT > Datasäkerhet > Sårbarheter och intrång
electrodez
Tjena!

Bli inte sura nu, men jag kommer antagligen med en väldigt dum fråga.. Enligt er iallafall i guess tongue.gif

Jag har läst ett flertal Buffer overflow tutorials. Men jag förstår inte vissa saker.

Jag förstår att man fyller stacken med fler bytes än vad den igentligen ska ta, så att man skriver över strängarna efter funktionen..

Men det jag inte förstår är det andra, hur man fyller stacken med sin shellcode. Och hur genererar man shellcoden föresten? är det själva payloaden först i asm
som man gör om till shellcode eller?

Som sagt, så har jag kollat på tutorials med samples.. Dom bygger först ett program som är sårbart. Sedan så bygger de exploiten eller va de gör. Men jag förstår inte hur man ska kunna köra dessa exploits? dom är ju utanför programet, men vart pekar dom på programet dom ska utsätta?

Det är skit svårt att förklara vad jag igentligen vill veta ^^ förstår lite grann på vissa ställen.

Hoppas ni står ut. Tack på förhand.

//Calle
blind
Här finns det potential för att bli något högre nivå vad det vanligtvis är i Nybörjarhörnan, flyttar till Sårbarheter och intrång.
/mod

Välkommen till Swerat. smile.gif
LJB
QUOTE(electrodez @ 2008-02-12 22:34) *
Tjena!

Bli inte sura nu, men jag kommer antagligen med en väldigt dum fråga.. Enligt er iallafall i guess tongue.gif

Jag har läst ett flertal Buffer overflow tutorials. Men jag förstår inte vissa saker.

Jag förstår att man fyller stacken med fler bytes än vad den igentligen ska ta, så att man skriver över strängarna efter funktionen..

Men det jag inte förstår är det andra, hur man fyller stacken med sin shellcode. Och hur genererar man shellcoden föresten? är det själva payloaden först i asm
som man gör om till shellcode eller?

Som sagt, så har jag kollat på tutorials med samples.. Dom bygger först ett program som är sårbart. Sedan så bygger de exploiten eller va de gör. Men jag förstår inte hur man ska kunna köra dessa exploits? dom är ju utanför programet, men vart pekar dom på programet dom ska utsätta?

Det är skit svårt att förklara vad jag igentligen vill veta ^^ förstår lite grann på vissa ställen.

Hoppas ni står ut. Tack på förhand.

//Calle


Det är efter det att du har skrivit över stacken med dina bytes som du först ska placera en NOP-sled, sedan din shellcode och sedan returadressen.


Exploit(din overflow) = (Dina bytes som ska skriva över stacken)
NOP-sled = (så många bytes som ska fylla ut outnyttjad plats)
Shellcode = (valfri shellcode...exempelvis ett cmd skal)
Returadress = (Adressen till någon esp adress i kernel32.dll...Har jag för mig)

Tror att en StackOverflow ungefär ska se ut så. Alltså, du lägger till skalkoden iprincip på samma sätt som du lägger till din overflow.

Här kan du läsa om shellcode: htttp://milw0rm.com/papers/51
Sen så finns det shellcode generatorer, det är bara att googla på det.





Rude
QUOTE(electrodez @ 2008-02-12 22:34) *
Jag förstår att man fyller stacken med fler bytes än vad den igentligen ska ta, så att man skriver över strängarna efter funktionen..


Det man skriver över är de andra registren. Exempel på register är EAX,EDX,ESP,EIP osv. Det du vill komma åt och ändra är som du redan vet EIP(Extended Instruction Pointer).

QUOTE(electrodez @ 2008-02-12 22:34) *
Men det jag inte förstår är det andra, hur man fyller stacken med sin shellcode.


Det finns, som jag har förstått det, flera sätt att göra detta. Anta att vi har en buffer på 512 byte som vi kan exploita.
Hur mycket som då krävs för att overflowa så att man kommer åt EIP kan variera, men säg att detta är 525 bytes. Efter 525 bytes av skräpkod skrivs EIP över.
Strängen vi skickar för att overflowa kan då se ut såhär:
[Skräpkod][nopsled][shellcode](Här har 525 bytes använts, och EIP skrivs över av returnaddress)[returnaddress]
Som jag förstår det så kan man då antingen peka till en jmp i en dll, t.ex jmp ESP i ntdll.dll eller liknande eller peka tillbaka till nopsled'en.
Landar du på nopsleden kommer den utföra no-operations tills den träffar shellcode. Den kommer sen att exekvera shellcoden och exploiten är successful.


QUOTE(electrodez @ 2008-02-12 22:34) *
Som sagt, så har jag kollat på tutorials med samples.. Dom bygger först ett program som är sårbart. Sedan så bygger de exploiten eller va de gör. Men jag förstår inte hur man ska kunna köra dessa exploits? dom är ju utanför programet, men vart pekar dom på programet dom ska utsätta?


Ofta kan man använda t.ex WinExec() vilket är bland dom enklare. Tror att det ser ut ungefär såhär då:
CODE
exploit.c
...
winexec("vulnerable.exe" overflowstring,0)


notera att detta inte alltid funkar på alla program, utan bara på dom som låter argv[1] gå till en strcpy() eller liknande.


Folk som känner sig säkrare på det här får gärna korrigera, jag skriver detta i syfte att lära mig själv också.
Mja
Det som brukar vara intressant är remote overflow, detta handlar i de flesta fall om applikationer som tar emot data via något nätverksgränssnitt.
Swestres har, om jag minns rätt, skrivit en liten "sploitme"-echo-server där den följer standarden, dvs upp till 1024 bytes som kommer in i bufferten. Problemet är när det kommer mer i en klump, och programmet inte kontrollerar hur mycket data som blir inläst.
Fördelen med echoservern är att det i alla fall i mina ögon är väldigt uppenbart vad man ska göra, det svåra är att göra det tongue.gif

Men Rude fick principen för själva attacken väldigt bra. Hitta en användarinmatning, se vad som händer när du skickar in mycket data. Skicka in mer och mer, när/om det sedan krashar har du lyckats få en overflow.
Sedan kommer den svåra biten, att få med instruktioner som får den att göra ngt, det är där NOP-släden kommer in.
Om du vet att du fyllde på med X antal bytes för att få den att krasha, måste du hitta en shellcode mindre än det, sedan lägga på NOP i starten på den, och själva hoppet på slutet av den.

Här är jag sedan ganska osäker på hur du beter dig för att hitta rätt med instruktionen.
Känns som detta är ngt man kanske skulle lägga lite krut på att förstå sig på bättre, även om overflows är en allt mer utdöende attack som såden (högnivå-språk har ju indatakontroller inbyggda till stor del) så är det ju fortfarande mycket av de riktigt VIKTIGA systemen som utvecklas med språk som är sårbara för den här typen av attack.

Har t.ex. funderat (OBS - Ingen uppmaning!) hur SL har konfigurerat sin server. Du skickar där via post-data in långa datasträngar i en .exe-fil på deras server, troligen via CGI eller ngt sånt. CGI var ju revolutionerande för alla hackers när det kom wink.gif

(Sidenote: Common Gateway Interface, ett gränssnitt för att köra applikationer kopplade mot webbservern. Tack vare alla hemma-servrar som kör linux och inte patchas med någon egentlig managment så ledde dåliga CGI-programvaror i stort sett på egen hand till att Linux-servrar gick om MS-servrar som mest hackade webbservers ett år. Statistikkälla tyvärr bortglömd från universitetetstiden, så tag med en nypa salt :-/)
swestres
QUOTE(Rude @ 2008-02-13 09:52) *
Det man skriver över är de andra registren. Exempel på register är EAX,EDX,ESP,EIP osv. Det du vill komma åt och ändra är som du redan vet EIP(Extended Instruction Pointer).

Nej, det är inte så det går till. Du kan aldrig skriva över själva registren. Du vill skriva över den minnesregion av stacken som håller det sparade värdet av eip. När ett C-program (t.ex.) anropar en funktion görs detta på IA-32 med instruktionen call som lägger adressen till nästa instruktion i följden på stacken och hoppar till den adress som är given som operand. När funktionen sen är färdig körs instruktionen ret som tar ett dword (i 32-bitars protected mode) som ligger överst på stacken, behandlar det som en adress och sätter eip till det. Skriver man då över denna minnesregion på stacken med sin egen adress kan man manupulera programflödet. Det man oftast vill då är att få eip att sättas till en adress någonstans i sin nop-sled, så att den sedan kan börja köra payloaden. Har du en buffer på 512 byte och de sparade värdena av ebp och eip som följer kan du använda 512+4 byte till en nop-sled och shell code. Därpå följer det värde du vill ha på instruktionspekaren.

Stack overflows kan förhindras ganska lätt om man verkligen vill, ASLR är ett exempel som gör det nästan omöjligt att veta var ens buffer finns i processens minnesrymd. Att göra stacken till en ren data-sektion är en annan, på så sätt kan man inte sätta eip till stacken. Man kan dock fortfarande skriva över det sparade värdet av eip.

EDIT: att logiskt separera kod och data (med hårdvarumodeller som Harvardmodellen) är också möjligt. Där kommer säkerheten som en bieffekt. Att ha separata stackar för returvärden och dataparametrar (som Forth) är ett annat, Forth går till och med ett steg längre och tillåter inte buffrar att läggas på stacken (det är inte en "ren" lösning egentligen, det bryter lite mot abstraktionen att ha en stack öht.) utan där läggs de istället i "data space", vilket mer eller mindre motsvarar arbetsminnet. Forth VM har faktiskt implementeras i hårdvara ett antal gånger, senaste är väl SEAForth, fast jag vet inte riktigt hur deras lösning är. I mina ögon påminner det mer om en FPGA än en CPU som sådan. Fast processordesign är inte min starka sida.

EDIT2:
ang.
QUOTE
Och hur genererar man shellcoden föresten? är det själva payloaden först i asm
som man gör om till shellcode eller?

Ja, det är nog det vanligaste sättet. Man skriver den kod man vill köra i assembler, kompilerar den till maskinkod och sedan använder man antingen maskinkoden direkt eller packar om den till ett C-fält eller liknande.

ex:
CODE
BITS 32
global _start
section .text
_start:
push    dword 0x72617265
push    dword 0x67657220
push    dword 0x73657274
push    dword 0x73657773
xor     eax, eax
mov     al, 4
xor     ebx, ebx
inc     ebx
mov     ecx, esp
xor     edx, edx
mov     dl, 16
int     0x80

xor     eax,eax
inc     eax
xor     ebx, ebx
int     0x80

Detta är en giltig shellcode utan nullbytes (man vill inte ha nullbytes om man jobbar mot att utnyttja stränghanteringsfunktioner som strcpy och liknande).
Vi kompilerar den till rå maskinkod med nasm:
QUOTE
nasm -fbin -o sc shellcode.asm

Sen kan man packa om det till en C-array för att underlätta skapandet av en exploit. Detta kan man antingen göra med en hex-editor, eller så skriver man ett program som gör det. Något i stil med:
CODE
#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fp;
    int ch;

    if (argc != 2) {
        fprintf(stderr, "bin2arr - convert a flat binary file to a C array\n"
               "by swestres\nusage: %s <file>", argv[0]);
        return 1;
    }

    fp = fopen(argv[1], "rb");
    if (!fp) {
        fprintf(stderr, "error: couldn't open %s for reading\n", argv[1]);
        return 1;
    }

    printf("char shellcode[] = \"");
    while ((ch = fgetc(fp)) != EOF) {
        printf("\\x%02X", ch);
    }

    printf("\";\n");
    fclose(fp);
    return 0;
}

QUOTE
$ gcc -o bin2arr bin2arr.c
$ ./bin2arr sc
char shellcode[] = "\x68\x65\x72\x61\x72\x68\x20\x72\x65\x67\x68\x74\x72\x65\x73\x68\x73\x77\x65\x73\x31\xC0\xB0\x04\x31\xDB\x43\x89\xE1\x31\xD2\xB2\x10\xCD\x80\x31\xC0\x40\x31\xDB\xCD\x80";

electrodez
Jösses men tack! va mycket det vart på engång =)

Men, när är det själva payloaden körs?

Om det ser ut så här [Skräpkod][nopsled][shellcode] [return]

Är då skräpkoden nopsleden samt shellcoden hela buffern totalt? eller är skräpkoden hela bufferten och det andra kommer efter?

För mig låter det som att skräp koden "overflowar" bufferten sedan så rullar den bara igenom 90iorna till shellcoden. Men det är tydligen inte så simpelt? För shellcoden bör väl utlösas direkt efter nopsleden då? vart return addressen kommer in förstår jag inte riktigt ^^

Eller är det så att programet fortsätter som vanligt efter overflowen, men sedan hoppar den in i stacken till shellcoden igen. Eftersom man angivit den addressen som ett hopp efter funktionen? Så när overflowen körs så "ignorerar" den bufferten, går vidare till en ret address som går tillbaka till en viss punkt i stacken?

Förlåt, jag får det inte att låta logiskt för mig riktigt ^^ det känns som det är nån liten informations del som fattas för att jag skall förstå tongue.gif. Kommer antagligen sedan säga.. Fan va dum jag va som inte förstod.

Justja! tack för välkomnandet =) Verkar vara ett riktigt trevligt forum.
Rude
Tack swestres, mycket intressant läsning.



QUOTE(electrodez @ 2008-02-13 15:27) *
Är då skräpkoden nopsleden samt shellcoden hela buffern totalt? eller är skräpkoden hela bufferten och det andra kommer efter?

För mig låter det som att skräp koden "overflowar" bufferten sedan så rullar den bara igenom 90iorna till shellcoden. Men det är tydligen inte så simpelt? För shellcoden bör väl utlösas direkt efter nopsleden då? vart return addressen kommer in förstår jag inte riktigt ^^


skräpkod+nopsled+shellcode ligger i buffern. Det är därför den bara kopieras(och inte exekveras), däremot när man sedan med returnaddress pekar till nopsled'en kommer du ju, som swestres sa, att ändra programflödet till att köra nopsled'en+shellcode.
electrodez
QUOTE(Rude @ 2008-02-13 16:22) *
Tack swestres, mycket intressant läsning.
skräpkod+nopsled+shellcode ligger i buffern. Det är därför den bara kopieras(och inte exekveras), däremot när man sedan med returnaddress pekar till nopsled'en kommer du ju, som swestres sa, att ändra programflödet till att köra nopsled'en+shellcode.


haha, jösses.. Säger som jag trodde jag skulle säga, va dum jag va som inte förstod tongue.gif.. Programets funktion i detta exempel var ju att kopiera in något i buffern bara ^^ Tack så mycket rude..

Tack för alla grymma svar =) och att ni tog er tid att skriva så pass långa inlägg som ni nu gjort. Uppskattas verkligen!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2012 Invision Power Services, Inc.