实验吧 tlc

来自实验吧的一道逆向题:http://www.shiyanbar.com/ctf/17

首先用IDA先观测一下,然后持续处于懵逼状态,最后气的亲自反汇编了一遍,下面是反汇编出来的源码,和源程序应该有90%的相似度。

//file:tlc.c

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define LENGTH 12

//看到这个函数是对输入字符串进行rot13操作(核心语句:a1[v3] = (a1[v3] + 13) % (v4 + 26);)
int rot13(char *buf)
{
    int length = strlen(buf);

    for (int i = 0; i < length; i++)
    {
        int cases;
        if (buf[i] >= 'A'&&buf[i] <= 'Z')
        {
            cases = 65;

            buf[i] = (buf[i] + 13) % (cases + 26);
            if (buf[i] <= 25)
            {
                buf[i] += cases;
            }
        }
        else if (buf[i] >= 'a'&&buf[i] <= 'z')
        {
            cases = 97;

            buf[i] = (buf[i] + 13) % (cases + 26);
            if (buf[i] <= 25)
            {
                buf[i] += cases;
            }
        }
    }

    return length;
}

int base64_decode_table(char ch)
{
    char temp = ch;

    if (ch < 'A' || ch > 'Z')
    {
        if (ch <'a' || ch > 'z')
        {
            if (ch <= '/' || ch > '9')
            {
                if (ch == '+')
                {
                    temp = 62;
                }
                else if (ch == '/')
                {
                    temp = 63;
                }
            }
            else
            {
                temp = ch + 4;
            }
        }
        else
        {
            temp = ch - 71;
        }
    }
    else
    {
        temp = ch - 65;
    }

    return temp;
}

//--这个函数是进行base64解码操作(因为有base64的三段式位移)
void base64_decode(char *str, char *buf, int length)
{
    if (str[length - 1] == '=')
    {
        length--;
    }
    if (str[length - 1] == '=')
    {
        length--;
    }

    int buf_length = 0;
    if (buf != NULL)
    {
        int i;
        for (i = 0; i < length / 4 * 4; i += 4)
        {
            if (str[i] == '\n')
            {
                i++;
            }

            int temp = base64_decode_table(str[i]) << 2;
            buf[buf_length] = temp | ((base64_decode_table(str[i + 1]) & 0b00110000) >> 4);

            temp = base64_decode_table(str[i + 1]) << 4;
            buf[buf_length + 1] = temp | (base64_decode_table(str[i + 2]) >> 2);

            temp = base64_decode_table(str[i + 2]) << 6;
            buf[buf_length + 2] = temp | base64_decode_table(str[i + 3]);

            buf_length += 3;
        }

        int offset = length & 0b00000011;
        if (offset == 0b10)
        {
            int temp = base64_decode_table(str[i]) << 2;
            buf[buf_length++] = temp | ((base64_decode_table(str[i + 1]) & 0b00110000) >> 4);
        }
        else if (offset = 0b11)
        {
            int temp = base64_decode_table(str[i]) << 2;
            buf[buf_length] = temp | ((base64_decode_table(str[i + 1]) & 0b00110000) >> 4);
            temp = base64_decode_table(str[i + 1]) << 4;
            buf[buf_length + 1] = temp | (base64_decode_table(str[i + 2]) >> 2);
            buf_length += 2;
        }
    }
    else
    {

    }

    return buf_length;
}

//判断(高n位能被n整除)
//str为数字的字符串形式
int judge(char *str, int str_length)
{
    int x = 0;
    int result;//在这里没有用,只不过程序要返回
    for (int i = 0; i < str_length; i++)
    {
        result = i;
        x = 10 * x + (str[i] - '0');
        if (x % (i + 1))
        {
            exit(1);
        }
    }

    return result;
}

