实验吧 tlc

TOC

  1. 1. 分析

分析

首先用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,因为本人还不太熟练,所以只能先用这么笨笨的办法。