欢迎访问Sunbet官网(www.sunbet.us),Allbet欧博官网(www.ALLbetgame.us)!

首页Sunbet_安全防护正文

分析SECCON CTF 2019中Crypto方向题目

b9e08c31ae1faa592019-12-2488安全技术CTF

分析SECCON CTF 2019中Crypto方向题目

前言

在SECCON CTF 2019中有3道Crypto方向的题目,题目相对比较简单,在这里对题目进行一下分析。

coffee_break

题目描述如下: The program "encrypt.py" gets one string argument and outputs ciphertext. Example: $ python encrypt.py "test_text" gYYpbhlXwuM59PtV1qctnQ== The following text is ciphertext with "encrypt.py". FyRyZNBO2MG6ncd3hEkC/yeYKUseI/CxYoZiIeV2fe/Jmtwx+WbWmU1gtMX9m905 encrypted.py 分析一下源码,发现题目流程非常直接,key1是自定义函数encrypt的密钥,key2是AES的密钥,且key1、key2均已知,题目将flag先做一次encrypt,然后对结果做padding,再进行AES加密(采用ECB模式,同时对key2也进行padding)。由于key2和padding的规则均已知,那么我们很容易就可以恢复出enc1,那么接下来就是写encrypt函数的逆decrypt函数了。 decrypt函数很好写,改成减法就可以了:
def decrypt(key, text):
    s = ''
    for i in range(len(text)):
        s += chr((((ord(text[i]) - 0x20) - (ord(key[i % len(key)]) - 0x20)) % (0x7e - 0x20 + 1)) + 0x20)
    return s
最后写成solver如下:
from Crypto.Cipher import AES
import base64

def decrypt(key, text):
    s = ''
    for i in range(len(text)):
        s += chr((((ord(text[i]) - 0x20) - (ord(key[i % len(key)]) - 0x20)) % (0x7e - 0x20 + 1)) + 0x20)
    return s

c = 'FyRyZNBO2MG6ncd3hEkC/yeYKUseI/CxYoZiIeV2fe/Jmtwx+WbWmU1gtMX9m905'

key1 = "SECCON"
key2 = "seccon2019"

c = base64.b64decode(c.encode('ascii'))
cipher = AES.new(key2 + chr(0x00) * (16 - (len(key2) % 16)), AES.MODE_ECB)
enc1 = cipher.decrypt(c)
print(decrypt(key1, enc1))
执行脚本即可得到flag:
SECCON{Success_Decryption_Yeah_Yeah_SECCON}

ZKPay

