pwn第一更-Icectf_drumpfhotel

最近在刷题的时候发现的一道相对简单的溢出题目,但是可能对堆溢出方面知识涉及的不多,导致花了不少时间去研究原理,感觉还有有不少收获的。

代开界面就是一个简单的宾馆预定系统

使用IDA分析函数,主要的函数包括mian(),book_suite(),book_room(),delete_booking(),print_booking()还有最主要的flag().

首先在main函数里会给个五个选择,预定suite、room,删除预定,打印预定,退出。

首先分析book_suite(),大致的情形就是在堆上申请了264个字节的空间,前四个字节储存print_name()函数,256个字节储存name,另外四个存储suite nummber。

Dump of assembler code for function book_suite:
   0x0804873b <+0>: push   %ebp
   0x0804873c <+1>: mov    %esp,%ebp
   0x0804873e <+3>: push   %ebx
   0x0804873f <+4>: sub    $0x34,%esp
   0x08048742 <+7>: mov    %gs:0x14,%eax
   0x08048748 <+13>: mov    %eax,-0xc(%ebp)
   0x0804874b <+16>: xor    %eax,%eax
   0x0804874d <+18>: movl   $0x108,(%esp)   -->Allocate 264 bytes in heap memory
   0x08048754 <+25>: call   0x80484e0 <malloc@plt> --> return ptr to memory in eax
   0x08048759 <+30>: mov    %eax,0x804b088  --> assign ptr to variable suite
   0x0804875e <+35>: movl   $0x8049688,(%esp)
   0x08048765 <+42>: call   0x8048490 <printf@plt> --> print "Name:"
   0x0804876a <+47>: mov    0x804b080,%eax
   0x0804876f <+52>: mov    %eax,(%esp)
   0x08048772 <+55>: call   0x80484a0 <fflush@plt>
   0x08048777 <+60>: mov    0x804b060,%eax
   0x0804877c <+65>: mov    0x804b088,%edx  --> variable suite
   0x08048782 <+71>: add    $0x4,%edx
   0x08048785 <+74>: mov    %eax,0x8(%esp)
   0x08048789 <+78>: movl   $0x100,0x4(%esp)--> length 0x100(256 bytes)
   0x08048791 <+86>: mov    %edx,(%esp)   
   0x08048794 <+89>: call   0x80484c0 <fgets@plt>--> read from stdin, store name at address suite+4, length 0x100(256 bytes)
   0x08048799 <+94>: mov    0x804b088,%eax  --> var suite into eax
   0x0804879e <+99>: movl   $0x8048a84,(%eax)--> store address of print_name function(0x8048a84) into memory location at suite
   0x080487a4 <+105>: movl   $0x804968f,(%esp)     -->"Suite number:"
   0x080487ab <+112>: call   0x8048490 <printf@plt>
   0x080487b0 <+117>: mov    0x804b080,%eax
   0x080487b5 <+122>: mov    %eax,(%esp)
   0x080487b8 <+125>: call   0x80484a0 <fflush@plt>
   0x080487bd <+130>: mov    0x804b060,%eax   -->stdin
   0x080487c2 <+135>: mov    %eax,0x8(%esp)   -->push stdin stream
   0x080487c6 <+139>: movl   $0x10,0x4(%esp)  -->read only 16bytes from stdin. *Cannot stack overflow*
   0x080487ce <+147>: lea    -0x1c(%ebp),%eax -->store in stack starting at $ebp-0x1c (28bytes away from base of stack)
   0x080487d1 <+150>: mov    %eax,(%esp)
   0x080487d4 <+153>: call   0x80484c0 <fgets@plt> --> get suite number from stdin and store in stack
   0x080487d9 <+158>: mov    0x804b088,%ebx   --> pointer suite
   0x080487df <+164>: lea    -0x1c(%ebp),%eax
   0x080487e2 <+167>: mov    %eax,(%esp)      
   0x080487e5 <+170>: call   0x8048530 <atoi@plt>
   0x080487ea <+175>: mov    %eax,0x104(%ebx)--> save integer result into  suite+0x104
   0x080487f0 <+181>: movl   $0x804969e,(%esp)  --> "Booked a suite!"
   0x080487f7 <+188>: call   0x80484f0 <puts@plt>
   0x080487fc <+193>: mov    0x804b080,%eax
   0x08048801 <+198>: mov    %eax,(%esp)
   0x08048804 <+201>: call   0x80484a0 <fflush@plt>
   0x08048809 <+206>: mov    -0xc(%ebp),%eax  -->Stack canary
   0x0804880c <+209>: xor    %gs:0x14,%eax
   0x08048813 <+216>: je     0x804881a <book_suite+223>
   0x08048815 <+218>: call   0x80484d0 <__stack_chk_fail@plt>
   0x0804881a <+223>: add    $0x34,%esp
   0x0804881d <+226>: pop    %ebx
   0x0804881e <+227>: pop    %ebp
   0x0804881f <+228>: ret    