//decode下面皆为解码部分,本人才疏学浅,并不懂有什么特殊含义
int decode1(char *out, char *str, int str_length)
{
    char *v6 = out + 8;
    out[0] = '\0';
    char *result = out;
    out[1] = '\0';

    for (int i = 0; i < 256; i++)
    {
        result = v6 + i;
        *result = i;
    }

    unsigned char v9 = 0;
    int v10 = 0;
    for (int i = 0; i < 256; i++)
    {
        char ch = v6[i];
        v9 = v9 + ch + str[v10];
        char v5 = v6[v9];
        v6[v9] = ch;
        v6[i] = v5;
        result == ++v10;
        if (v10 >= str_length)
        {
            v10 = 0;
        }
    }

    return result;
}

int decode3(char *in)
{
    char *v1 = in + 2 * 4;
    int ch = (unsigned int)(in[0] + 1);
    unsigned char v3 = in[ch + 8];
    int v4 = (unsigned char)(in[4] + v3);
    unsigned char v5 = in[v4 + 8];

    *(int *)&(in[0]) = ch;
    *(int *)&(in[4]) = v4;
    v1[v4] = v3;
    v1[ch] = v5;

    return (unsigned char)in[(unsigned int)((unsigned char)(v3 + v5) + 8)];
}

int decode2(char *in1, char *out, char *in2, int in2_length)
{
    int result;
    for (int i = 0; i < in2_length; i++)
    {
        result = i;
        char ch = in2[i];
        out[i] = ch ^ decode3(in1);
    }

    return result;
}

int main(int argc, char **argv)
{
    char buf[LENGTH] = { 0 };
    char s1[1024], s2[1024];
    memset(s1, 0, 1024);
    memset(s2, 0, 1024);

    printf("Please input key:");
    fflush(stdout);

    fgets(buf, LENGTH, stdin);

    rot13(buf);

    base64_decode(buf, s1, LENGTH);

    judge(s1, strlen(s1));

    char *s = (char *)malloc(264);
    memset(s, 0, 264);

    decode1(s, s1, strlen(s1));

    //这个是直接从IDA数据段中获取,应该是密文,需要秘钥进行解码
    char const_s[] = { 14, 62, 106, 121, 121, 235, 156, 221, 130, 200, 82, 145, 155, 99, 157, 159, 2, 141, 207, 34, 68, 127, 0 };
    decode2(s, s2, const_s, strlen(const_s));

    printf("Text is:%s\n", s2);
    return 0;
}

然后看出程序首先输入12字节,然后rot13,然后base64解码,然后做了一个判断(高n位能被n整除),最后用输入作为密钥解密一段数据,得到flag。

但是满足高n位能被n整除的数很多,于是爆破。

#include<stdio.h>
#define MIN 100000000
#define MAX 1000000000
#define LENGTH 9

int main()
{
    for(int i=MIN;i1;ii--)
        {
            if(temp%ii==0)
            {
                temp=temp/10;
            }
            else
            {
                break;
            }
        }

        if(ii==1)
        {
            printf("%d\n",i);
        }
    }

    return 0;

}
import os
s=''
with open('dic','r') as f:
    s=f.read()

s=s.split('\n')
for v in s:
    command='main "'+v+'" >> answer'
    os.system(command)

最后在得到的数据中找到flag。

C:\Users\Ex\source>strings answer|grep "{"
p$el{
\{V(@
{#}%
Text is:{n
0['{H
xe{#a
Text is:{
|d{N
KhDn{
Text is:i{
;gm{
MF.{t_gM
ScW-{
Text is:[{LN_=emzl
{?Rv
\{ K
={A?
Text is:{
{#i[qQ~|
({0h5M
Text is:ISG{E43y_c0m131l3}
q<g{S
2x{F
1)e{
Text is:-{<
Text is:{
{I\M
Gm{s=
Text is:{
Z}\{V
Text is:g{4
oI{$
Text is:{#
[{*W
Text is:D{YC&
Text is:u]{
O#{g8rj
.k{[px
Text is:t{
Text is:-{
Text is:<i{
Text is:{|

当然也可以用zio,因为本人还不太熟练,所以只能先用这么笨笨的办法。