题目只给了一个web链接,访问链接之后界面如下:   分析SECCON CTF 2019中Crypto方向题目  安全技术 第1张 有注册页面,那我们随便注册一个tom用户,注册之后登陆,界面如下: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第2张 简单浏览一下就会发现网站提供给了我们三个功能:
第一个页面(Home)展示当前的余额以及收款记录,初始有500余额,如果我们的余额>1000000那么就会显示flag。
第二个页面(Send)允许我们转账给他人,我们输入一个金额后会生成一个二维码,别人扫了这个二维码,就会收到我们的转账。
第三个页面(Receive)允许我们收款,我们扫了别人转账的二维码,我们就会收到这一笔金额。
我们尝试输入100,成功生成一张二维码如下: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第3张 我们尝试输入大于我们当前余额的金额,比如1000,则会提示Don't cheat!,同时二维码生成失败: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第4张 那么我们识别一下生成的转账100的二维码的内容,发现得到内容如下:
username=bob001&amount=100&proof=MHp0dPknFIRzzPKQI7QyNrqB3eaYrmt1zBRDKQZZmOAlMCAw6BA66tCUJUCGsuIE0eSyN5yFxcbRuf1x7HkaXFNoKiYxCjCsrZvaYHK0r5I3t5INyvLN7VDwKxyxm2PZPqDGnXz+KnO6P6tHXK+g/ZGyUz8+V+A/xG6y5E1nbrR4+PoMIL0KMSAwG2en1UBWnIayMomcoQfm9ajwU4fUQz91sIYfkiwKCwcxCjBlmnbjpYZUs4BQcUS16JjOrnjRRFPqC3UgCm4VQgeHLDEgMHdwhL+9bMK+UjLe0LwHdujShpbE7HMarWGhrrSmVqMRMQowuWBl8E3VdZEy4y5H1uBwcd27qUN1DFzW43SSD9YOYywwCjBbRw4C+aG3ulLAWOWunjPOaW95iJLRoWuQ5s7Nuu1/BTEK&hash=a7dc02e0891c6af6e6e47cdd41618822ce076b6dacfd9beb2025ace7613bd94b
其中usernameamount分别是我们当前的用户名和要转账的金额,proofhash两个参数我们暂时无法理解,因此我们尝试再生成一张转账200的二维码并再次识别,得到结果如下:
username=bob001&amount=200&proof=MHp0dPknFIRzzPKQI7QyNrqB3eaYrmt1zBRDKQZZmOAlMCAw6BA66tCUJUCGsuIE0eSyN5yFxcbRuf1x7HkaXFNoKiYxCjCsrZvaYHK0r5I3t5INyvLN7VDwKxyxm2PZPqDGnXz+KnO6P6tHXK+g/ZGyUz8+V+A/xG6y5E1nbrR4+PoMIL0KMSAwG2en1UBWnIayMomcoQfm9ajwU4fUQz91sIYfkiwKCwcxCjBlmnbjpYZUs4BQcUS16JjOrnjRRFPqC3UgCm4VQgeHLDEgMHdwhL+9bMK+UjLe0LwHdujShpbE7HMarWGhrrSmVqMRMQowuWBl8E3VdZEy4y5H1uBwcd27qUN1DFzW43SSD9YOYywwCjBbRw4C+aG3ulLAWOWunjPOaW95iJLRoWuQ5s7Nuu1/BTEK&hash=a7dc02e0891c6af6e6e47cdd41618822ce076b6dacfd9beb2025ace7613bd94b
和第一次的识别结果比较一下就会发现,除了amount参数变化了以外,其余参数均不变化,那么我们尝试直接将amount改为1000000,然后再次注册一个账号收款,看能否收到这笔1000000的汇款:
[红日安全]Web安全Day13 - 命令执行实战攻防 本文由红日安全成员:Once 编写,如有不当,还望斧正。 大家好,我们是红日安全-Web安全攻防小组。此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字叫 Web安全实战 ,希望对想要学习Web安全的朋友们有所帮助。每一篇文章都是于基于漏洞简介-漏洞原理-漏洞危害-测试方法(手工测试,工具测试)-靶场测试(分为PHP靶场、JAVA靶场、Python靶场基本上三种靶场全部涵盖)-实战演练(主要选择相应CMS或者是Vulnhub进行实战演练),如果对大家有帮助请Star鼓励我们创作更好文章。如果你愿意加入我们,一起完善这个项目,欢迎通过邮件形式(sec-redclub@qq.com)联系我们。 1. 命令执行&代码执行
分析SECCON CTF 2019中Crypto方向题目  安全技术 第5张 可以看到系统再次提示我们no cheat!,我们猜测它的check逻辑很有可能是判断当前余额是否大于转账金额,如果是的话转账通过,否则转账失败,这里bob001的账户余额小于1000000,因此在alice001这个账户这里无法接受这笔汇款。 那我们可以换个思路想一想,如果我们把amount参数改为负数,比如-1000000,那么再check的时候,由于转账金额是负数,那么当前余额确实大于转账金额,就可以通过check,此时我们再用另外一个账号来收款,这样发起转账的一方由于扣款数为负,相当于增加了余额,就可以以此来达成题目条件。我们尝试将amount的值改为-1000000,重新生成一张二维码并使用alice001账户来接收这笔汇款: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第6张 可以看到这笔转账成功了,alice001的账户余额变为了-999500元: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第7张 此时我们回到bob001账户,可以看到我们的账户余额变为了1000500,当然也就拿到了flag: 分析SECCON CTF 2019中Crypto方向题目  安全技术 第8张 flag:
SECCON{y0u_know_n07h1ng_3xcep7_7he_f4ct_th47_1_kn0w}

Crazy Repetition of Codes

