Challenge area
1.elrond32
文件下载下来,放到ida里面看,找到关键代码。
大致分析,先求key,再找v2,再异或。
写出脚本
#include<stdio.h>
int main(void)
{
int key[9]={105,115,101,110,103,97,114,100};
int v2[33]={ 0xf,0x1f,0x4,0x9,0x1c,0x12,0x42,0x9,0xc,0x44,
0xd,0x7,0x9,0x6,0x2d,0x37,0x59,0x1e,0,0x59,0xf,0x8
,0x1c,0x23,0x36,0x7,0x55,0x2,0xc,0x8,0x41,0xa,0x14,};
int i;
for(i=0;i<33;i++)
{
printf("%c",key[i%8]^v2[i]);
}
}
得到flag{s0me7hing_S0me7hinG_t0lki3n}
2.666
ELF文件,ida打开,找到关键代码,分析
写出脚本
#include<stdio.h>
int main(void)
{
int s[19]={'i', 'z', 'w', 'h', 'r', 'o', 'z', '"', '"', 'w', '"', 'v', '.', 'K', '"', '.', 'N', 'i'};
int flag[19];
int i;
for(i=0;i<18;i+=3)
{
flag[i]=(s[i]^18)-6;
flag[i+1]=(s[i+1]^18)+6;
flag[i+2]=s[i+2]^6^18;
}
for(i=0;i<18;i++)
printf("%c",flag[i]);
}
3.Reversing-x64Elf-100
ELF文件,ida打开,找到关键代码,分析
比较有意思的是以前还没做到过用字符串组这种的加密,脚本如下
#include<stdio.h>
int main(void)
{
char v3[3][8] = {"Dufhbmf","pG`imos","ewUglpt"};
int i;
int flag[13];
for(i=0;i<=11;i++)
{
flag[i]=*(v3[i%3]+2*(i/3))-1;
printf("%c",flag[i]);
}
}
得到Code_Talkers
4.IgniteMe
exe文件,ida打开,找到关键代码,分析
写脚本
#include<stdio.h>
int main(void)
{
char code[]="GONDPHyGjPEKruv{{pj]X@rF";
int flag[24]={0};
int i;
int key[40]={13, 19, 23, 17, 2, 1, 32, 29, 12, 2,
25, 47, 23, 43, 36, 31, 30, 22, 9, 15,
21, 39, 19, 38, 10, 47, 30, 26, 45, 12,
34, 4};
for(i=0;i<24;i++)
{
flag[i]=((code[i]^key[i])-72)^0x55;
printf("%c",flag[i]);
}
}
套上格式,得到EIS{WADX_TDGK_AIHC_IHKN_PJLM}
5.debug
IDA不能打开,用Eexinfo PE打开,发现是.net,并且还混淆了的。
先去混淆,类似去混淆还有buuctf的一道[V&N2020 公开赛]CSRe 1。
先将文件和de4tor.exe放在同一个文件夹,这里是放在的de4tor,顺便把文件名改了,在cmd里面执行。
然后用
dnspy32位打开,直接进入入口点。
到了main函数。
得到lag{967DDDFBCD32C1F53527C221D9E40A0B}
6.hackme
ida打开找到关键代码。
写出脚本
#include<stdio.h>
int main(void)
{
int flag[23];
int code[23]={ 95, 242, 94, 139, 78, 14, 163, 170, 199, 147,
129, 61, 95, 116, 163, 9, 145, 43, 73, 40,
147, 103};
int i,j,num=0,men;
for(i=0;i<22;i++)
{
j=i+1;
men=0;
num=0;
while(men<j)
{
men++;
num=1828812941 * num + 12345;
}
flag[i]=code[i]^num;
printf("%c",flag[i]);
}
}
7.Guess-the-Number
java逆向,直接拖到jd-gui。
大数异或,上python,脚本如下
a=0x4b64ca12ace755516c178f72d05d7061
b=0xecd44646cfe5994ebeb35bf922e25dba
flag=hex(a^b)
print(flag)
8.BABYRE
9.EasyRE
这道题非常有意思,其f5出来的伪代码有点问题,开始看了好久还没看明白,后来一边写脚本,发现了问题。
然后这里去dbg里面看看字符串倒序怎么一回事。
然后开始写脚本
#include<stdio.h>
void down(int *a,int len_flag)
{
int i,t;
int len=len_flag;
for(i = 0; i < len/2; i++)
{
t = a[i];
a[i] = a[len-i-1];
a[len-i-1] = t;
}
}
int main(void)
{
int code[25]={'x', 'I', 'r', 'C', 'j', '~', '<', 'r', '|', '2', 't', 'W', 's', 'v', '3', 'P', 't', 'I',0x7f,0x7a,0x6e,0x64,0x6b,0x61};
int flag[25];
int i;
for(i=0;i<24;i++)
{
flag[i]=(code[i]^6)-1;
}
down(flag,25);
for(i=0;i<25;i++)
{
printf("%c",flag[i]);
}
}
得到flag{xNqU4otPq3ys9wkDsN}
10.Shuffle
ida打开直接就看到flag了,SECCON{Welcome to the SECCON 2014 CTF!}
11.re-for-50-plz-50
文件下载下来,Eexinfo PE打开,发现是mpis,而且ida无法f5,只好看汇编。
关键地方
写出脚本
#include<stdio.h>
int main(void)
{
char flag[]="cbtcqLUBChERV[[Nh@_X^D]X_YPV[CJ";
int i;
for(i=0;i<31;i++)
{
printf("%c",flag[i]^0x37);
}
}
得到TUCTF{but_really_whoisjohngalt}
12.dmd-50
ida打开,看到关键代码,然后发现是MD5加密
直接在线解密
13.secret-galaxy-300
ida打开,看了半天也没分析出来是什么,没有input,也没有输出,就是有些关于行星呀什么之类的。然后看别人的wp,用了od动调。
然后在ida里面的赋值好像在这里
然后得到flag:aliens_are_around_us
14.srm-50
文件直接打开,要你输入email和password,然后直接放到ida里面看,找到关键函数
得到flag:CZ9dmq4c8g9G7bAX
15.simple-check-100
前言:挺开心的,由于这道题的exe文件用dbg动调,得到的flag竟然是乱码,让我学会了如何用ida动态调试elf文件,这里给个链接如何用ida动态调试elf文件:https://www.it610.com/article/1298189057175658496.htm。
首先看看ida里面的逻辑
先来说说exe调试过程。
再来说一说ida动调elf过程。
然后得到flag
16.gametime
感谢这道题锻炼了我dbg的动调能力。
文件下载下来,是一个游戏,,属于玩通关了就给flag的那一种,先玩一玩,如果你足够厉害应该是可以玩出来的。玩了一下大概游戏规则就是看到s就按’ ‘,遇到x就按’x’,遇到m就按’m’。
然后放到ida里面看,为了好看一点,改了部分函数名称,分析分为3个部分。
第一部分,告诉你游戏规则
第二部分,熟悉怎么玩。
第三部分,玩10次,对了就给flag
接下来,x32dbg动调,需要自己慢慢分析整个流程,找到关键函数位置,这里就只放两个关键点的图片。
条件判断1
条件判断2
最后得到flag
17.tt3441810
这道题就是很无语的。就是将所有二进制提出来,然后去看。
脚本
#include<stdio.h>
int main(void)
{
int a[300]={ 104, 102, 108, 72, 191, 1, 0, 0,
72, 141, 52, 36, 72,
186, 2, 0, 0, 0, 0, 0, 0, 0, 72,
184, 1, 0, 0, 0, 0, 0, 0, 0, 15,
5, 104, 97, 103, 0, 0, 72, 191, 1, 0,
0, 0, 0, 0, 0, 0, 72, 141, 52, 36,
72, 186, 2, 0, 0, 0, 0, 0, 0, 0,
72, 184, 1,
15, 5, 104, 123, 112, 0, 0, 72, 191, 1,
0, 0, 0, 0, 0, 0, 0, 72, 141, 52,
36, 72, 186, 2,
0, 72, 184, 1,
0, 15, 5, 104, 111, 112, 0, 0, 72, 191,
1, 0, 0, 0, 0, 0, 0, 0, 72, 141,
52, 36, 72, 186, 2,
0, 0, 72, 184, 1, 0, 0, 0, 0, 0,
0, 0, 15, 5, 104, 112, 111, 0, 0, 72,
191, 1, 0, 0, 0, 0, 0, 0, 0, 72,
141, 52, 36, 72, 186, 2, 0, 0, 0, 0,
0, 0, 0, 72, 184, 1, 0, 0, 0, 0,
0, 0, 0, 15, 5, 104, 112, 114, 0, 0,
72, 191, 1,
72, 141, 52, 36, 72, 186, 2,
0, 0, 0, 0, 72, 184, 1,
0, 0, 0, 0, 15, 5, 104, 101, 116, 0,
0, 72, 191, 1,
0, 72, 141, 52, 36, 72, 186, 2, 0, 0,
0, 0, 0, 0, 0, 72, 184, 1, 0, 0,
0, 0, 0, 0, 0, 15, 5, 104, 125, 10,
0, 0, 72, 191, 1, 0, 0, 0, 0, 0,
0, 0, 72, 141, 52, 36, 72, 186, 2, 0,
0, 0, 0, 0, 0, 0, 72, 184, 1, 15, 5,
72, 49, 255, 72, 184, 60,15,5};
int i;
for(i=0;i<300;i++)
{
if(a[i]!=0&&a[i]<='z'&&a[i]>='a'&&a[i]!='h')
{
printf("%c",a[i]);
}
}
}
将输出内容整理一下,得到flag{poppopret}
18.notsequence
怎么说呢,这道题只要你看出是杨辉三角就简单。考了杨辉三角的两个个性质。
性质一:第n行数字的和为2^(n-1)。1=2^(1-1),1+1=2^(2-1),1+2+1=2^(3-1),1+3+3+1=2^(4-1),1+4+6+4+1=2^(5-1),1+5+10+10+5+1=2^(6-1)
性质二:斜线上数字的和等于其向左(从左上方到右下方的斜线)或向右拐弯(从右上方到左下方的斜线),拐角上的数字。1+1=2,1+1+1=3,1+1+1+1=4,1+2=3,1+2+3=6,1+2+3+4=10,1+3=4,1+3+6=10,1+4=5。
脚本
#include<stdio.h>
int main(void)
{
int a[200][200];
int i,j,n;
printf("n为杨辉三角的行数,请输入n:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
a[i][0]=1;
a[i][i]=1;
}
for(i=2;i<n;i++)
{
for(j=1;j<i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
}
for(i=0;i<n;i++)
{
for(j=0;j<=i;j++)
{
printf("%d",a[i][j]);
}
}
}
得到RCTF{37894beff1c632010dd6d524aa9604db}
19.re2-cpp-is-awesome
简单的cpp代码分析。
直接写脚本
#include<stdio.h>
int main(void)
{
int key[33]={0x24,0x00,0x05,0x36,0x65,0x07,0x27,0x26,0x2D,
0x01, 0x03,0x00,0x0D,0x56,0x01, 0x03,0x65,0x03,0x2D,0x16,
0x02,0x15,0x03,0x65, 0x00,0x29,0x44,0x44,0x01,0x44, 0x2B};
char table[120]="L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t";
int flag[30];
int i;
for(i=0;i<31;i++)
{
flag[i]=table[key[i]];
printf("%c",flag[i]);
}
}
20.easy_Maze
迷宫题,然后IDA打开先分析一下逻辑。
然后根据动态调试来获取变换后的迷宫。
然后就可以写迷宫了
21.Replace
这道题让我又见识了一种奇数偶数加密的方式。
首先upx脱壳,然后放入ida里面
写脚本
#include<stdio.h>
int main(void)
{
int a[257]={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
};
char b[71]="2a49f69c38395cde96d6de96d6f4e025484954d6195448def6e2dad67786e21d5adae6";
int flag[36];
int mid[36];
int i,j;
for(i=0;i<70;i++)
{
if(b[i]< 48 || b[i] > 57)
b[i] = b[i] - 87;
else
b[i] = b[i] - 48;
}
for(i=0;i<70;i++)
{
printf("%d ",b[i]);
}
printf("\n");
for(i=0,j=0;i<70;i+=2,j++)
{
mid[j]=((b[i]<<4)+b[i+1])^0x19;
}
for(i=0;i<=38;i++)
{
printf("%d ",mid[i]);
}
for(i=0;i<35;i++)
{
for(j=0;j<256;j++)
{
if(mid[i]==a[j])
{
flag[i]=j;
}
}
}
printf("\n");
for(i=0;i<35;i++)
{
printf("%c",flag[i]);
}
}
得到flag{Th1s_1s_Simple_Rep1ac3_Enc0d3}
22.SignIn
文件下载下来直接用ida打开,一套操作找到关键代码
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char v4; // [rsp+0h] [rbp-4A0h]
char v5; // [rsp+10h] [rbp-490h]
char v6; // [rsp+20h] [rbp-480h]
char v7; // [rsp+30h] [rbp-470h]
char v8; // [rsp+40h] [rbp-460h]
char v9; // [rsp+B0h] [rbp-3F0h]
unsigned __int64 v10; // [rsp+498h] [rbp-8h]
v10 = __readfsqword(0x28u);
puts("[sign in]");
printf("[input your flag]: ", a2);
__isoc99_scanf("%99s", &v8);
sub_96A(&v8, &v9);
__gmpz_init_set_str(&v7, "ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16LL);
__gmpz_init_set_str(&v6, &v9, 16LL);
__gmpz_init_set_str(&v4, "103461035900816914121390101299049044413950405173712170434161686539878160984549", 10LL);
__gmpz_init_set_str(&v5, "65537", 10LL);
__gmpz_powm(&v6, &v6, &v5, &v4);
if ( (unsigned int)__gmpz_cmp(&v6, &v7) )
puts("GG!");
else
puts("TTTTTTTTTTql!");
return 0LL;
}
发现是一个rsa加密, __gmpz_init_set_str 函数是GNU 高精度算法库。
c=0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35//密文
n=103461035900816914121390101299049044413950405173712170434161686539878160984549
e=65537
先得到q,p。
q=282164587459512124844245113950593348271
p=366669102002966856876605669837014229419
用脚本跑出来
from Crypto.Util.number import *
import gmpy2
p = 282164587459512124844245113950593348271
q = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = q*p
phi = (q-1)*(p-1)
d = gmpy2.invert(e,phi)
m = gmpy2.powmod(c,d,n)
flag = long_to_bytes(m)
print(flag)
得到suctf{Pwn_@_hundred_years}
23.EASYHOOK##
通过这道题学会了可以使用动调来找到加密函数的位置。
ida看到主函数后,发现里面根本不好找到加密函数,还有一个假的加密函数,然后通过动调来来找到加密函数,如下。
ida相应位置
写出相应脚本
#include<stdio.h>
int main(void)
{
int code[20]={0x61, 0x6A, 0x79, 0x67, 0x6B, 0x46, 0x6D, 0x2E, 0x7F, 0x5F,
0x7E, 0x2D, 0x53, 0x56, 0x7B, 0x38, 0x6D, 0x4C, 0x6E};
int i,j;
int flag[20];
flag[18]=code[18]^0x13;
for(i=0;i<18;i++)
{
if(i%2)
{
flag[i]=(code[i]^i)+i;
}
else
{
flag[i+2]=code[i]^i;
}
}
for(i=0;i<19;i++)
{
printf("%c",flag[i]);
}
}
得到的东西前面加一个f,得到flag{Ho0k_w1th_Fun}
24.babymips
如果你有可以反汇编mips架构的ida,这道题就很简单。
开始写脚本
#include<stdio.h>
int main(void)
{
int code[33]={ 0x51, 0x7C, 0x6A, 0x7B, 0x67, 0x52, 0xFD,
0x16, 0xA4, 0x89, 0xBD, 0x92, 0x80, 0x13, 0x41, 0x54, 0xA0,
0x8D, 0x45, 0x18, 0x81, 0xDE, 0xFC, 0x95, 0xF0, 0x16, 0x79,
0x1A, 0x15, 0x5B, 0x75, 0x1F};
int flag[33];
int i;
for(i=5;i<32;i++)
{
if(i%2)//奇
code[i]=code[i]<<2|code[i]>>6;
else//偶
code[i]=code[i]<<6|code[i]>>2;
}
for(i=0;i<32;i++)
{
flag[i]=code[i]^(32-i);
printf("%c",flag[i]);
}
}
25.reverse-for-the-holy-grail-350
不得不说这道题是真的有点坑。考验静态分析能力,还有一个爆破考点。
真正的比较在stringMod函数中。
脚本如下
#include<stdio.h>
int main(void)
{
int flag[19];//65, 105, 110, 69,111,97
flag[0]=65;
flag[3]=105;
flag[6]=110;
flag[9]=69;
flag[12]=111;
flag[15]=97;
int v8[19]={666,667 ,669 ,673 ,676 ,677 ,679 ,683 ,686 ,687 ,689 ,693 ,696 ,697 ,699 ,703 ,706 ,707 ,709};
int marry[7]={471, 12, 580, 606, 147, 108};
int i=0,j,c=0,v7=666;
for(i=0;i<18;i++)
{
flag[i]=flag[i]^v7;
v7=v7+v7%5;
}
flag[2]=239+256*2;
flag[5]=196+256*2;
flag[8]=220+256*2;
flag[11]=199+256*2;
flag[14]=222+256*2;
flag[17]=252+256*2;
for(i=0;i<18;i++)
{
printf("%d ",flag[i]);
}
printf("\n");
for(i=0,c=0;i<18;i+=3,c++)
{
for(j=35;j<123;j++)
{
if(flag[i]*(j^v8[i+1])%flag[i+2]==marry[c])
{
flag[i+1]=j^v8[i+1];
break;
}
}
}
for(i=0;i<18;i++)
{
flag[i]=flag[i]^v8[i];
printf("%c",flag[i]);
}
}
套上格式得到tuctf{AfricanOrEuropean?}
26.re4-unvm-me
pyc文件,然后就用uncompyle6反编译一下,由于其他文章之前有过这样的题,就不写怎么反编译了。
然后解密可以直接线上解,或者用脚本解,脚本比较慢
好兄弟写的脚本如下
list = [174282896860968005525213562254350376167, 137092044126081477479435678296496849608, 126300127609096051658061491018211963916, 314989972419727999226545215739316729360, 256525866025901597224592941642385934114, 115141138810151571209618282728408211053, 8705973470942652577929336993839061582, 256697681645515528548061291580728800189, 39818552652170274340851144295913091599, 65313561977812018046200997898904313350, 230909080238053318105407334248228870753, 196125799557195268866757688147870815374, 74874145132345503095307276614727915885]
list = [8705973470942652577929336993839061582]
for k in list:
m = hex(k)[2:]
print(m,end=',')
import hashlib
dic = ['{','}','0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
list1 = ['831daa3c843ba8b087c895f0ed305ce7','6722f7a07246c6af20662b855846c2c8','5f04850fec81a27ab5fc98befa4eb40c','ecf8dcac7503e63a6a3667c5fb94f610','c0fd15ae2c3931bc1e140523ae934722','569f606fd6da5d612f10cfb95c0bde6d','068cb5a1cf54c078bf0e7e89584c1a4e','c11e2cd82d1f9fbd7e4d6ee9581ff3bd','1df4c637d625313720f45706a48ff20f','3122ef3a001aaecdb8dd9d843c029e06','adb778a0f729293e7e0b19b96a4c5a61','938c747c6a051b3e163eb802a325148e','38543c5e820dd9403b57beff6020596d']
for j in list1:
for a in range(len(dic)):
for b in range(len(dic)):
for c in range(len(dic)):
for d in range(len(dic)):
for e in range(len(dic)):
m = dic[a].encode('utf-8') + dic[b].encode('utf-8') + dic[c].encode('utf-8') + dic[d].encode('utf-8') + dic[e].encode('utf-8')
flag = hashlib.md5()
flag.update(m)
md5 = flag.hexdigest()
if md5 == j:
print(m, end='')
27.Windows_Reverse1
这道题挺奇怪,将一串字符串作为索引表,然后我们输入的值就是表的下标,然后和一串字符串作比较。
首先先解壳,然后好像解壳后的文件就不能动调了,应该还是可以动调的,以后再学吧。
然后写脚本
#include<stdio.h>
int main(void)
{
int a[130]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x7E, 0x7D, 0x7C, 0x7B,
0x7A, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71,
0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68, 0x67,
0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D,
0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53,
0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F,
0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35,
0x34, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B,
0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
0x20, 0x00};
char v4[17]="DDCTF{reverseME}";
int i,j;
printf("flag{");
for(i=0;i<16;i++)
{
for(j=0;j<=130;j++)
{
if(v4[i]==a[j])
{
printf("%c",j);
break;
}
}
}
printf("}");
}
得到flag{ZZ[JX#,9(9,+9QY!}
28.easyRE1
ida打开,f5一下就可以得到flag{db2f62a36a018bce28e46d976e3f9864}
29.ReverseMe-120
这道题是base解码过程,以前都做的是编码,开始还没看懂。
根据提示字符串’you_know_how_to_remove_junk_code’,来用动调找到关键位置,明白加密原理。
第一次加密。
第二次加密。
然后到ida里面看相关位置。
知道是base64解码就简单多了,就异或0x25然后解码。
脚本如下
import base64
date_1 = "you_know_how_to_remove_junk_code"
date_2 = ''
for i in date_1:
date_2 += chr(ord(i)^0x25)
date = date_2.encode("utf-8")
flag = base64.b64encode(date) # 被编码的参数必须是二进制数据
print(flag)
30.android-app-100
安卓逆向,就当长见识吧。还要分析解压的一个so文件,确实做不来。
先jeb分析。
现在通过ida分析so文件来得到v1
然后就可以写脚本了,如果网上直接转好像不行,那个空格转不了。
import hashlib
str = '92174992 '
# 92060626+114366+“ ”
hl = hashlib.md5()
hl.update(str.encode(encoding='utf-8'))
print('MD5加密前为 :' + str)
print('MD5加密后为 :' + hl.hexdigest())
套上格式得到Sharif_CTF(833489ef285e6fa80690099efc5d9c9d)
31.serial-150
静态分析好像不行,必须动态分析,比较麻烦的就是不知道怎么改指令,好像改不了,xdbg都可以改。ida调试如下
然后这里是输入flag,随便输就行了
判断长度
然后是第一位
然后是第一位和最后一位的和的一个判断
然后就是第二位,第三位,总共要改33次zf。
得到flag:EZ9dmq4c8g9G7bAV
32.testre
就是base58,由于之前了解过,然后题中有一个让你混淆base64,实际上没得用,要解的话就直接排序一下最后的密文,然后网站直接解就行了。
得到flag:base58_is_boring
33.handcrafted-pyc
这道题学到了很多东西,文件读写呀,和python字节码这些。
看了别人wp做的,先根据题意生成pyc
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import marshal,zlib,base64
out=zlib.decompress(base64.b64decode('eJyNVktv00AQXm/eL0igiaFA01IO4cIVCUGFBBJwqRAckLhEIQmtRfPwI0QIeio/hRO/hJ/CiStH2M/prj07diGRP43Hs9+MZ2fWMxbnP6mux+oK9xVMHPFViLdCTB0xkeKDFEFfTIU4E8KZq8dCvB4UlN3hGEsdddXU9QTLv1eFiGKGM4cKUgsFCNLFH7dFrS9poayFYmIZm1b0gyqxMOwJaU3r6xs9sW1ooakXuRv+un7Q0sIlLVzOCZq/XtsK2oTSYaZlStogXi1HV0iazoN2CV2HZeXqRQ54TlJRb7FUlKyUatISsdzo+P7UU1Gb1POdMruckepGwk9tIXQTftz2yBaT5JQovWvpSa6poJPuqgao+b9l5Aj/R+mLQIP4f6Q8Vb3g/5TB/TJxWGdZr9EQrmn99fwKtTvAZGU7wzS7GNpZpDm2JgCrr8wrmPoo54UqGampFIeS9ojXjc4E2yI06bq/4DRoUAc0nVnng4k6p7Ks0+j/S8z9V+NZ5dhmrJUM/y7JTJeRtnJ2TSYJvsFq3CQt/vnfqmQXt5KlpuRcIvDAmhnn2E0t9BJ3SvB/SfLWhuOWNiNVZ+h28g4wlwUp00w95si43rZ3r6+fUIEdgOZbQAsyFRRvBR6dla8KCzRdslar7WS+a5HFb39peIAmG7uZTHVm17Czxju4m6bayz8e7J40DzqM0jr0bmv9PmPvk6y5z57HU8wdTDHeiUJvBMAM4+0CpoAZ4BPgJeAYEAHmgAUgAHiAj4AVAGORtwd4AVgC3gEmgBBwCPgMWANOAQ8AbwBHgHuAp4D3gLuARwoGmNUizF/j4yDC5BWM1kNvvlxFA8xikRrBxHIUhutFMBlgQoshhPphGAXe/OggKqqb2cibxwuEXjUcQjccxi5eFRL1fDSbKrUhy2CMb2aLyepkegDWsBwPlrVC0/kLHmeCBQ=='))
f=open('out','wb')
f.write(out)
f.close()
注意要在python2.7下来生成out文件,然后加上pyc后缀,然后还要用编辑器加上pyc文件头03 F3 0D 0A 97 32 18 5E 63,不然无法反编译。py和pychttps://www.cnblogs.com/blili/p/11799483.html
然后用uncompyle6 -o命令反编译,得到一个py文件,代码很长,是python的字节码。就直接上脚本了,可以去看大佬的wp,挺详细的。
import re
with open('1.txt','r') as f:
line = []
for i in range(950):
line.append(f.readline())
l1=[]
for i in line:
if 'LOAD_CONST' in i :
l1.append(re.findall(r'\d+',i))
print(l1)
s=''
for i in l1:
if i[1]!=0:
s +=chr(int(i[1]))
def ROT_TWO(l):
a =l.pop()
b =l.pop()
l.append(a)
l.append(b)
return l
def BINARY_ADD(l):
a =l.pop()
b =l.pop()
# print('{'+a,b,a+b,b+a+'}')
l.append(b+a)//注意这里必须是b+a,字符串的相加不能换换顺序。
return l
# s ="llaC em yP aht notriv lauhcamni !eac Ini npreterP tohty ntybdocese!!! ctihN{noy woc uoc naipmoa eldnur yP nnohttyb doceni euoy rb ria}!napwssro :dorWp gnssadrow...elP esa yrtaga .ni oD tonurbf etecro)= ."
l3=list(s)
l4=[]
j=0
for i in line:
if 'LOAD_CONST' in i:
l4.append(l3[j])
# print(l4)
j +=1
elif 'ROT_TWO' in i:
l4=ROT_TWO(l4)
elif 'BINARY_ADD' in i:
l4=BINARY_ADD(l4)
print(l4)
需要注意的是我的1.txt是改了’738 LOAD_CONST None’成为’738 LOAD_CONST 32’,也就是加了一个空格,不然脚本会出错。
得到flag:hitcon{Now you can compile and run Python bytecode in your brain!}
34.asong
这道题主要考了一个文件读写,然后根据that_girl这个文件构成一个索引表。
ida先看大致框架
然后再来看3个加密
然后写脚本
with open('out','rb') as f:
line=[]
line.append(f.read())
print(line)
s=list(line[0])
code=''
for i in s:
code +=hex(i)
code +=','
print(code)
with open('that_girl','r') as f:
str = ''
str = f.read()
str1=list(str.lower())
print(str1)
L1=[' ','\'', '_', 'a', 'c', 'b', 'e', 'd', 'g', 'f', 'i', 'h', 'k', 'm', 'l', 'o', 'n', 'p', 's', 'r', 'u', 't', 'w', 'v', 'y']
num=0
for i in L1:
num = 0
for j in range(len(str1)):
if i == str1[j]:
num+=1
print('%d: \'%c\',' %(num,i),end='')
print('\n')
l1=[0xec,0x29,0xe3,0x41,0xe1,0xf7,0xaa,0x1d,0x29,0xed,0x29,0x99,0x39,0xf3,0xb7,0xa9,0xe7,0xac,0x2b,0xb7,0xab,0x40,0x9f,0xa9,0x31,0x35,0x2c,0x29,0xef,0xa8,0x3d,0x4b,0xb0,0xe9,0xe1,0x68,0x7b,0x41]
l2=[]
mid=l1[37]&0x7
for i in range(0,len(l1)):
l2.append((mid<<5)|(l1[i]>>3))
mid=l1[i]&0x7
print(l2)
l3=[0]*38
table=[22, 0, 6, 2, 30, 24, 9, 1, 21, 7, 18, 10, 8, 12, 17, 23, 13, 4, 3, 14, 19, 11, 20, 16, 15, 5, 25, 36, 27, 28, 29, 37, 31, 32, 33, 26, 34, 35]
dict= {71: ' ',40: '\'',245: '_',104: 'a',15: 'c',30: 'b',169: 'e',29: 'd',38: 'g',19: 'f',60: 'i',67: 'h',20: 'k',28: 'm',39: 'l',165: 'o',118: 'n',26: 'p',51: 's',61: 'r',45: 'u',133: 't',34: 'w',7: 'v',62: 'y'}
j=0
while(table[j]):
l3[table[j]]=l2[j]
j=table[j]
l3[0]=133
print(l3)
flag=''
for i in l3:
flag+=dict[i]
print('QCTF{'+flag+'}')
得到QCTF{that_girl_saying_no_for_your_vindicate}
35.梅津美治郎
先ida静态分析一下
然后动调一下,有一个int3异常,然后调用了自己的一个异常处理函数
再进入第二个比较函数内部
开始写脚本
a='u1nnf2lg'
c=''
for i in a:
c+=chr(ord(i) ^ 2)
print('flag{r0b0RUlez!_'+c+'}')
得到flag{r0b0RUlez!_w3lld0ne}
36.echo-server
这道题就是对去花指令的考察吧
可能有点省略,多试试就行了
然后就可以看到代码了
然后不知道为什么我保存的文件,然后放到虚拟机,运行不了。就贴一个flag吧:F8C60EB40F66919A77C4BD88D45DEF4
37.re5-packed-movement
这道题有upx加壳,然后脱壳后不能反编译,但是如果细心的话可以发现一些特点
mov R2, 41h ; 'A'
这种指令每格一段距离就会出现,先全部搜索一下,直接alt+t
flag就出来了
得到ALEXCTF{M0Vfusc4t0r_w0rk5_l1ke_m4g1c}
38.What-does-this-button-do
ida打开时发现了这个,直接改后缀为.apk
然后jeb打开,找到关键代码
写脚本
list=[102, 108, 97, 103, 0x7B, 0x77, 52, 110, 110, 52, 0x5F, 106, 52, 0x72, 0x5F, 109, 0x79, 0x5F, 100, 51, 120, 0x7D]
flag=''
for i in list:
flag +=chr(i)
print(flag)
得到flag{w4nn4_j4r_my_d3x}
39.easyGo
之前一直想用去符号表的脚本,一直没成功,今天到处找了一些资料,看了看师傅们的博客终于弄好了,简单说一下过程。
- https://github.com/sibears/IDAGolangHelper.git下载脚本
- ida7.0,7.5都用不起,https://blog.csdn.net/qq_21063873/article/details/104335240改脚本后7.0就可用了。
- File–Script file—脚本,就可以发现函数名改了。
然后分析题目
脚本
import base64
import string
str1 = 'tGRBtXMZgD6ZhalBtCUTgWgZfnkTgqoNsnAVsmUYsGtCt9pEtDEYsql3'
string1 = "6789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print(base64.b64decode(str1.translate(str.maketrans(string1, string2))))
得到flag{92094daf-33c9-431e-a85a-8bfbd5df98ad}
40.2ex
mips架构,不得不说反编译后还是很难看。一个变表的base64。
脚本
#include<stdio.h>
int main(void)
{
int a[64]={ 0x40, 0x2C, 0x2E, 0x31, 0x66, 0x67, 0x76, 0x77, 0x23, 0x60,
0x2F, 0x32, 0x65, 0x68, 0x75, 0x78, 0x24, 0x7E, 0x22, 0x33,
0x64, 0x69, 0x74, 0x79, 0x25, 0x5F, 0x3B, 0x34, 0x63, 0x6A,
0x73, 0x7A, 0x5E, 0x2B, 0x7B, 0x35, 0x62, 0x6B, 0x72, 0x41,
0x26, 0x3D, 0x7D, 0x36, 0x61, 0x6C, 0x71, 0x42, 0x2A, 0x2D,
0x5B, 0x37, 0x30, 0x6D, 0x70, 0x43, 0x28, 0x29, 0x5D, 0x38,
0x39, 0x6E, 0x6F, 0x44};
int i;
for(i=0;i<64;i++)
{
printf("%c",a[i]);
}
}
//@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD
base64解密
import base64
base1 = '@,.1fgvw#`/2ehux$~"3dity%_;4cjsz^+{5bkrA&=}6alqB*-[70mpC()]89noD'
t = '_r-+_Cl5;vgq_pdme7#7eC0='//把第一个删了。
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
ans = ''
for i in t:
ans += base[base1.index(i)]
print(ans)
print(base64.b64decode(ans))
得到flag{change53233}
first
一道多线程md5加密,然后检验的方式也挺独特。通过动调更能理解一些变量的含义,和整个逻辑过程。可以用ida脚本findcrypt
分析整个过程
然后是创建了线程来进行md5加密,线程调用了6次,每次加密4个字符。
最后是输出真正的flag
解题思路就是先md5爆破得到输入的24个字符,然后异或得到flag
md5爆破脚本,好像md5爆破,密文必须是小写字母样,大写爆不出来。
import hashlib
list1=['4746bbbd02bb590f','BEAC2821ECE8FC5C','ad749265ca7503ef','4386B38FC12C4227','B03ECC45A7EC2DA7', 'BE3C5FFE121734E8']
for j in list1:
for a in range(48,128):
for b in range(48,128):
for c in range(48,128):
for d in range(48,128):
str = chr(a)+chr(b)+chr(c)+chr(d)
flag = hashlib.md5(str.encode('utf-8')).hexdigest()
if flag[0:16] == j.casefold():
print(str, end='')
//juhuhfenlapsiuerhjifdunu
然后异或解密,然后会发现一些数据不对(goodjobyougeytcnsflaj284),原因是爆破出来md5的字符是乱的,根据错误位置判断是第4组和第6组有问题,略微调一下顺序,并且还有一个点,就是v11的值还是要是原来的值,写出的脚本如下。
#include<stdio.h>
#include<string.h>
int main(void)
{
char str[25]="juhuhfenlapsiuerhjifdunu";
char flag[25];
int table[25]={0xFE, 0xE9, 0xF4, 0xE2, 0xF1, 0xFA, 0xF4, 0xE4, 0xF0,
0xE7, 0xE4, 0xE5, 0xE3, 0xF2, 0xF5, 0xEF, 0xE8, 0xFF, 0xF6,
0xF4, 0xFD, 0xB4, 0xA5, 0xB2};
int i,mid,num=0;
for(i=0;i<24;i++)
{
mid=str[i]+i;
num^=mid;
}
strcpy(str,"juhuhfenlapsdunuhjifiuer");
for(i=0;i<24;i++)
{
flag[i]=num ^ table[i] ^ str[i];
printf("%c",flag[i]);
}
}
MyDriver2-397
驱动逆向
#include<stdio.h>
#include<windows.h>
int main()
{
unsigned int a[32]={ 0x5C6E1395, 0x5C5813A2, 0x5C5413B3, 0x5C541388, 0x5C57139A, 0x5C5013A9, 0x5C6E13A2, 0x5C0213F7, 0x5C1F13F6, 0x5C4913B1, 0x000013B1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
int i,j;
char m[128]={0x50,0x00,0x5F,0x00,0x67,0x00,0x69,0x00,0x76,0x00,0x65,0x00,0x4D,0x00,0x65,0x00,0x5F,0x00,0x66,0x00,0x6C,0x00,0x61,0x00,0x67,0x00,0x5F,0x00,0x32,0x00,0x33,0x00,0x33,0x00,0x2E,0x00,0x74,0x00,0x78,0x00,0x74,0x00,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C,0xC5,0x13,0x31,0x5C};
char n[128]={ 0x70, 0x74, 0x37, 0x65, 0x47, 0x66, 0x05, 0x61, 0x11, 0x20,
0x0C, 0x73, 0x6D, 0x41, 0x3A, 0x73, 0x36, 0x6D, 0x16, 0x6C,
0x09, 0x5F, 0x28, 0x6E, 0x0B, 0x69, 0x31, 0x65, 0x6D, 0x68,
0x5C, 0x6F, 0x58, 0x5F, 0x6A, 0x72, 0x02, 0x00, 0x78, 0x00,
0x74, 0x00, 0x50, 0x00, 0x5F, 0x00, 0x67, 0x00, 0x69, 0x00,
0x76, 0x00, 0x65, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x5F, 0x00,
0x66, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x67, 0x00, 0x5F, 0x00,
0x32, 0x00, 0x33, 0x00, 0x33, 0x00, 0x2E, 0x00, 0x74, 0x00,
0x78, 0x00, 0x74, 0x00, 0x50, 0x00, 0x5F, 0x00, 0x67, 0x00,
0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x4D, 0x00, 0x65, 0x00,
0x5F, 0x00, 0x66, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x67, 0x00,
0x5F, 0x00, 0x32, 0x00, 0x33, 0x00, 0x33, 0x00, 0x2E, 0x00,
0x74, 0x00, 0x78, 0x00, 0x74, 0x00, 0x50, 0x00};
for(i=0;i<32;i++)//得到m
{
a[i]=(a[i]^1546720197);
printf("0x%02X,0x%02X,0x%02X,0x%02X,", *((char*)&a[i])&0xff,*((char*)&a[i] + 1)&0xff,*((char*)&a[i] +2)&0xff,*((char*)&a[i]+3)&0xff);
}
for(int i=0;i<128;i++)
{
n[i]^=m[i%42];
}
printf("%s",n);
}
xx
大致流程
输入flag,对前4位进行检验
填充key,然后xxtea加密
然后换位,异或加密
最后比较
所以解题思路就是,先异或解密,换位,再xxtea解密
exp
#include<stdio.h>
int main(void)
{
int code[24]={0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B,
0x20, 0x20, 0x91, 0xF7, 0x02, 0x35, 0x23, 0x18, 0x02, 0xC8,
0xE7, 0x56, 0x56, 0xFA};
int i,j,a;
for(i=23;i>0;i--)
{
a=i/3-1;
if(i/3>0)
{
do
{
code[i]^=code[a--];
}
while(a>=0);
}
}
for(i=0;i<24;i++)
{
printf("%X ",code[i]);
}
printf("\n0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X,0x%X",code[1],code[3],code[0],code[2],code[5],code[7],code[4],code[6],code[9],code[11],code[8],code[10],code[13],code[15],code[12],code[14],code[17],code[19],code[16],code[18],code[21],code[23],code[20],code[22]);
}
//0xBC,0xA5,0xCE,0x40,0xF4,0xB2,0xB2,0xE7,0xA9,0x12,0x9D,0x12,0xAE,0x10,0xC8,0x5B,0x3D,0xD7,0x6,0x1D,0xDC,0x70,0xF8,0xDC
xxtea解密
#include<stdio.h>
void decrypt(unsigned int *code ,unsigned int *key ,unsigned int n)
{
unsigned int next,end,sum;
unsigned int rounds,e,delta=0x9e3779b9;
int i;
rounds=6+52/n;
sum=rounds*delta& 0xffffffff;
next=code[0];//设置next为code的第一个
do
{
e=(sum>>2)&3;
for(i=n-1;i>0;i--)//解密最后一个到第二个
{
end=code[i-1];
code[i]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ))& 0xffffffff;
next=code[i];
}
end=code[n-1];
code[0]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) +(key[i&3^e]^end) ))& 0xffffffff;
next=code[0];
sum=(sum-delta)& 0xffffffff;
}while(--rounds);
}
int main()
{
unsigned key[4]={0x67616c66,0,0,0};
unsigned int n=6;
int i;
unsigned int code[6]={0x40cea5bc,0xe7b2b2f4,0x129d12a9,0x5bc810ae,0x1d06d73d,0xdcf870dc};
decrypt(code,key,n);
for(i=0;i<5;i++)
{
// printf("%x",code[i]);
printf("%c%c%c%c", *((char*)&code[i])&0xff,*((char*)&code[i] + 1)&0xff,*((char*)&code[i] + 2)&0xff,*((char*)&code[i]+3)&0xff);
}
}
//flag{CXX_and_++tea}
Junk_Instruction
这道题的关键点就是MFC的check跳到了哪里,和去花指令(感觉有点难),或者动调找关键点和对比部分。然后就是带不同的数据去试。
先用xspy软件得到check后跳到了哪里,如下。
加密过程就是,flag去掉前5个和最后一个,然后倒序,然后rc4加密。
具体过程就是动调了,主要看xor和cmp,然后cmp数据的时候,是从最后一个开始比较的,也没什么关系。
exp,注意密文里面有个0,会导致脚本的len出问题,所以直接将len=32
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;
/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;//做一道re的题时这里就改为了,s[i]=256-i
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[i]和s[j]
s[j] = tmp;
}
}
/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = (Data[k]^s[t]);
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
char key[256] = "qwertyuiop" ;
char pData[512] = {0x5b,0xd6,0xd0,0x26,0xc8,0xdd,0x19,0x7e,0x6e,0x3e,0xcb,0x16,0x91,0x7d,0xff,0xaf,0xdd,0x76,0x64,0xb0,0xf7,0xe5,0x89,0x57,0x82,0x9f,0xc,0x0,0x9e,0xd0,0x45,0xfa};
unsigned long len = 32;
int i;
printf("key=%s,length=%d\n\n", key, strlen(key));
rc4_init(s, (unsigned char*)key, strlen(key));//已经完成了初始化
for (i = 0; i<256; i++)//用s2[i]暂时保留经过初始化的s[i],很重要的!!!
{
s2[i] = s[i];
}
//rc4_init(s,(unsignedchar*)key,strlen(key));//初始化密钥
rc4_crypt(s2, (unsigned char*)pData, len);//解密
printf("flag{");
for(i=31;i>0;i--)
{
printf("%c", pData[i]);
}
printf("}");
return 0;
}
//flag{973387a11fa3f724d74802857d3e052}
别人的python版本
d = [0x5B, 0xD6, 0xD0, 0x26, 0xC8, 0xDD, 0x19, 126, 110, 62, -53, 22, -111, 125, -1, -81, -35, 118, 100, -80, -9, -27, -119, 87, -126, -97, 12, 0, -98, -48, 69, -6]
import sys, os, hashlib, time, base64
def rc4(plain, key):
box = list(range(256))
j = 0
for i in range(256):
j = (j + box[i] + ord(key[i % len(key)])) % 256
box[i], box[j] = box[j], box[i]
print(box)
# print(type(box)) #for_test
# return box
res = []
i = j = 0
for s in plain:
i = (i + 1) % 256
j = (j + box[i]) % 256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j]) % 256
k = box[t]
res.append(chr((s ^ k)&0xff))
return res
r = rc4(d, "qwertyuiop")
r = [(i) for i in r]
print("".join(r[::-1]))
icekey
C#程序,用了一个ice算法,程序中自带加密解密,所以动调直接调用程序里面的解密函数解密密文就行了。
evil
这道题,大概看了下,做不了了,附件x.jpg都没给了,(后来在吾爱论坛找到了图片),但整个流程还是值得分析一波的。
脱壳就不说了,手动脱,esp定律。
然后就进入主函数分析。
主要分析,那个sub_401370函数,这个函数就不应该执行。
后来再一分析,自毁进程的原因找到了,这也解释了为什么要复制自己到一个临时的文件目录。
这里我假设
Buffer=C:\Users\Temp\a.exe
Filename=D:\a.exe
CommandLine=C:\Users\Temp\a.exe "D:\a.exe"
然后根据https://www.cnblogs.com/weekbo/p/9054488.html,https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa中讲述createprocess()api的第一个参数
所以说创建的进程实际上是我们复制的那个exe文件,也就是C:\Users\Temp\a.exe。
这就导致了我们会在新进程中的这个位置跳出来
接下来就进入了,sub_401620这个函数,进去看看。
所以,原文件就被删除了。
然后要做这个题就要绕过前面的函数,直接跳到,从网站下载x.jpg和读取jpg的那个函数开始。
后头在吾爱破解论坛上找到了x.jpg,所以就可以做了,但是不知道为什么用动调来做,老是调到一个地方就调不走了。所以还是静态解吧。
解密函数
#include<stdio.h>
unsigned __int64 a=0x4A8754F5745174;
unsigned char key[256]={};
void getkey()
{
int i;
char v4[8]={0};
for(i=0;i<8;i++)
{
v4[i]=a;
a>>=8;
}
for(i=0;i<256;i++)
{
key[i]=(i+v4[i%8])&0xff;
}
}
decrypt(unsigned char v[])
{
int i,x=0,y=0;
unsigned int v4;
unsigned int v5;
for(i=0;i<326;i++)
{
x=(x+1)%256;
y=(key[x]+y)%256;
v4 = key[x];
v5 = key[y];
key[x] = v5;
key[y] = v4;
v[i]=(key[(v4+v5)%256]^v[i]^i)&0xff;
}
}
int main(void)
{
FILE *fp;
unsigned char v[326]={0};
unsigned char flag[100]={0};
int i,j,k=0;
fp=fopen("x.jpg","rb");
fread(&v, 1, 326, fp);
getkey();
decrypt(v);
for(i=0;i<326;i++)
{
if(v[i]==0x68)
{
for(j=1;j<5;j++)
{
flag[k+j]=v[i+j];
printf("%c",flag[k+j]);
k+=4;
}
}
}
}//嶯靗l A32.duserX ratsCongcomXing.chuxuxhddidiade@d9e97173d4aed69bb1c4adacc49bTF-c DDCKey:
解密得到的是shellcode,也就是机器码,我们提数据来得到flag
#include<stdio.h>
#include<string.h>
int main(void)
{
char flag[]="com ing.chuxuxhddidiade@d9e97173d4aed69bb1c4adacc49bTF-c DDCKey:";
int i;
int len;
len=strlen(flag);
// printf("%d",len);
for(i=len-1;i>0;i-=4)
{
printf("%c%c%c%c",flag[i-3],flag[i-2],flag[i-1],flag[i]);
}
}
//Key: DDCTF-cc49badacb1c4d69bd4ae7173d9e9ade@didiuxhdchuxing.com
为了懒得提数据,我们也可以直接将解密数据放到xdbg的空白处,然后开头开始执行。
childRE
考点是一个数据结构二叉树的变换顺序,没学数据结构,但是它的变换顺序是一定的,所以可以带值去找出变换顺序,然后就是UnDecorateSymbolName这个函数,函数反修饰指定已修饰的 C++ 符号名。
分析总流程
所以先求outputString。
脚本1
//abcdefghijklmnopqrstuvwxyz12345
#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(void)
{
char table[]="1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'ASDFGHJKL:\"ZXCVBNM<>?zxcvbnm,./";
char table1[]="(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&";
char table2[]="55565653255552225565565555243466334653663544426565555525555222";
int v1[62],v2[62],code[62];
int i,j;
// int len=strlen(table);
// printf("%d",len);
for(i=0;i<0x3E;i++)
{
for(j=0;j<=90;j++)
{
if(table1[i]==table[j])
{
v1[i]=j;
break;
}
}
}
for(i=0;i<0x3E;i++)
{
for(j=0;j<=90;j++)
{
if(table2[i]==table[j])
{
v2[i]=j;
break;
}
}
}
for(i=0;i<62;i++)
{
code[i]=v2[i]*23+v1[i];
printf("%c",code[i]);
}
}
//private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
手动还原回去,得到?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z。这个知识点《加密与解密》第4章讲了一小部分,然后这个师傅写的比较详细https://www.freesion.com/article/6515734088/,然后进行位置变换。
脚本2,a数组是我自己试的数据,b数组是动调得到的数据。
#include<stdio.h>
int main()
{
int a[31]={ 0x70, 0x71, 0x68, 0x72, 0x73, 0x69, 0x64, 0x74, 0x75, 0x6A,
0x76, 0x77, 0x6B, 0x65, 0x62, 0x78, 0x79, 0x6C, 0x7A, 0x31,
0x6D, 0x66, 0x32, 0x33, 0x6E, 0x34, 0x35, 0x6F, 0x67, 0x63,
0x61};
int b[31]={0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x31, 0x32, 0x33, 0x34,
0x35};
int c[31];
char str[]="?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z";
int i,j;
for(i=0;i<31;i++)
{
for(j=0;j<31;j++)
{
if(b[i]==a[j])
{
c[i]=j;
// printf("%d ",c[i]);
}
}
}
for(i=0;i<31;i++)
{
printf("%c",str[c[i]]);
}
}
//Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP
脚本3,md5加密
import hashlib
str='Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP'
flag = hashlib.md5(str.encode('utf-8')).hexdigest()
print('flag{'+flag+'}')
//flag{63b148e750fed3a33419168ac58083f5}
RE-Crc-300
一个窗口类的程序,正好大致看了看crc,嘻嘻。
进入到DialogFunc函数,可以看到很清晰的结构。
进入CRC检验函数,查看逻辑
所以分奇,偶爆破就行。
exp,本来想写个python的,但爆不出来,还是用c吧
#include<stdio.h>
int dword_AAFD60[]={0x00000000,0x00000000,0x77073096,0xF26B8303,0xEE0E612C,0xE13B70F7,0x990951BA,0x1350F3F4,0x076DC419,0xC79A971F,0x706AF48F,0x35F1141C,0xE963A535,0x26A1E7E8,0x9E6495A3,0xD4CA64EB,0x0EDB8832,0x8AD958CF,0x79DCB8A4,0x78B2DBCC,0xE0D5E91E,0x6BE22838,0x97D2D988,0x9989AB3B,0x09B64C2B,0x4D43CFD0,0x7EB17CBD,0xBF284CD3,0xE7B82D07,0xAC78BF27,0x90BF1D91,0x5E133C24,0x1DB71064,0x105EC76F,0x6AB020F2,0xE235446C,0xF3B97148,0xF165B798,0x84BE41DE,0x030E349B,0x1ADAD47D,0xD7C45070,0x6DDDE4EB,0x25AFD373,0xF4D4B551,0x36FF2087,0x83D385C7,0xC494A384,0x136C9856,0x9A879FA0,0x646BA8C0,0x68EC1CA3,0xFD62F97A,0x7BBCEF57,0x8A65C9EC,0x89D76C54,0x14015C4F,0x5D1D08BF,0x63066CD9,0xAF768BBC,0xFA0F3D63,0xBC267848,0x8D080DF5,0x4E4DFB4B,0x3B6E20C8,0x20BD8EDE,0x4C69105E,0xD2D60DDD,0xD56041E4,0xC186FE29,0xA2677172,0x33ED7D2A,0x3C03E4D1,0xE72719C1,0x4B04D447,0x154C9AC2,0xD20D85FD,0x061C6936,0xA50AB56B,0xF477EA35,0x35B5A8FA,0xAA64D611,0x42B2986C,0x580F5512,0xDBBBC9D6,0x4B5FA6E6,0xACBCF940,0xB93425E5,0x32D86CE3,0x6DFE410E,0x45DF5C75,0x9F95C20D,0xDCD60DCF,0x8CC531F9,0xABD13D59,0x7EAEB2FA,0x26D930AC,0x30E349B1,0x51DE003A,0xC288CAB2,0xC8D75180,0xD1D83946,0xBFD06116,0x23B3BA45,0x21B4F4B5,0xF779DEAE,0x56B3C423,0x05125DAD,0xCFBA9599,0x1642AE59,0xB8BDA50F,0xE4292D5A,0x2802B89E,0xBA3A117E,0x5F058808,0x4851927D,0xC60CD9B2,0x5B016189,0xB10BE924,0xA96AE28A,0x2F6F7C87,0x7DA08661,0x58684C11,0x8FCB0562,0xC1611DAB,0x9C9BF696,0xB6662D3D,0x6EF07595,0x76DC4190,0x417B1DBC,0x01DB7106,0xB3109EBF,0x98D220BC,0xA0406D4B,0xEFD5102A,0x522BEE48,0x71B18589,0x86E18AA3,0x06B6B51F,0x748A09A0,0x9FBFE4A5,0x67DAFA54,0xE8B8D433,0x95B17957,0x7807C9A2,0xCBA24573,0x0F00F934,0x39C9C670,0x9609A88E,0x2A993584,0xE10E9818,0xD8F2B687,0x7F6A0DBB,0x0C38D26C,0x086D3D2D,0xFE53516F,0x91646C97,0xED03A29B,0xE6635C01,0x1F682198,0x6B6B51F4,0x5125DAD3,0x1C6C6162,0xA34E59D0,0x856530D8,0xB01EAA24,0xF262004E,0x42752927,0x6C0695ED,0x96BF4DCC,0x1B01A57B,0x64D4CECF,0x8208F4C1,0x77843D3B,0xF50FC457,0x85EFBE38,0x65B0D9C6,0xDBFC821C,0x12B7E950,0x2997011F,0x8BBEB8EA,0x3AC7F2EB,0xFCB9887C,0xC8AC71E8,0x62DD1DDF,0x1C661503,0x15DA2D49,0xEE0D9600,0x8CD37CF3,0xFD5D65F4,0xFBD44C65,0x0F36E6F7,0x4DB26158,0x61C69362,0x3AB551CE,0x93AD1061,0xA3BC0074,0x80FDE395,0xD4BB30E2,0x72966096,0x4ADFA541,0xA65C047D,0x3DD895D7,0x5437877E,0xA4D1C46D,0x4767748A,0xD3D6F4FB,0xB50CF789,0x4369E96A,0xEB1FCBAD,0x346ED9FC,0x197448AE,0xAD678846,0x0A24BB5A,0xDA60B8D0,0xF84F3859,0x44042D73,0x2C855CB2,0x33031DE5,0xDEEEDFB1,0xAA0A4C5F,0xCDBE2C45,0xDD0D7CC9,0x3FD5AF46,0x5005713C,0x7198540D,0x270241AA,0x83F3D70E,0xBE0B1010,0x90A324FA,0xC90C2086,0x62C8A7F9,0x5768B525,0xB602C312,0x206F85B3,0x44694011,0xB966D409,0x5739B3E5,0xCE61E49F,0xA55230E6,0x5EDEF90E,0xFB410CC2,0x29D9C998,0x092A8FC1,0xB0D09822,0x1A7A7C35,0xC7D7A8B4,0xE811FF36,0x59B33D17,0x3CDB9BDD,0x2EB40D81,0xCEB018DE,0xB7BD5C3B,0xDDE0EB2A,0xC0BA6CAD,0x2F8B6829,0xEDB88320,0x82F63B78,0x9ABFB3B6,0x709DB87B,0x03B6E20C,0x63CD4B8F,0x74B1D29A,0x91A6C88C,0xEAD54739,0x456CAC67,0x9DD277AF,0xB7072F64,0x04DB2615,0xA457DC90,0x73DC1683,0x563C5F93,0xE3630B12,0x082F63B7,0x94643B84,0xFA44E0B4,0x0D6D6A3E,0xE9141340,0x7A6A5AA8,0x1B7F9043,0xE40ECF0B,0xCFB5F4A8,0x9309FF9D,0x3DDE77AB,0x0A00AE27,0x2E8E845F,0x7D079EB1,0xDCE5075C,0xF00F9344,0x92A8FC17,0x8708A3D2,0x60C37F14,0x1E01F268,0x73938CE0,0x6906C2FE,0x81F80FE3,0xF762575D,0x55326B08,0x806567CB,0xA759E80B,0x196C3671,0xB4091BFF,0x6E6B06E7,0x466298FC,0xFED41B76,0x1871A4D8,0x89D32BE0,0xEA1A27DB,0x10DA7A5A,0xF94AD42F,0x67DD4ACC,0x0B21572C,0xF9B9DF6F,0xDFEB33C7,0x8EBEEFF9,0x2D80B0C4,0x17B7BE43,0x3ED04330,0x60B08ED5,0xCCBBC033,0xD6D6A3E8,0xA24BB5A6,0xA1D1937E,0x502036A5,0x38D8C2C4,0x4370C551,0x4FDFF252,0xB11B4652,0xD1BB67F1,0x65D122B9,0xA6BC5767,0x97BAA1BA,0x3FB506DD,0x84EA524E,0x48B2364B,0x7681D14D,0xD80D2BDA,0x2892ED69,0xAF0A1B4C,0xDAF96E6A,0x36034AF6,0xC9A99D9E,0x41047A60,0x3BC21E9D,0xDF60EFC3,0xEF087A76,0xA867DF55,0x1D63F975,0x316E8EEF,0x0E330A81,0x4669BE79,0xFC588982,0xCB61B38C,0xB21572C9,0xBC66831A,0x407EF1CA,0x256FD2A0,0x532E023E,0x5268E236,0xA145813D,0xCC0C7795,0x758FE5D6,0xBB0B4703,0x87E466D5,0x220216B9,0x94B49521,0x5505262F,0x66DF1622,0xC5BA3BBE,0x38CC2A06,0xB2BD0B28,0xCAA7A905,0x2BB45A92,0xD9F75AF1,0x5CB36A04,0x2B9CD9F2,0xC2D7FFA7,0xFF56BD19,0xB5D0CF31,0x0D3D3E1A,0x2CD99E8B,0x1E6DCDEE,0x5BDEAE1D,0xEC064EED,0x9B64C2B0,0xC38D26C4,0xEC63F226,0x31E6A5C7,0x756AA39C,0x22B65633,0x026D930A,0xD0DDD530,0x9C0906A9,0x0417B1DB,0xEB0E363F,0xF67C32D8,0x72076785,0xE52CC12C,0x05005713,0x1747422F,0x95BF4A82,0x49547E0B,0xE2B87A14,0xBB3FFD08,0x7BB12BAE,0xA86F0EFC,0x0CB61B38,0x5A048DFF,0x92D28E9B,0x8ECEE914,0xE5D5BE0D,0x7CA56A17,0x7CDCEFB7,0x6FF599E3,0x0BDBDF21,0x9D9E1AE0,0x86D3D2D4,0xD3D3E1AB,0xF1D4E242,0x21B862A8,0x68DDB3F8,0x32E8915C,0x1FDA836E,0xC083125F,0x81BE16CD,0x144976B4,0xF6B9265B,0xE622F5B7,0x6FB077E1,0xF5720643,0x18B74777,0x07198540,0x88085AE6,0x590AB964,0xFF0F6A70,0xAB613A67,0x66063BCA,0xB831C993,0x11010B5C,0x4A5A4A90,0x8F659EFF,0x9E902E7B,0xF862AE69,0x6CFBAD78,0x616BFFD3,0x7FAB5E8C,0x166CCF45,0x8DC0DD8F,0xA00AE278,0xE330A81A,0xD70DD2EE,0x115B2B19,0x4E048354,0x020BD8ED,0x3903B3C2,0xF0605BEE,0xA7672661,0x24AA3F05,0xD06016F7,0xD6C1BC06,0x4969474D,0xC5914FF2,0x3E6E77DB,0x37FACCF1,0xAED16A4A,0x69E9F0D5,0xD9D65ADC,0x9B8273D6,0x40DF0B66,0x88D28022,0x37D83BF0,0x7AB90321,0xA9BCAE53,0xAE7367CA,0xDEBB9EC5,0x5C18E4C9,0x47B2CF7F,0x4F48173D,0x30B5FFE9,0xBD23943E,0xBDBDF21C,0xF36E6F75,0xCABAC28A,0x0105EC76,0x53B39330,0x12551F82,0x24B4A3A6,0xE03E9C81,0xBAD03605,0x34F4F86A,0xCDD70693,0xC69F7B69,0x54DE5729,0xD5CF889D,0x23D967BF,0x27A40B9E,0xB3667A2E,0x79B737BA,0xC4614AB8,0x8BDCB4B9,0x5D681B02,0x988C474D,0x2A6F2B94,0x6AE7C44E,0xB40BBE37,0xBE2DA0A5,0xC30C8EA1,0x4C4623A6,0x5A05DF1B,0x5F16D052,0x2D02EF8D,0xAD7D5351};
void check1(int a,int b,int c,int d,int e)
{
unsigned int v6=-1;
int i;
char table[]={0x53, 0x6F, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x61, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x64, 0x69, 0x66,
0x66, 0x63, 0x75, 0x6C, 0x74, 0x20, 0x70, 0x72, 0x6F, 0x62,
0x6C, 0x65, 0x6D, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6F, 0x75,
0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x76, 0x65,
0x72, 0x79, 0x20, 0x67, 0x6F, 0x6F, 0x64, 0x20, 0x63, 0x6F,
0x6D, 0x70, 0x75, 0x74, 0x65, 0x2E, 0x42, 0x75, 0x74, 0x20,
0x69, 0x66, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x64, 0x6F, 0x20,
0x6E, 0x6F, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61,
0x20, 0x67, 0x6F, 0x6F, 0x64, 0x20, 0x63, 0x6F, 0x6D, 0x70,
0x75, 0x74, 0x65, 0x72, 0x2E, 0x49, 0x74, 0x20, 0x73, 0x65,
0x65, 0x6D, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x54,
0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x6C, 0x65,
0x6D, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x74, 0x61, 0x6B,
0x65, 0x20, 0x61, 0x20, 0x6C, 0x6F, 0x74, 0x20, 0x6F, 0x66,
0x20, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x42, 0x75, 0x74, 0x20,
0x6E, 0x6F, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x20,
0x69, 0x73, 0x20, 0x69, 0x6D, 0x70, 0x6F, 0x73, 0x73, 0x69,
0x62, 0x6C, 0x65, 0x2E, 0x53, 0x6F, 0x20, 0x6A, 0x75, 0x73,
0x74, 0x20, 0x74, 0x72, 0x79, 0x20, 0x69, 0x74, 0x21, 0x21,
0x53, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x73,
0x2C, 0x54, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x67,
0x20, 0x77, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6D, 0x20, 0x69,
0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x65, 0x61, 0x6C,
0x6C, 0x20, 0x5B, 0x5D, 0x5B, 0x5D, 0x28, 0x29, 0x28, 0x29,
0x3C, 0x3E, 0x3C, 0x3E, 0x2E, 0x2E, 0x00};
table[0x00]=a;
table[0x22]=b;
table[0x44]=c;
table[0x66]=d;
table[0x88]=e;
for(i=0;i<256;i+=2)
{
v6 = dword_AAFD60[2 * (unsigned __int8)(v6 ^ table[i])] ^ (v6 >> 8);
}
if(~v6==0xBA56C4F9)
{
printf("%c%c%c%c%c ",a,b,c,d,e);
}
}
void check2(int a,int b,int c,int d,int e)
{
unsigned int v4=-1;
int i;
char table[]={0x53, 0x6F, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
0x20, 0x61, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x64, 0x69, 0x66,
0x66, 0x63, 0x75, 0x6C, 0x74, 0x20, 0x70, 0x72, 0x6F, 0x62,
0x6C, 0x65, 0x6D, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6F, 0x75,
0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20, 0x76, 0x65,
0x72, 0x79, 0x20, 0x67, 0x6F, 0x6F, 0x64, 0x20, 0x63, 0x6F,
0x6D, 0x70, 0x75, 0x74, 0x65, 0x2E, 0x42, 0x75, 0x74, 0x20,
0x69, 0x66, 0x20, 0x79, 0x6F, 0x75, 0x20, 0x64, 0x6F, 0x20,
0x6E, 0x6F, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61,
0x20, 0x67, 0x6F, 0x6F, 0x64, 0x20, 0x63, 0x6F, 0x6D, 0x70,
0x75, 0x74, 0x65, 0x72, 0x2E, 0x49, 0x74, 0x20, 0x73, 0x65,
0x65, 0x6D, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x54,
0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x62, 0x6C, 0x65,
0x6D, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x74, 0x61, 0x6B,
0x65, 0x20, 0x61, 0x20, 0x6C, 0x6F, 0x74, 0x20, 0x6F, 0x66,
0x20, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x42, 0x75, 0x74, 0x20,
0x6E, 0x6F, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x20,
0x69, 0x73, 0x20, 0x69, 0x6D, 0x70, 0x6F, 0x73, 0x73, 0x69,
0x62, 0x6C, 0x65, 0x2E, 0x53, 0x6F, 0x20, 0x6A, 0x75, 0x73,
0x74, 0x20, 0x74, 0x72, 0x79, 0x20, 0x69, 0x74, 0x21, 0x21,
0x53, 0x6F, 0x6D, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x73,
0x2C, 0x54, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x67,
0x20, 0x77, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6D, 0x20, 0x69,
0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x65, 0x61, 0x6C,
0x6C, 0x20, 0x5B, 0x5D, 0x5B, 0x5D, 0x28, 0x29, 0x28, 0x29,
0x3C, 0x3E, 0x3C, 0x3E, 0x2E, 0x2E, 0x00};
table[0x11]=a;
table[0x33]=b;
table[0x55]=c;
table[0x77]=d;
table[0x99]=e;
for(i=0;i<256;i+=2)
{
v4 = dword_AAFD60[2 * (unsigned __int8)(v4 ^ table[i+1]) +1] ^ (v4 >> 8);
}
if(~v4==0xE89BA203)
{
printf("%c%c%c%c%c ",a,b,c,d,e);
}
}
int main()
{
int a,b,c,d,e;
for(a=30;a<=128;a++)
{
for(b=30;b<128;b++)
{
for(c=30;c<128;c++)
{
for(d=30;d<128;d++)
{
for(e=30;e<128;e++)
{
check1(a,b,c,d,e);
check2(a,b,c,d,e);
}
}
}
}
}
}
//I sac
//ti r
爆破时间比较久。爆出来,我发现多解还挺多,哈哈哈
将正确的拼接一下得到hctf{It is a crc program!}
polyre
ida打开,可以看到用了控制流平坦化。
看了wp,说要用脚本处理一下,https://github.com/cq674350529/deflat下载deflat.py处理,这里使用这个脚本还是花费了一些时间来配环境,网上也没有具体教程,这里就说详细点。
首先安装angr,https://blog.csdn.net/weixin_45055269/article/details/105176185,注意升级pip。
pip3 install virtualenv//安装virtualenv
mkdir angr
cd angr
source venv/bin/activate//进入对应的环境
pip3 install -i http://pypi.douban.com/simple --trusted-host pypi.douban.com angr//安装angr
deactive//退出当前venv环境
每次使用的时候要先进入这个环境(source venv/bin/activate)。我们创建这个angr文件夹里面,就有一个python3.8的环境,里面已经有了angr,但是要用deflat.py这个脚本还少了am_graph.py,找了许久,结果就在GitHub那个项目里面,放到python3.8的site-packages。
然后就可以用了,嘻嘻,这个python3是angr中的python3.8。
完成后,就会生成一个polyre_recovered文件,再次用ida打开就会看到代码好看多了。
这里正式来分析逻辑,其中的while()都不用管,用来干扰分析的,真正处理部分如下。
我用c写的类似过程。
#include<stdio.h>
int main()
{
int i;
for(i=0;i<6;i++)
{
for(j=0;j<64;j++)
{
if(flag[i]>=0)
{
flag[i]=flag[i]<<1;
}
else
{
flag[i]=flag[i]<<1;
flag[i]=flag[i]^0xB0004B7679FA26B3;
}
}
}
}
比较部分
然后要解的话有两个思路,一个用z3,z3yyds
from z3 import *
code=[0x0BC8FF26D43536296,0x520100780530EE16,0x4DC0B5EA935F08EC,0x342B90AFD853F450,
0x8B250EBCAA2C3681,0x55759F81A2C68AE4]
s = Solver()
flag = [BitVec('flag[%d]' % i, 64) for i in range(6)]
for i in range(6):
for j in range(64):
flag[i]=If(flag[i]>=0,flag[i]*2,(flag[i]*2)^0xB0004B7679FA26B3)//z3特有的If
s.add(flag[i]==code[i])
print(s.check())
m=s.model()
print(m)
//[flag[4] = 7363777037631763767,
flag[3] = 3835203404393046370,
flag[1] = 7148951143638579506,
flag[2] = 3257850080642543666,
flag[0] = 7378644943136451686,
flag[5] = 32056]
整理输出
code=[7378644943136451686,7148951143638579506,3257850080642543666,
3835203404393046370,7363777037631763767,32056]
flag=[0]*6
def print_flag(s):
str=''
for i in range(0,len(s),2):
a=int(s[i:i+2],16)
str+=chr(a)
print(str[::-1],end='')
for i in range(6):
flag[i]=(hex(code[i]).replace('0x',''))
print_flag(flag[i])
//flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}
方法二,逆向反解
思路:细心观察,可以发现,如果数大于0,那么它的第一位一定是0,如果数据小于0,那么第一位是1。且不同的处理方式,也会导致得到的数要么是奇数,要么是偶数,我们就可以根据是奇数还是偶数来写反解脚本。还可以用一个简单的数据来试验一下,然后看看反过来怎么解,用一个byte大小的数就行了。
if(flag[i]>=0)//第一位是0
{
flag[i]=flag[i]<<1;//左位移1位,得到的最后一位是0,是偶数。
}
else//第一位是1
{
flag[i]=flag[i]<<1;
flag[i]=flag[i]^0xB0004B7679FA26B3;//左移1位加上异或,得到最后一位是1,是奇数。
}
脚本
#include<stdio.h>
unsigned __int64 code[6]={0x0BC8FF26D43536296,0x520100780530EE16,0x4DC0B5EA935F08EC,0x342B90AFD853F450,
0x8B250EBCAA2C3681,0x55759F81A2C68AE4};//注意是unsigned __int64,因为我们处理时,是根据奇偶,不需要区分有符号还是无符号。
int main()
{
signed __int64 flag[6];
int i,j;
char ch;
for(i=0;i<6;i++)
{
for(j=0;j<64;j++)
{
if(code[i]&0x1==1)//如果是奇数
{
code[i]=(code[i]^0xB0004B7679FA26B3);
code[i]=(code[i]>>1);
code[i]=code[i]|0x8000000000000000;//一定要确保第一位是1,因为正向加密时,这个数是负数。
}
else//如果是偶数
{
code[i]=(code[i]>>1);//右移1位,第一位变为0,这时候不需要处理第一位,因为正向加密时,第一位一定是0,也就是这个数是正数。
}
}
}
//输出
for(i=0;i<6;i++)
{
for(j=0;j<8;j++)
{
ch=code[i]&0xff;
printf("%c",ch);
code[i]=code[i]>>8;
}
}
}
//flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}
seven
驱动迷宫题,注意键盘码就行https://blog.csdn.net/wguoyong/article/details/5678511。
打印出迷宫,
#include<stdio.h>
int main(void)
{
int a[14][16]={ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x6F, 0x2E, 0x2E, 0x2E,
0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2E, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2E, 0x2E, 0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2E, 0x2E, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2E, 0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2E, 0x2E, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2E, 0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2E, 0x2E, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2E, 0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2E, 0x2E, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2E, 0x2E, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x37, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x2A, 0x2A, 0x2A, 0x2A };
int i,j;
for(i=0;i<14;i++)
{
for(j=0;j<15;j++)
{
printf("%c",a[i][j]);
}
printf("\n");
}
}
***************
o..............
**************.
************...
***********..**
**********..***
*********..****
********..*****
*******..******
******..*******
*****..********
****..*********
****7**********
***************
//hctf{ddddddddddddddssaasasasasasasasasas}
Reverse
一个windows逆向,考点比较简单。
主函数逻辑
进入处理函数
写出脚本
#include<stdio.h>
unsigned char sub_401460(unsigned char a1[], int a2)
{
char v2; // al
char v3; // cl
int v4; // eax
int v5; // edx
v2 = a1[a2];
v3 = a1[a2+1];
if ( (unsigned __int8)(v2 - 48) > 9u )
v2 -= 55;
v4 = v2 & 0xF;
v5 = (v3 - 55) & 0xF;
if ( (unsigned __int8)(v3 - 48) <= 9u )
v5 = v3 & 0xF;
return v5 | (16 * v4);
}
int main()
{
unsigned char key[]="1A2F943C4D8C5B6EA3C9BCAD7E";
char code[]={0x0F, 0x87, 0x62, 0x14, 0x01, 0xC6, 0xF0, 0x21, 0x30, 0x11, 0x50, 0xD0, 0x82, 0x23, 0xAE, 0x23,0xEE, 0xA9, 0xB4, 0x52, 0x78, 0x57, 0x0C, 0x86, 0x8B};
int i;
unsigned char flag[25],mid;
for(i=0;i!=25;i++)
{
mid=sub_401460(key,i);
flag[i]=mid^code[i];
}
for(i=0;i<25;i++)
{
flag[i]=((flag[i]>>2)&0xff)|((flag[i]<<6)&0xff);
}
printf("%s",flag);
}
//EIS{ea3y_r7Eve0rSe_r1ghT}
Re150
一个elf文件,文件需要动调来看,存在smc,和很多花指令。
先是smc
然后找到主函数,并且去掉里面的花,很多都是E8,还有一些是很多字节码都没用的部分。得到主函数如下。
然后加密部分
脚本
#include<stdio.h>
int main(void)
{
unsigned char flag[]={ 0x73, 0x8D, 0xF2, 0x4C, 0xC7, 0xD4, 0x7B, 0xF7, 0x18, 0x32,
0x71, 0x0D, 0xCF, 0xDC, 0x67, 0x4F, 0x7F, 0x0B, 0x6D};
int i;
for(i=0;i<20;i++)
{
flag[i]=flag[i]^0x20;
flag[i]=flag[i]^i;
flag[i]= (flag[i] <<(i%8)) |(flag[i]>>(8-i%8));
printf("%c",flag[i]);
}
}
//SYC{>>Wh06m1>>R0Ot}
babyre1
考察点,xxtea加密解密,还有md5加密,爆破,和细节约束条件。
主函数
加密函数内部
题目中,还有个判断就是,md5(rctf{(input)})=5f8243a662cf71bf31d2b2602638dc1d
所以写脚本的大概思路就是根据密文Bingo!^0x17,来先得到解密前的6个字节,然后爆破剩下的两个字节,然后进行xxtea解密,将解密后的8个字节,套上格式rctf{},进行md5加密,然后和md5数据进行比较。
脚本,其中的md5.c来自GitHub。
#include<stdio.h>
#include "MD5.c"
#include<string.h>
void encrypt(unsigned int *flag ,unsigned int *key ,unsigned int n)
{
unsigned int next,end,sum;
unsigned int rounds,e,delta=0x9e3779b9;
int i;
rounds=6+52/n;//轮回的次数
sum=0;
end=flag[n-1];//先设置end的值为最后一个,因为加密第一个要用
do
{
sum+=delta;
e=(sum>>2)&3;//与key的值关;
for(i=0;i<n-1;i++)//加密第一个到倒数第二个
{
next=flag[i+1];
flag[i]+=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
end=flag[i];//现在用end来保存当前数据的值,为下一个数据的加密做准备。
}
next=flag[0];//将第一个数据给next,为加密最后一个数据做准备,这时候end的值为倒数第二个数据。
flag[n-1]+=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
end=flag[n-1];//继续设置end的值为最后一个数据,为新一轮加密做准备。
}while(--rounds);
}
void decrypt(unsigned int *code ,unsigned int *key ,unsigned int n)
{
unsigned int next,end,sum;
unsigned int rounds,e,delta=0x9e3779b9;
int i;
rounds=6+52/n;
sum=rounds*delta;
next=code[0];//设置next为code的第一个
do
{
e=(sum>>2)&3;
for(i=n-1;i>0;i--)//解密最后一个到第二个
{
end=code[i-1];
code[i]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) + (key[(i&3)^e]^end) ));
next=code[i];
}
end=code[n-1];
code[0]-=(( (end>>5^next<<2) + (next>>3^end<<4) ) ^ ( (sum^next) +(key[i&3^e]^end) ));
next=code[0];
sum-=delta;
}while(--rounds);
}
int main()
{
unsigned int key[4]={0x0E0C7E0C7,0x0C6F1D3D7,0x0C6D3C6D3,0x0C4D0D2CE};
char hex[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
unsigned int n=2;
int i,j,k,m,q,x,num,z;
for(i=0;i<=4;i++)
{
for(j=0;j<0xff;j++)
{
unsigned int code[2]={0x70797e55,0x00003678};
code[1]=code[1]|(i<<24)|(j<<16);
encrypt(code,key,n);
unsigned char flag[22]="rctf{";
num=0;
for(m=0;m<2;m++)
{
for(q=0;q<4;q++)
{
flag[5+num]=hex[(*((char*)&code[m]+q)&0xff)>>4];
flag[5+num+1]=hex[(*((char*)&code[m]+q)&0xff)&0xf];
num+=2;
}
}
flag[21]=125;
char flag_md5[33]={0};
unsigned char res[23]={0};
md5((uint8_t*)flag, 22, res);
for(int x=0;x<16;x++)
{
sprintf(flag_md5+2*x,"%02x",res[x]);
}
if(!strcmp(flag_md5,"5f8243a662cf71bf31d2b2602638dc1d"))
{
printf("flag:%s",flag);
}
}
}
}
//flag:rctf{05e8a376e4e0446e}
easyRE
这道题,和buu上的一样,直接复制过来了
下载文件用ida打开,shift+12;
找到重要代码
unsigned __int64 v54; // [rsp+108h] [rbp-18h]
v54 = __readfsqword(0x28u);
v12 = 73;
v13 = 111;
v14 = 100;
v15 = 108;
v16 = 62;
v17 = 81;
v18 = 110;
v19 = 98;
v20 = 40;
v21 = 111;
v22 = 99;
v23 = 121;
v24 = 127;
v25 = 121;
v26 = 46;
v27 = 105;
v28 = 127;
v29 = 100;
v30 = 96;
v31 = 51;
v32 = 119;
v33 = 125;
v34 = 119;
v35 = 101;
v36 = 107;
v37 = 57;
v38 = 123;
v39 = 105;
v40 = 121;
v41 = 61;
v42 = 126;
v43 = 121;
v44 = 76;
v45 = 64;
v46 = 69;
v47 = 67;
memset(v48, 0, sizeof(v48));
v49 = 0;
v50 = 0;
sub_4406E0(0LL, v48, 37LL);
v50 = 0;
if ( sub_424BA0(v48) == 36 )
{
for ( i = 0; i < (unsigned __int64)sub_424BA0(v48); ++i )
{
if ( (unsigned __int8)(v48[i] ^ i) != *(&v12 + i) )//v48是自己输入的,*(&v12 + i)就相当于一个数组,从v12到v47,一共36个数。简单的异或。
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0("continue!");
memset(&v51, 0, 0x40uLL);
v53 = 0;
sub_4406E0(0LL, &v51, 64LL);
v52 = 0;
if ( sub_424BA0(&v51) == 39 )
{
v1 = sub_400E44(&v51);
v2 = sub_400E44(v1);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
if ( !(unsigned int)sub_400360(v10, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v54 )
sub_444020();
return result;
}
先看这一部分
if ( sub_424BA0(v48) == 36 )
{
for ( i = 0; i < (unsigned __int64)sub_424BA0(v48); ++i )
{
if ( (unsigned __int8)(v48[i] ^ i) != *(&v12 + i) )//v48是自己输入的,*(&v12 + i)就相当于一个数组,从v12到v47,一共36个数。简单的异或。
{
result = 4294967294LL;
goto LABEL_13;
}
}
写出脚本
#include<stdio.h>
int main(void)
{
int a[36]={73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,119,101,107,57,123,105,121,61,126,121,76,64,69,67};
int i;
for(i=0;i<36;i++)
{
a[i]=a[i]^i;
printf("%c",a[i]);
}
}
得到
它说:前四个字符是“flag”,现在还不知道意思。
继续看
memset(&v51, 0, 0x40uLL);//定义了一个数组叫v51
v53 = 0;
sub_4406E0(0LL, &v51, 64LL);
v52 = 0;
if ( sub_424BA0(&v51) == 39 )//v61长度是39
{
v1 = sub_400E44(&v51);//对v51base64编码
v2 = sub_400E44(v1);//对v1base64编码
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
if ( !(unsigned int)sub_400360(v10, off_6CC090) )将v10和off_6CC090对比。
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
整个过程就是一个不断base64编码的过程,进行了10次,得到了off_6CC090,也就是
Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ==
直接网上解码10次,发现是https://bbs.pediy.com/thread-254172.htm,居然是一个网站。。。。无情被欺骗。最后通过看wp,发现真正的算法在
得到代码
unsigned __int64 __fastcall sub_400D35(__int64 a1, __int64 a2)
{
__int64 v2; // rdx
__int64 v3; // rdx
__int64 v4; // rdx
unsigned __int64 result; // rax
unsigned __int64 v6; // rt1
unsigned int v7; // [rsp+Ch] [rbp-24h]
signed int i; // [rsp+10h] [rbp-20h]
signed int j; // [rsp+14h] [rbp-1Ch]
unsigned int v10; // [rsp+24h] [rbp-Ch]
unsigned __int64 v11; // [rsp+28h] [rbp-8h]
v11 = __readfsqword(0x28u);
v7 = sub_43FD20() - qword_6CEE38;
for ( i = 0; i <= '\x04�'; ++i )
{
sub_40F790(v7);
sub_40FE60(v7, a2, v2);
sub_40FE60(v7, a2, v3);
v7 = (unsigned __int64)sub_40FE60(v7, a2, v4) ^ 2557891634;
}
v10 = v7;
if ( ((unsigned __int8)v7 ^ byte_6CC0A0[0]) == 'f' && (HIBYTE(v10) ^ (unsigned __int8)byte_6CC0A3) == 'g' )//这里的f和g是不是有点熟悉,再联系一下前面的提示:前四个字符是“flag”,通过这个来求key。
{
for ( j = 0; j <= 24; ++j )
sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v10 + j % 4)));//加密算法,key实际上就是那个v10,通过j % 4,又可以知道,v10只有4个。
}
v6 = __readfsqword(0x28u);
result = v6 ^ v11;
if ( v6 != v11 )
sub_444020();
return result;
}
byte_6CC0A0[25]={0x40,0x35,0x20,0x56,0x5d,0x18,0x22,0x45,0x17,0x2f,0x24,0x6e,0x62,0x3c,0x27,0x54,0x48,0x6c,0x24,0x6e,0x72,0x3c,0x32,0x45,0x5b};
写出脚本
#include<stdio.h>
int main(void)
{
int a[36]={73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,119,101,107,57,123,105,121,61,126,121,76,64,69,67};
int key[4]={'f','l','a','g'} ;
int byte_6CC0A0[25]={0x40,0x35,0x20,0x56,0x5d,0x18,0x22,0x45,0x17,0x2f,0x24,0x6e,0x62,0x3c,0x27,0x54,0x48,0x6c,0x24,0x6e,0x72,0x3c,0x32,0x45,0x5b};
int i,j;
for(i=0;i<36;i++)
{
a[i]=a[i]^i;
printf("%c",a[i]);
}
printf("\n");
for(i=0;i<4;i++)//通过前4个字符,也就是flag,求出key。
{
key[i]=key[i]^byte_6CC0A0[i];
}
for(j=0;j<25;j++)//用key来解密。
{
byte_6CC0A0[j]=byte_6CC0A0[j]^key[j%4];
printf("%c",byte_6CC0A0[j]);
}
}
得到flag{Act1ve_Defen5e_Test}
babyre
题目设置了3个password,第一个是3维迷宫,第二个是base64解密,第3个是类似sm4的加密过程。
3维迷宫
画出3维迷宫
#include<stdio.h>
//ddwwxxssxaxwwaasasyywwdd
int main()
{
char map[]="**************.****.**s..*..******.****.***********..***..**..#*..***..***.********************.**..*******..**...*..*.*.**.*";
int i;
for(i=0;i<125;i++)
{
printf("%c ",map[i]);
if((i+1)%5==0)
{
printf("\n");
}
if((i+1)%25==0)
{
printf("\n");
}
}
}
* * * * * * . . * * * . . * * * * * * * * * * * *
* * * * * * * * * . * . . * * * * * * * * * . . *
* * * * . * * * * . . . # * . * * * * * * . . . *
* * * * . * * * * * . * * * . * * * * * . . * . *
* * s . . * * * * * . * * * . . * * . . . * * . *
第二部分,base64解密过程,应该是把表给隐藏了,动调应该可以看到。
脚本
import base64
url = 'sctf_9102'
date = url.encode("utf-8")
st = base64.b64encode(date)
print(st)
#c2N0Zl85MTAy
第3部分,也是比较难的一部分,类似sm4加密过程。
要逆这个算法,想了很久,分析发现其实和数组内异或加密是差不多的,我们假设生成的30个数为v1~v30,我们可以知道v30=v26^sub_1464(v27 ^ v28 ^ v29),现在密文已知,相当于v27,v28,v29,v30是已知,所以可以求得v26,然后可以求得v25…..直到最后求出开始的4个数,然后转为char。
这个还可以不写算法,直接用题目中的,只需要将开始的4个数改为密文(注意顺序就行),就可以得到明文。
网上找的脚本如下
aaa = [0xbe040680,0xc5af7647,0x9fcc401f,0xd8bf92ef]
d = [
0x000000D6, 0x00000090, 0x000000E9, 0x000000FE, 0x000000CC, 0x000000E1, 0x0000003D, 0x000000B7, 0x00000016, 0x000000B6, 0x00000014, 0x000000C2, 0x00000028, 0x000000FB, 0x0000002C, 0x00000005, 0x0000002B, 0x00000067, 0x0000009A, 0x00000076, 0x0000002A, 0x000000BE, 0x00000004, 0x000000C3, 0x000000AA, 0x00000044, 0x00000013, 0x00000026, 0x00000049, 0x00000086, 0x00000006, 0x00000099, 0x0000009C, 0x00000042, 0x00000050, 0x000000F4, 0x00000091, 0x000000EF, 0x00000098, 0x0000007A, 0x00000033, 0x00000054, 0x0000000B, 0x00000043, 0x000000ED, 0x000000CF, 0x000000AC, 0x00000062, 0x000000E4, 0x000000B3, 0x0000001C, 0x000000A9, 0x000000C9, 0x00000008, 0x000000E8, 0x00000095, 0x00000080, 0x000000DF, 0x00000094, 0x000000FA, 0x00000075, 0x0000008F, 0x0000003F, 0x000000A6, 0x00000047, 0x00000007, 0x000000A7, 0x000000FC, 0x000000F3, 0x00000073, 0x00000017, 0x000000BA, 0x00000083, 0x00000059, 0x0000003C, 0x00000019, 0x000000E6, 0x00000085, 0x0000004F, 0x000000A8, 0x00000068, 0x0000006B, 0x00000081, 0x000000B2, 0x00000071, 0x00000064, 0x000000DA, 0x0000008B, 0x000000F8, 0x000000EB, 0x0000000F, 0x0000004B, 0x00000070, 0x00000056, 0x0000009D, 0x00000035, 0x0000001E, 0x00000024, 0x0000000E, 0x0000005E, 0x00000063, 0x00000058, 0x000000D1, 0x000000A2, 0x00000025, 0x00000022, 0x0000007C, 0x0000003B, 0x00000001, 0x00000021, 0x00000078, 0x00000087, 0x000000D4, 0x00000000, 0x00000046, 0x00000057, 0x0000009F, 0x000000D3, 0x00000027, 0x00000052, 0x0000004C, 0x00000036, 0x00000002, 0x000000E7, 0x000000A0, 0x000000C4, 0x000000C8, 0x0000009E, 0x000000EA, 0x000000BF, 0x0000008A, 0x000000D2, 0x00000040, 0x000000C7, 0x00000038, 0x000000B5, 0x000000A3, 0x000000F7, 0x000000F2, 0x000000CE, 0x000000F9, 0x00000061, 0x00000015, 0x000000A1, 0x000000E0, 0x000000AE, 0x0000005D, 0x000000A4, 0x0000009B, 0x00000034, 0x0000001A, 0x00000055, 0x000000AD, 0x00000093, 0x00000032, 0x00000030, 0x000000F5, 0x0000008C, 0x000000B1, 0x000000E3, 0x0000001D, 0x000000F6, 0x000000E2, 0x0000002E, 0x00000082, 0x00000066, 0x000000CA, 0x00000060, 0x000000C0, 0x00000029, 0x00000023, 0x000000AB, 0x0000000D, 0x00000053, 0x0000004E, 0x0000006F, 0x000000D5, 0x000000DB, 0x00000037, 0x00000045, 0x000000DE, 0x000000FD, 0x0000008E, 0x0000002F, 0x00000003, 0x000000FF, 0x0000006A, 0x00000072, 0x0000006D, 0x0000006C, 0x0000005B, 0x00000051, 0x0000008D, 0x0000001B, 0x000000AF, 0x00000092, 0x000000BB, 0x000000DD, 0x000000BC, 0x0000007F, 0x00000011, 0x000000D9, 0x0000005C, 0x00000041, 0x0000001F, 0x00000010, 0x0000005A, 0x000000D8, 0x0000000A, 0x000000C1, 0x00000031, 0x00000088, 0x000000A5, 0x000000CD, 0x0000007B, 0x000000BD, 0x0000002D, 0x00000074, 0x000000D0, 0x00000012, 0x000000B8, 0x000000E5, 0x000000B4, 0x000000B0, 0x00000089, 0x00000069, 0x00000097, 0x0000004A, 0x0000000C, 0x00000096, 0x00000077, 0x0000007E, 0x00000065, 0x000000B9, 0x000000F1, 0x00000009, 0x000000C5, 0x0000006E, 0x000000C6, 0x00000084, 0x00000018, 0x000000F0, 0x0000007D, 0x000000EC, 0x0000003A, 0x000000DC, 0x0000004D, 0x00000020, 0x00000079, 0x000000EE, 0x0000005F, 0x0000003E, 0x000000D7, 0x000000CB, 0x00000039, 0x00000048, 0x000000C6, 0x000000BA, 0x000000B1, 0x000000A3, 0x00000050, 0x00000033, 0x000000AA, 0x00000056, 0x00000097, 0x00000091, 0x0000007D, 0x00000067, 0x000000DC, 0x00000022, 0x00000070, 0x000000B2, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
]
for i in range(len(d)):
if d[i] == 0xa6:
print i
def pass3_re(x):
x &= 0xffffffff
a = d[x&0xff]
b = (d[(x&0xffff)>>8]<<8)
c = (d[(x&0xffffff)>>16]<<16)
e = (d[(x&0xffffffff)>>24]<<24)
x = a|b|c|e
x &= 0xffffffff
a = (((x<<12)|(x>>20))&0xffffffff)
b = (((x>>6)|(x<<26))&0xffffffff)
c = (((x<<8)|(x>>24))&0xffffffff)
e = (((x>>2)|(x<<30))&0xffffffff)
x = a^b^c^e
return x&0xffffffff
l = []
for i in range(30 - 4):
l.append(0)
for i in aaa:
l.append(i)
cx = 25
for i in range(26):
l[cx] = pass3_re(l[cx+1] ^ l[cx+2] ^ l[cx+3]) ^ l[cx+4]
cx -= 1
pass3 = ''
for i in range(4):
pass3 += (hex(l[i])[2:]).decode('hex')[::-1]
print pass3
所以得到flag:sctf{ddwwxxssxaxwwaasasyywwdd-c2N0Zl85MTAy(fl4g_is_s0_ug1y!)}
easy-reverse-200
不知道为什么交不了flag了
分析函数,发现是对字节加密的xtea算法,对delat也进行了修改。
脚本解密
#include<stdio.h>
void decrypt(unsigned int r ,char *code ,int *key)
{
char v0,v1,i,j=0;
unsigned char sum=0xD9u;
v0=code[0];
v1=code[1];
do
{
sum += 71;
v1 -= (sum + *(unsigned __int8 *)(key + (((char)sum >> 11) & 3))) ^ (v0 + (16 * (char)v0 ^ ((char)v0 >> 5)));
v0 -= (v1 + (((char)v1 >> 5) ^ 16 * (char)v1)) ^ (sum + *(unsigned __int8 *)(key + (sum & 3)));
}while(sum!=0xb9);
code[0]=v0;
code[1]=v1;
printf("%c%c",code[0]%128,code[1]%128);
}
int main()
{
int key[4]={0xde,0xad,0xbe,0xef};
unsigned int r=32;
char code[24]={ 0xBF, 0xF1, 0x6A, 0x2C, 0x10, 0x0B, 0x16, 0x59, 0xBA, 0x3A,
0x8C, 0x49, 0x05, 0x1B, 0x04, 0xE2, 0x85, 0xD5, 0xC2, 0xFC,
0xD7, 0x9B, 0xE9, 0x42};
int i;
for(i=0;i<24;i+=2)
{
decrypt(r,&code[i],key);
}
}
//zctf{ha_hAha_d1l_exp0r7}