End of assembler dump.

使用gdb查看堆地址分配,第一个地址就是print_name()函数的地址。

(gdb) x/100wx suite
0x804c008: 0x08048a84(func) 0x62626262 0x00000a62 0x00000000
0x804c018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c048: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c058: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c068: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c078: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c088: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c098: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0a8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0b8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0c8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0d8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0e8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0f8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c108: 0x00000000 0x0804863d(int) 0x00000000 0x00020ef1
0x804c118: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c128: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c138: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c148: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c158: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c168: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c178: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c188: 0x00000000 0x00000000 0x00000000 0x00000000

接下里是book_room函数,分配了大小为260的堆内存,256大小的向内存储存name,剩下4个字节储存room_nummber.

(gdb) disass book_room
Dump of assembler code for function book_room:
   0x08048820 <+0>: push   %ebp
   0x08048821 <+1>: mov    %esp,%ebp
   0x08048823 <+3>: push   %ebx
   0x08048824 <+4>: sub    $0x34,%esp
   0x08048827 <+7>: mov    %gs:0x14,%eax
   0x0804882d <+13>: mov    %eax,-0xc(%ebp)
   0x08048830 <+16>: xor    %eax,%eax
   0x08048832 <+18>: movl   $0x104,(%esp)   
   0x08048839 <+25>: call   0x80484e0 <malloc@plt>--> allocate 260 bytes in heap
   0x0804883e <+30>: mov    %eax,0x804b08c  --> save pointer to variable room 
   0x08048843 <+35>: movl   $0x8049688,(%esp) --> "Name: "
   0x0804884a <+42>: call   0x8048490 <printf@plt>
   0x0804884f <+47>: mov    0x804b080,%eax
   0x08048854 <+52>: mov    %eax,(%esp)
   0x08048857 <+55>: call   0x80484a0 <fflush@plt>
   0x0804885c <+60>: mov    0x804b060,%eax
   0x08048861 <+65>: mov    0x804b08c,%edx --> variable room
   0x08048867 <+71>: add    $0x4,%edx
   0x0804886a <+74>: mov    %eax,0x8(%esp)
   0x0804886e <+78>: movl   $0x100,0x4(%esp)
   0x08048876 <+86>: mov    %edx,(%esp)
   0x08048879 <+89>: call   0x80484c0 <fgets@plt> --> read from stdin, store name at address room+4, length 0x100(256 bytes)
   0x0804887e <+94>: movl   $0x80496ae,(%esp)  --> "Room Number: "
   0x08048885 <+101>: call   0x8048490 <printf@plt>
   0x0804888a <+106>: mov    0x804b080,%eax
   0x0804888f <+111>: mov    %eax,(%esp)
   0x08048892 <+114>: call   0x80484a0 <fflush@plt>
   0x08048897 <+119>: mov    0x804b060,%eax
   0x0804889c <+124>: mov    %eax,0x8(%esp)
   0x080488a0 <+128>: movl   $0x10,0x4(%esp)  --> read 16 bytes
   0x080488a8 <+136>: lea    -0x1c(%ebp),%eax 
   0x080488ab <+139>: mov    %eax,(%esp)
   0x080488ae <+142>: call   0x80484c0 <fgets@plt>
   0x080488b3 <+147>: mov    0x804b08c,%ebx
   0x080488b9 <+153>: lea    -0x1c(%ebp),%eax
   0x080488bc <+156>: mov    %eax,(%esp)
   0x080488bf <+159>: call   0x8048530 <atoi@plt>
   0x080488c4 <+164>: mov    %eax,(%ebx)  --> save room number into address room
   0x080488c6 <+166>: movl   $0x80496bc,(%esp)
   0x080488cd <+173>: call   0x80484f0 <puts@plt> "Booked a room!"
   0x080488d2 <+178>: mov    0x804b080,%eax
   0x080488d7 <+183>: mov    %eax,(%esp)
   0x080488da <+186>: call   0x80484a0 <fflush@plt>
   0x080488df <+191>: mov    -0xc(%ebp),%eax
   0x080488e2 <+194>: xor    %gs:0x14,%eax
   0x080488e9 <+201>: je     0x80488f0 <book_room+208>
   0x080488eb <+203>: call   0x80484d0 <__stack_chk_fail@plt>
   0x080488f0 <+208>: add    $0x34,%esp
   0x080488f3 <+211>: pop    %ebx
   0x080488f4 <+212>: pop    %ebp
   0x080488f5 <+213>: ret    
End of assembler dump.
(gdb) 

查看堆结构,发现前四个字节储存的就是room_nummber

