DDCTF部分WP

这周去打了DDCTF,花了一周做出了九道题,完成了1000分的梦想。也算是菜鸡打比赛这么久拿到分数最多的一次了,现记录如下:

MISC

1、(╯°□°)╯︵ ┻━┻

(╯°□°)╯︵ ┻━┻
d4e8e1f4a0f7e1f3a0e6e1f3f4a1a0d4e8e5a0e6ece1e7a0e9f3baa0c4c4c3d4c6fbb9e1b2e2e5e2b5b4e4b8b7e6e1e1b6b9e4b5e3b8b1b1e3e5b5b6b4b1b0e4e6b2fd

刚开始拿到这道题的时候以为是base64,因为base64是可以解出来的,解出base64后以为是栅栏密码,解了半天无效,卡在这里。
之后观察字符特点发现字母最大没有超过f的,应该是16进制,可是转换成ascii还是乱码,又试过把整个文本倒序输出(因为题目颜文字名称为flipping table),依然无效。
之后尝试尝试各种方法,并在Wechall里面发现了类似的题目(Training: Crypto - Caesar II),还是做题少啊。。。。
其实题目就是一个16位表示的移位密码,写脚本跑flag:

s="d4 e8 e1 f4 a0 f7 e1 f3 a0 e6 e1 f3 f4 a1 a0 d4 e8 e5 a0 e6 ec e1 e7 a0 e9 f3 ba a0 c4 c4 c3 d4 c6 fb b7 b9 b8 e4 b5 b5 e4 e2 b7 b6 b5 b5 b2 e1 b9 b2 b2 e4 b0 b0 e4 b7 b7 b5 e5 b3 b3 b1 b1 b9 b0 b7 fd"
s=s.split()
for key in range(0,128+1,1):
    for i in s:
        i = int(i,16)
        print (chr((i + key + 256) % 256 ), end = '')
    print (key)

当跑到128的时候看到了flag

2、第四扩展FS

D公司正在调查一起内部数据泄露事件,锁定嫌疑人小明,取证人员从小明手机中获取了一张图片引起了怀疑。这是一道送分题,提示已经在题目里,日常违规审计中频次有时候非常重要。

题目附件是一个windows.jpg文件,binwalk发现内含有zip文件,使用foremost分离得到一个zip文件
zip文件经过加密,检查过发现并不是伪加密,于是有一次卡在了密码上。。。。。。
后来群里有人提示那张jpg文件里面有东西,查了半天隐写最后竟然发现密码是在属性->详细信息->备注里!!!
后来想想其实这样是比较符合实际情况的,很多人是会把不常用的密码写到文件的备注里,可以看出DD的这次赛题画风比较贴近实际了。
打开zip文件得到了一个file.txt,考虑到题目最后一句话中提到的频次,写个脚本来统计文件中字母出现的频次:

s=open('file.txt','r').read()
A="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789!{}"
for a in A:
    times=s.count(a)
    print (times,a)

然后很惊喜的发现有些字母是没有出现过的,而有些字母出现了一千多次,在这儿突然开个脑洞把出现的字母根据频次大小排序,于是很开心的得到了flag
(这道题属于想打死出题人系列,因为题目的解题思路和第四扩展FS没有任何一点关系,看到群里不少的人被题目名称给误导了,还好我机智!)

3、流量分析

提示一:若感觉在中间某个容易出错的步骤,若有需要检验是否正确时,可以比较MD5: 90c490781f9c320cd1ba671fcb112d1c
提示二:注意补齐私钥格式
—–BEGIN RSA PRIVATE KEY—–
XXXXXXX
—–END RSA PRIVATE KEY—–

这是我打比赛过程中第一次做流量分析题(以前遇到不是推给队友就是直接放弃)
首先打开协议分级发现有93.5%的流量都是FTPdata,通过ftp传送了文件
DDCTF部分WP_第1张图片

查看ftp流量,发现传送了Fl_g.zip和sqlmap.zip两个文件,但却伴随着大量的数据包丢失
这里写图片描述
这里写图片描述
考虑是否有办法恢复这些丢失的报文,但看了好久发现并没有重发的报文,因此这条路可以宣告gg了
再去看看协议分级发现里面还有smtp流量,该流量是收到的邮件信息,去看看这些报文,在一封邮件里发现了一个base64加密的图片,解码后根据题目的提示二猜到应该是一个RSA私钥文件,同时发现流量包里还有HTTPS流量,因此将私钥文件导入解密https流量的到flag.
(最后导入证书这一步卡了很久,最后比对分析是自己证书多了几个回车格式上的错误,可以说是很生气了)

4、安全通信

这道题目拿到题是想放弃的,因为对aes了解的比较少。
看完代码搞清了程序流程:首先输入你的mission key(系统根据mission key生成你的flag),然后输入agent id(随意输),程序会随机生成key并根据你的agent id 和flag对字符串Connection for mission: {agent id}, your mission’s flag is: {flag}进行加密并输出加密结果。然后程序允许用户自己定义字符串并用相同的key进行加密并输出,加密方式使用了ecb模式。
放弃之前顺手在google查了一下aes ecb attack,发现由于ecb模式是直接对明文进行分块加密,因此存在明文攻击的可能性,具体参考:Attacking ECB

ecb模式攻击原理:

DDCTF部分WP_第2张图片
ecb模式使用相同的key分块对明文分别进行加密,相同的明文获得相同的密文输出
根据这一特性,可以构造如下数据进行攻击:
首先输入blocksize-1的填充,这样未知字符串的第一个字符将落到填充块的最后一个字节:
这里写图片描述
这时会得到填充块的一个密文输出,爆破最后一个字节,直到产生与刚才相同的密文输出,就可以确定未知字符串的一个字节,重复这个过程就可以得到完整的未知字符串。

攻击条件

要能够像包含未知字符串的明文中插入数据(本题满足条件)
exp:

#!/usr/bin/env python
# coding=utf-8

from pwn import *
found=False
number=15
#count=1
flag=""
message="Connection for mission: , your mission's flag is: DDCTF{7ec4e929f4b93b6fbd3506dd"
while(number>=0):
    p=remote('116.85.48.103',5002)
    p.recvline()
    p.sendline("570ddb32ebcb382bdd0a62f437c4f769")
    p.recvline()
    p.sendline("1"*number)
    initialdata=p.recvline()
    blockdata=initialdata[144:175]
    #print(initialdata)
    #print("----------")
    array="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789{}"
    count=1
    for i in array:
        p.recvline()
        print count
        count=count+1
        message="Connection for mission: "+"1"*number+", your mission's flag is: DDCTF{7ec4e929f4b93b6fbd3506dd"+flag+i
        #print(message)
        p.sendline(message)
        data=p.recv()
        #print data
        if data[144:175]==blockdata:
            found = True
            print i
            flag=flag+i
            number=number-1
            if(i=="}"):
                number=-1
            #message=message+i
            break
            p.close()
print(flag)

每次只能爆16位,这是爆flag第三部分的代码,前面两部分需要稍微修改代码。

Android

1、RSA

先用jadx查看android的java代码,确定使用libhello-libs.so中的函数StringFromJNI判断输入是否正确。使用IDA加载此so文件,找到对应的函数Java_com_didictf_guesskey2018one_
MainActivity_stringFromJNI
sub_31364函数以输入为参数进行了某些处理,根据函数流程以及“basic_string::_S_construct null not valid”字符串基本确定次函数功能类似于stl string的初始化,将char*转化为string。string在内存中的结构为

这里写图片描述
其中ref表示指向当前string的指针个数,当ref<0时表示此string不允许使用指针,只允许复制。
Sub_31364函数功能为createstring,下面的sub_30A08函数为copy,j_j_j__Z20__aeabi_wind_cpp_prjSs基本可以确定为关键函数。下面分析此函数。
函数前半段为对输入进行处理,例如判断输入长度是否为43,并且将输入与byte_4DECB中的字符串进行亦或,得到的结果前十位转化为long作为除数。
后面是对两串固定字符进行处理,得到被除数。j_j_j__ZNSt3mapIciSt4lessIcESaISt4p
airIKciEEEixERS3_函数经过demangle得到

j_j_j_std::map <char, int, std::less, std::allocator<std::pair<char const, int> > >::operator[](char const&)

也就是相当于stl map的[]操作。所以使用python脚本可以得到被除数。

map1 = {}
str1 = 'deknmgqipbjthfasolrc'
for i in range(len(str1)):
    map1[str1[i]] = i/2
str2 = 'jlocpnmbmbhikcjgrla'
k = []
for i in range(len(str2)):
print map1[str2[i]],

最后是对结果的判断,首先判断余数是否为0,以及结果和被除数的大小。可以从0~√n 依次判断是否可以整除,最后得到一组数据1499419583,3927794789。根据判断条件得出被除数是1499419583,根据结果倒推可以得到flag。

2、Hello Baby Dex

Hook libdvm.so中的 openDexFileNative函数,打开apk可以得到patch_temp.jar。用jadx打开,根据流程可知是一个class patch,使用joseph算法获得最后的key,使用python脚本获得flag。

def joseph2(strt, dis):
    obj = [2131165184, 2131165213, 2131165215, 2131165216, 2131165222, 2131165221, 2131165233, 2131165311, 2131165185,
           2131165255, 2131165261, 2131165242, 2131165245]
    i2 = strt
    i = 0
    while 1:
        if len(obj) <= 1:
            break
        i = i2 + dis - 1
        i2 = i % len(obj)
        tmp = obj[i2]
        obj.remove(tmp)
    return str((obj[0] >> 5) & (obj[0] << 6))
print 'DDCTF{'+joseph2(5,6)+joseph2(7,8)+'}'

3、Diffie-Hellman

Apk的java部分与1相同,分析Java_com_didictf_guesskey2018two_MainActivity_
stringFromJNI函数的逻辑,可得逻辑为:
已知p和result,以及迭代函数a = f(a) % p,求经过多少次迭代后a等于result。所以代码为:

#include 
int main(int argc, char const *argv[]) {
    unsigned long p = 0xB49487B06AA40;
    unsigned long result = 0x1D026744B3680;
    unsigned long tmp = 0;
    unsigned long v12 = 2;
    unsigned long i = 0;
    for(i = 0;i < 0xffffffff; i ++)
    {
        //printf("i is %ld\n", i);
        *(((unsigned int *)&tmp) + 1) = v12 >> 31;
        *((unsigned int *)&tmp) = v12 * 2;
        v12 = tmp % p;
        if(v12 == result)
        {printf("has found, i is %ld\n", i);}
    }
    return 0;
}

你可能感兴趣的:(DDCTF部分WP)