题目描述如下: I'm crazy about googology! crc.py requirements.txt 打开requirements.txt可以看到题目告诉我们pycrypto的版本是2.6.1,这个就是明确了一下crc.py中使用的pycrypto的版本(即from Crypto.Cipher import AES那行),我们参考一下即可。 然后我们打开crc.py,简单审计一下源码,可以发现题目的逻辑很简单,key是由连续6次CRC32值的bytes形式拼接而成的,然后使用这个key对flag进行了AES加密,那么我们的任务很明确,就是求出key就可以了。 继续看一下可以发现每次CRC32操作的数据都是已知的(依次为"TSG", "is", "here", "at", "SECCON", "CTF!"这6个字符串),而每次crc的值都是由自身反复更新得到的(初始值为0),最后把经过int("1" * 10000)次CRC32循环操作得到的最终值作为key的一部分,这里注意int("1" * 10000)是一个相当巨大的数字,我们是不可能真的跑这么多次循环然后直接看一下crc的最终值的,因此肯定要进行化简。 正如CRC32的名字那样,我们每次CRC32操作的输出是32比特的数,那么根据鸽巢原理,在大约2*32次步骤之后肯定会有循环出现,即crc的值又会回到初值0,那么我们就可以通过遍历先看一下多少次循环后crc的值又变回0,把这个当做一个循环周期,然后把`int("1" 10000)%循环周期`当做是真正的有效循环,这样就可以直接做有效循环然后看crc的最终值是多少,然后把得到的结果依次拼接形成key再拿去做AES解密,即可得到flag。 但是在写脚本的时候我们会发现,即时这种方法用python跑仍然太慢了,那么我们可以尝试写成C++的solver来跑,这里给出一版C++的solver,首先我们把CRC32的周期计算出来(6次的周期都是一样的):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>

typedef unsigned int uint;
uint POLYNOMIAL = 0xEDB88320;
int have_table = 0;
uint table[256];

void make_crc32_table(){
    int i, j, crc;
    have_table = 1;
    for (i = 0 ; i < 256 ; i++)
        for (j = 0, table[i] = i ; j < 8 ; j++)
            table[i] = (table[i]>>1)^((table[i]&1)?POLYNOMIAL:0);
}

uint crc32(uint crc,char *buff, int len){
    if (!have_table) make_crc32_table();
    crc = ~crc;
    for (int i = 0; i < len; i++)
        crc = (crc >> 8) ^ table[(crc ^ buff[i]) & 0xff];
    return ~crc;
}

int main(){
    char * buf = "TSG";
    uint32_t _crc32 = 0;
    make_crc32_table();
    int i = 0;
    unsigned int cycle = 1;
    while(1) {
        _crc32 = crc32(_crc32, buf, 3);
        if (_crc32 == 0) {
            break;
        }
        cycle ++;
    }
    printf("%d\n",cycle);
    return 0;
}
跑出来周期是1431655765,然后我们再使用python算出有效周期:
>>> int("1" * 10000)%1431655765
169873741L
接下来就可以把6次的crc的值直接跑出来了:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>

typedef unsigned int uint;
uint POLYNOMIAL = 0xEDB88320;
int have_table = 0;
uint table[256];

void make_crc32_table(){
    int i, j, crc;
    have_table = 1;
    for (i = 0 ; i < 256 ; i++)
        for (j = 0, table[i] = i ; j < 8 ; j++)
            table[i] = (table[i]>>1)^((table[i]&1)?POLYNOMIAL:0);
}

uint crc32(uint crc,const char *buff, int len){
    if (!have_table) make_crc32_table();
    crc = ~crc;
    for (int i = 0; i < len; i++)
        crc = (crc >> 8) ^ table[(crc ^ buff[i]) & 0xff];
    return ~crc;
}

int main() {
    const char *buf[] = {"TSG", "is", "here", "at", "SECCON", "CTF!"};
    int buflen[] =  {3,2,4,2,6,4};
    make_crc32_table();
    int i=0,j=0; 
    for(i=0;i<6;i++){
        uint32_t _crc32 = 0;
        for(j=0;j<169873741;j++) {
            _crc32 = crc32(_crc32, buf[i], buflen[i]);
        }
        printf("%s %u\n",buf[i],_crc32);
    }
}
得到结果如下:
TSG 2962998607
is 3836056187
here 2369777541
at 3007692607
SECCON 1526093488
CTF! 3679021396
接下来按照题目要求将其拼接为key,然后进行解密即可得到flag:
from Crypto.Util.number import *

crclist = [2962998607,3836056187,2369777541,3007692607,1526093488,3679021396]
key = ""

for i in crclist:
    key += long_to_bytes(i)

c = '79833173d435b6c5d8aa08f790d6b0dc8c4ef525823d4ebdb0b4a8f2090ac81e'.decode('hex')
aes = AES.new(key, AES.MODE_ECB)
flag = aes.decrypt(c)
print flag
flag:
SECCON{Ur_Th3_L0rd_0f_the_R1NGs
   

网友评论