(gdb) x/100wx room
0x804c008: 0x00000001(int) 0x61616161 0x00000a61 0x00000000
0x804c018: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c028: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c038: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c048: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c058: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c068: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c078: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c088: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c098: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0a8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0b8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0c8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0d8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0e8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0f8: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c108: 0x00000000 0x00020ef9 0x00000000 0x00000000
0x804c118: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c128: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c138: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c148: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c158: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c168: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c178: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c188: 0x00000000 0x00000000 0x00000000 0x00000000

主要的问题在print_booking中,这个函数里调用了print_name函数

(gdb) disass print_booking
Dump of assembler code for function print_booking:
   0x080489a5 <+0>: push   %ebp
   0x080489a6 <+1>: mov    %esp,%ebp
   0x080489a8 <+3>: sub    $0x28,%esp
   0x080489ab <+6>: mov    %gs:0x14,%eax
   0x080489b1 <+12>: mov    %eax,-0xc(%ebp)
   0x080489b4 <+15>: xor    %eax,%eax
   0x080489b6 <+17>: mov    0x804b088,%eax  --> pointer suite
   0x080489bb <+22>: test   %eax,%eax
   0x080489bd <+24>: jne    0x80489e6 <print_booking+65>
   0x080489bf <+26>: mov    0x804b08c,%eax
   0x080489c4 <+31>: test   %eax,%eax
   0x080489c6 <+33>: jne    0x80489e6 <print_booking+65>
   0x080489c8 <+35>: movl   $0x80496cb,(%esp)
   0x080489cf <+42>: call   0x8048490 <printf@plt>
   0x080489d4 <+47>: mov    0x804b080,%eax
   0x080489d9 <+52>: mov    %eax,(%esp)
   0x080489dc <+55>: call   0x80484a0 <fflush@plt>
   0x080489e1 <+60>: jmp    0x8048a71 <print_booking+204>
   0x080489e6 <+65>: mov    0x804b088,%eax --> pointer suite
   0x080489eb <+70>: test   %eax,%eax
   0x080489ed <+72>: je     0x8048a2c <print_booking+135>
   0x080489ef <+74>: mov    0x804b088,%eax
   0x080489f4 <+79>: mov    (%eax),%eax -->address of print_name function in suite
   0x080489f6 <+81>: mov    0x804b088,%edx
   0x080489fc <+87>: add    $0x4,%edx
   0x080489ff <+90>: mov    %edx,(%esp) --> location of string for suite name
   0x08048a02 <+93>: call   *%eax --> call print_name function giving it location of suite name **Need to overwrite value of print_name function in suite with address of function flag()
   0x08048a04 <+95>: mov    0x804b088,%eax
   0x08048a09 <+100>: mov    0x104(%eax),%eax
   0x08048a0f <+106>: mov    %eax,0x4(%esp)
   0x08048a13 <+110>: movl   $0x804970a,(%esp)
   0x08048a1a <+117>: call   0x8048490 <printf@plt>
   0x08048a1f <+122>: mov    0x804b080,%eax
   0x08048a24 <+127>: mov    %eax,(%esp)
   0x08048a27 <+130>: call   0x80484a0 <fflush@plt>
   0x08048a2c <+135>: mov    0x804b08c,%eax
   0x08048a31 <+140>: test   %eax,%eax
   0x08048a33 <+142>: je     0x8048a71 <print_booking+204>
   0x08048a35 <+144>: mov    0x804b08c,%eax
   0x08048a3a <+149>: add    $0x4,%eax
   0x08048a3d <+152>: mov    %eax,0x4(%esp)
   0x08048a41 <+156>: movl   $0x804971c,(%esp)
   0x08048a48 <+163>: call   0x8048490 <printf@plt>
   0x08048a4d <+168>: mov    0x804b08c,%eax
   0x08048a52 <+173>: mov    (%eax),%eax
   0x08048a54 <+175>: mov    %eax,0x4(%esp)
   0x08048a58 <+179>: movl   $0x804970a,(%esp)
   0x08048a5f <+186>: call   0x8048490 <printf@plt>
   0x08048a64 <+191>: mov    0x804b080,%eax
   0x08048a69 <+196>: mov    %eax,(%esp)
   0x08048a6c <+199>: call   0x80484a0 <fflush@plt>
   0x08048a71 <+204>: mov    -0xc(%ebp),%eax
   0x08048a74 <+207>: xor    %gs:0x14,%eax
   0x08048a7b <+214>: je     0x8048a82 <print_booking+221>
   0x08048a7d <+216>: call   0x80484d0 <__stack_chk_fail@plt>
   0x08048a82 <+221>: leave  
   0x08048a83 <+222>: ret    
End of assembler dump.
(gdb)  

之后的delete_booking()函数主要是free()堆块,利用过程就是首先为suite申请堆块,然后free掉,之后为room申请堆块,nummber处输入flag()地址的十进制,这样suite和room的前四个字节都指向同一个地址,造成room前四个字节地址指针混乱,而suite()的print_name()函数地址被转换为flag()地址。

有钱的捧个钱场
0%