标签:
2016-09-11 13:06:28 来源:安全客-FlappyPig 作者:安全客
阅读:12099次
点赞(3)
收藏(82)
作者:FlappyPig
稿费:700RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
2016 华山杯 网络安全技能大赛 解题报告
队伍: FlappyPig
添加type=”submin”,点击提交抓包
有一串字符串,base64->md5,1931b。提交getflag
源码有代码,先找0e开头的md5,然后user.php,直接反序列化绕过
看了下js,直接alert(a) 14208
<img src=1 onerror=alert(1)>
Jsfuck,解密后是一句话
用工具解不开,直接自己写脚本吧ANSI->Unicode
这题怀疑出错了吧,函数的都没定义,咋传?还没get到出题人的意图,通过下一题直接读的源码
先看源码,用php://input改成admin,然后可以直接读文件,index中有个class.php
1
|
<span style="color: rgb(0, 0, 0);"><?php<br>class Read{//f1a9.php<br> public $file;<br> public function __toString(){<br> if(isset($this->file)){<br> echo file_get_contents($this->file); <br> }<br> return "__toString was called!";<br> }<br>}<br></span> |
没法直接读f1a9.php,反序列化去读
靠上个题读到源码,然后看了下role有注入,还有两层base64
Sqlmap有个base64encode.py的tamper,所以自己改下,改成两层
然后sqlmap.py –r –tamper=”base2.py” –v 3 ,the_key表,key字段
http://huashan.xdsec.cn/pic/login
这里可以看到源码,
重置密码的地方可以二次注入
注册的时候带’的用户名,然后重置密码的时候会注入
‘ and LEFT ((select flag from flag),x)=’ flag_Xd{hSh_ctf:dutwq}’
如果充值成功了,密码就会变,所以就无法登陆了,写脚本跑下就好了,太慢了……
这个是plaidctf2014的原题,不过改了一个地方,
var args = [].slice.apply(arguments).sort().filter(function(x,i,a){return a.indexOf(x) == i;});
if(args.length != 5) return "数够参数了吗?";
var flag = false; args.map(function(x){flag |= x >= 999;});
if(flag) return "有点大了哦";
1
2
3
4
5
|
var m = args.map(cal); if(m.filter(function(x,i){return m[2]+3*i==x;}).length < 1) return "no"; if(m.filter(function(x,i){return x == args[i];}).length < 2) return "nono"; if(m.filter(function(x,i){return x > m[i-1];}).length > 2) return "bala"; if(m.filter(function(x,i){return x < m[i-1];}).length > 1) return "balana~"; |
满足条件即可弹出flag
五次分别输入
2.0
2.00
6
76
949
代码就是个简单变化,动态跟了几步,发现进行了如下操作:
1
2
3
4
5
6
7
|
""" xor 0x30 ^ 1 xor 0x32 ^ 2 xor 0x33 ^ 3 xor 0x34 ^ 1 xor 0x35 ^ 2 """ |
最后进行字符串比较,反过来写下就可以,如下:
1
2
3
4
5
|
target = "VgobmndVlBVE" result = "" for index, item in enumerate(target): result += chr(ord(item)^(((index)%3)+1)) print result |
这题的逻辑就不是常人的,有两个用户名和密码。
开始那个还正常点
用户名:amdin,
密码的md5值知道,然后反查了下值为:xdadmin
但是输完并没有什么用,提交也不对:
后来发现另外一个函数也用到了用户名密码,如下:
输入3247,5569得到如下:
组合下输出的结果,提交不对,,,,,,,,,,
不对啊,,,,,,,,,,
仔细看代码,没别的逻辑了啊,,,,纠结了好久
突然队友提交了“用户名+密码+输出”的结果,通过。。。。。。。。
竟然通过了。。。。。。。。。
题目是个图片,直接strings crackme3.jpg,得到一串01
目测可以拼出来字,一共1177个,11*107
代码就是个简单的走迷宫,图如下:
输入的东西,进行各简单变化,对应于走的方向,如下:
走的逻辑如下:
根据坐标生成方向即可,逆代码如下:
1
|
<span style="color: rgb(0, 0, 0);">map_info = "***********####******#**#*****##*##********#*********#*#####***###***#*********#*********#********##"<br>result = ""<br>x = 0<br>y = 0<br>pos_list = []<br>for i in range(len(map_info)):<br> result += map_info[i]<br> y = (i)%10<br> x = i/10<br> if (i+1)%10 == 0:<br> result += "\n"<br> if map_info[i] == "#":<br> pos_list.append((x, y))<br>print map_info[0x28]<br>print result<br>print pos_list<br>last = 0<br>way_list = []<br>way_list.append((1,0))<br>way_list.append((0,-1))<br>way_list.append((0,-1))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((-1,0))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((0,-1))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((1,0))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((0,1))<br>way_list.append((-1,0))<br>print len(way_list)<br>map_dic = {}<br>map_dic[(-1, 0)] = 3<br>map_dic[(1, 0)] = 4<br>map_dic[(0, -1)] = 1<br>map_dic[(0, 1)] = 2<br>result = []<br>for i in way_list:<br> result.append(map_dic[i])<br>way_key = """0A1B<br>a2b3<br>4C5D<br>c6d7<br>8E9F<br>e0f1"""<br>way_key = way_key.split("\n")<br>print result<br>print len(result)<br>result_info = ""<br>for i in range(4):<br> for j in range(6):<br> result_info += way_key[j][result[i*6+j]-1]<br>print way_key<br>print result_info<br></span> |
flag如下:最后一行
虽然题目给了个jpg,但其实是个程序,主要的判断逻辑如下:
1
|
<span style="color: rgb(0, 0, 0);">int __cdecl sub_401000(char *Src)<br>{<br> char Dst[20]; // [sp+0h] [bp-14h]@1<br> Dst[0] = byte_415282;<br> *(_DWORD *)&Dst[1] = 0;<br> *(_DWORD *)&Dst[5] = 0;<br> *(_DWORD *)&Dst[9] = 0;<br> *(_DWORD *)&Dst[13] = 0;<br> *(_WORD *)&Dst[17] = 0;<br> Dst[19] = 0;<br> strcpy_s(Dst, 17u, Src);<br> check_equ_401320(Dst[0], Dst[8]);<br> check_equ_401320(Dst[0], Dst[9]);<br> check_equ_401320(Dst[1], Dst[10]);<br> check_equ_401320(Dst[2], Dst[4]);<br> check_equ_401320(Dst[3], Dst[5]);<br> check_equ_401320(Dst[11], 5);<br> check_equ_401320(Dst[7], 3 * Dst[11]);<br> check_bigger_401350(Dst[12], 5 * Dst[14]);<br> check_equ_401320(Dst[13], 2 * Dst[12]);<br> check_bigger_401350(Dst[3], 3 * Dst[12]);<br> check_bigger_401350(Dst[0], Dst[3]);<br> check_bigger_401350(21, Dst[0]);<br> check_equ_401320(Dst[0], Dst[6] + Dst[12]);<br> check_equ_401320(Dst[6], 2 * Dst[15]);<br> check_bigger_401350(Dst[2], 4 * Dst[14]);<br> check_bigger_401350(Dst[6], Dst[2]);<br> if ( Dst[2] % 3 )<br> {<br> printf(aNextTime);<br> sub_40E644();<br> exit(0);<br> }<br> check_bigger_401350(Dst[1], 7);<br> check_bigger_401350(Dst[2], Dst[1]);<br> return check_bigger_401350(Dst[0], Dst[1] + Dst[2]);<br>}<br></span> |
就是一些列的条件,满足就会输出得到了flag,约束如下:
1
|
<span style="color: rgb(0, 0, 0);">Dst[0] = Dst[8]<br>Dst[0] == Dst[9]<br>Dst[1] == Dst[10]<br>Dst[2] == Dst[4]<br>Dst[3] == Dst[5]<br>Dst[11] == 5<br>Dst[7] == 3 * Dst[11]<br>Dst[12] > 5 * Dst[14]<br>Dst[13] == 2 * Dst[12]<br>Dst[3] > 3 * Dst[12]<br>Dst[0] > Dst[3]<br>21 > Dst[0]<br>Dst[0] == Dst[6] + Dst[12]<br>Dst[6] == 2 * Dst[15]<br>Dst[2] > 4 * Dst[14]<br>Dst[6] > Dst[2]<br>Dst[2] % 3 == 0<br>Dst[1] > 7<br>Dst[2] > Dst[1]<br>Dst[0] > Dst[1] + Dst[2])<br></span> |
直接用个求解器求解即可,结果如下:
直接算出与加上0x60即可得到flag,如下:
这题目就是运行得时候,对一些不可访问的地址进行了写入,导致崩溃,看代码貌似是专门这样写的,如下:
直接对[0x10]处进行了赋值,程序这样的位置还有好几处,如下:
直接对其进行nop,然后将输出,转成printf即可,如下:
Flag直接就打印出来了,如下:
代码就很简单,如下图:
直接计算即可, 代码如下:
1
2
3
4
5
|
info = "ILoveXD" result_info = "" for i in range(7): result_info += chr(ord(info[i])+7-i) print result_info |
结果如下:
用户名: FindKey
密码:T25Zb3VyQ29tcHV0ZXI= base64解码得: OnYourComputer
生成了一个flag.jpg,里面的内容为FindKeyOnYourComputerArvinShow
Flag的品相好差。
ADFGX加密
给了3个文件 clear-1.txt crypt-1.txt和crypt-2.txt,用clear-1.txt和crypt-1.txt异或可以得到重复循环的片段,推测循环节即为密钥,用该密钥解密crypt-2即可得到flag
这是个原题,见这里:https://github.com/truongkma/ctf-tools/tree/master/cryptopals-solutions-master/set1/8
主要就是从一大堆CBC密文里检测出ECB密文,脚本一模一样抄即可。
打开就是flag,明文,直接交
flag_Xd{hSh_ctf:flag xie can xie yu hen xing gao}
这题先进行了DH交换密钥,然后用交换后的密钥加密的flag。A B P都不是很大,猜想这个离散对数问题比较容易解。
https://www.alpertron.com.ar/DILOG.HTM
用这个工具可以直接求解出离散对数算出a的私有指数,然后计算B^a就作为密钥了。但是这题有一个地方很坑,得到的密钥只有8个字节,但是AES需要16个字节作为密钥,一开始卡这里卡了很久。后来才脑洞出来高位全部补\x00,然后解完发现后一半flag是乱码,又是很坑,后来用CBC模式试了一下,iv取全0,解出来才正常。
web的任意文件读取,直接读源码
这题算法其实很简单,就是对随机字符串进行啦哈希操作然后进行一个替换作为密码。由于运行的时候用的hash函数是随机的,所以4个都试一下。
1
|
<span style="color: rgb(0, 0, 0);">#!/usr/bin/env python<br>import hashlib<br>dic = "AabRcQPXdYVeTWUSfghijklCmDnEoGpqFrHsItKJLuvwxyz01M23O45N67Z89B"<br>serial = "skxxRWi23"<br>for i in range(4):<br> ans = ‘‘<br> if (i==0):<br> enc = hashlib.md5(serial).hexdigest()<br> for j in range(8):<br> ans += str(dic.index(enc[j]))<br> print enc<br> print ans<br> if (i==1):<br> enc = hashlib.sha1(serial).hexdigest()<br> for j in range(8):<br> ans += str(dic.index(enc[j]))<br> print enc<br> print ans<br> if (i==2):<br> enc = hashlib.sha256(serial).hexdigest()<br> for j in range(8):<br> ans += str(dic.index(enc[j]))<br> print enc<br> print ans<br> if (i==3):<br> enc = hashlib.sha384(serial).hexdigest()<br> for j in range(8):<br> ans += str(dic.index(enc[j]))<br> print enc<br> print ans<br></span> |
最后尝试发现:
序列号:skxxRWi23
哈希值:521c0892b9dc0a7026fbe9664e6a339e7fee9492605733ea09968fbd83f18dfff91fe87d9d620fa4d3dd3010b47495dc
解锁码:545048447596050
这一是正确的。
这题其实是给apk加了个壳,程序里把真实的apk经过了加密(异或255)拼到了apk的dex文件后面,所以我直接把dex文件提取出来,整个文件异或255,然后从第一个PK开始提取出原始APK。然后原始的APK扔到jeb里就很容易看出源代码了。
算法很简单:
1
|
<span style="color: rgb(0, 0, 0);">#!/usr/bin/env python<br>import base64<br>import hashlib<br>username = base64.b64decode(‘U2hlMTFfTjZSYw==‘)<br>v4 = hashlib.sha1(username).hexdigest()<br>print username<br>print v4[:16]<br></span> |
apk用了zip伪加密,首先用010editor打开,将所有 0x50 0x4B 0x01 0x02(PK..)的位置后的第五个字节改为0,即可成功安装或解压。可参考吾爱破解的文章帖子http://www.52pojie.cn/thread-287242-1-1.html。
反编译apk后发现会调用Native函数check来验证密码,直接用ida将libdemo.so打开。如下
三段比较简单的加密,直接用ipython解了
把上面的result的值输入手机中,即可显示“碰头地点:太白南路2号”
这个题首先也是一个伪加密,修复后即可正常安装和解压。
首先apk一启动就会调用libgeneratekey.so中的isExit函数,如果该函数返回0那么apk就退出,而ida查看isExit函数的唯一作用就是返回0。因此可以使用apktool反编译apk,将SplashActivity.smali文件中第52行的if-eqz改为if-nez,即可绕过这个检测。
随后会启动MainActivity,这个类的唯一操作就是将输入的字符串传入native层的函数encodePassword中,并且显示出encodePassword返回的字符串。因此我们使用ida查看encodePassword函数。主要逻辑如下
可以看出,该函数会将输入的字符串与一串经过极其复杂变形的字符串进行比较,这里我们可以不去深入研究变形的过程,因为该函数没有将输入的字符串做任何变化,而是去直接比较的,因此我们可以使用调试或者hook的方法直接将变形完的字符串打印出来。这里我用frida直接hook了encodePS函数,打印出它的返回值即可,会打印两遍,取后一次。
hook代码
|
输出:
上图以l开头的字符串即为flag。
这题并不难,直接解压后发现是乱的
然后扔binwalk,得到文件名和偏移量,脚本分解出文件
然后按照文件名排序解出并且合并文本
Python沙盒逃逸题。
一开始设想用[].__class__.__base__.__subclasses__()[40]来使用file读文件。后来发现他命令限制长度50,非常蛋疼。后来才发现可以直接设定__builtins__变量来把指令分成多条进行,就不会受这个限制了。最后的exp如下:
1
|
<span style="color: rgb(0, 0, 0);">__builtins__[‘ww‘]=().__class__.__base__<br>__builtins__[‘w‘]=ww.__subclasses__()<br>w[40](‘./flag.txt‘).read();print k<br></span> |
Stegsolve打开,里面有张二维码,反色下就好了
扫码后base32
Binwalk可以看到一个zip
密码长度4位,直接爆破,密码:19bZ
解开后将右边的块补上即可
那个http的头里发现了:
直接用mp3stego decode掉得到:
可见字符,顺序乱了,考虑栅栏,长度为6的试了不行,后面应该长度有些许变化,手动切割,得到flag:
|
本文由 安全客 原创发布,如需转载请注明来源及本文地址。
本文地址:http://bobao.360.cn/learning/detail/3019.html
标签:
原文地址:http://www.cnblogs.com/adislj777/p/5924439.html