:Coolapk140: 本篇可能会持续更新
PART1
RE11:Java逆向解密
这个是为数不多自己做的题
下载来是个.class文件,用jadx打开来是这个样子
看到26有一堆奇奇怪怪的,看着就像ascii的东西,有个加密函数
那么就写个解密脚本
key=[180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
flag=''
for i in key:
s=(i^32)-ord('@')
flag+=chr(s)
print flag
运行结果:
flag:flag{This_is_theflag!}
RE12:刮开有奖
[hidden]不会,还没写呢[/hidden]
RE13:[GXYCTF2019]luck_guy
21.5.1
又被小端序这个东西坑了:在CTF中的小端序与大端序
下载文件出来
ida64拖进去打开
整个反编译出来逻辑还是比较清楚的,就是switch按照一定顺序执行,就会给flag
看了一下感觉有用的就1,4,5 想了一下可能会是451,4551,45551这几种,然后试了一下试不出来,后面才发现又被小端序这个东西坑到了,然后调整了一下s的顺序
直接把整个关键代码修改一下放进vscode去试一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"defs.h"
int main(){
unsigned int v0;
char v1;
signed int i;
signed int j;
__int64 s;
char v6;
unsigned __int64 v7;
char f1[]={71, 88, 89, 123, 100, 111, 95, 110, 111, 116, 95,0};
char f2[9];
int a;
for ( i = 0; i <= 4; ++i )
{
scanf("%d",&a);
switch ( a )
{
case 1:
puts("OK, it's flag:");
memset(&s, 0, 0x28uLL);
printf("%s %s", f1,f2);
break;
case 2:
printf("Solar not like you");
break;
case 3:
printf("Solar want a girlfriend");
break;
case 4:
v6 = 0;
f2[7]=127;
f2[6]=102;
f2[5]=111;
f2[4]=96;
f2[3]=103;
f2[2]=117;
f2[1]=99;
f2[0]=105;
break;
case 5:
for ( j = 0; j <= 7; ++j )
{
if ( j % 2 == 1 )
v1 = f2[j] - 2;
else
v1 = f2[j] - 1;
f2[j] = v1;
}
break;
default:
puts("emmm,you can't find flag 23333");
break;
}
}
}
输入451就出来了flag
flag:GXY{do_not_hate_me}
RE14:findit
21.5.1
下载下来发现是个apk,直接jadx打开,源码直接出来了
代码都不用写,直接挑出关键代码稍作修改放到vscode里面运行一下就可以了
#include<stdio.h>
int main(){
char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
char b[] = {'p','v','k','q','{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
char x[17];
char y[38];
for (int i = 0; i < 17; i++) {
if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
x[i] = (char) (a[i] + 18);
} else if ((a[i] < 'A' || a[i] > 'Z') && (a[i] < 'a' || a[i] > 'z')) {
x[i] = a[i];
} else {
x[i] = (char) (a[i] - '\b');
}
}
for (int i2 = 0; i2 < 38; i2++) {
if ((b[i2] < 'A' || b[i2] > 'Z') && (b[i2] < 'a' || b[i2] > 'z')) {
y[i2] = b[i2];
} else {
y[i2] = (char) (b[i2] + 16);
if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
y[i2] = (char) (y[i2] - 26);
}
}
}
for(int i =0;i<17;i++){
printf("%c",x[i]);
}
printf("\n");
for(int j=0;j<38;j++){
printf("%c",y[j]);
}
}
但是我输出y会乱码,我也不知道为啥
于是就交给手机,把x输进去框框里面,得到flag
flag:flag{c164675262033b4c49bdf7f9cda28a75}
RE15:简单注册器
21.5.8
下载文件,发现是个apk,拖进jadx打开
找到关键代码拖进vscode,稍微做一点修改
#include<stdio.h>
int main(){
char x[33] = "dd2940c04462b4dd7c450528835cca15";
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
printf("flag{%s}",x);
}
运行得到flag
flag:flag{59acc538825054c7de4b26440c0999dd}
RE16:[GWCTF 2019]pyre
21.5.8
下载文件,是一个pyc文件,找某度有个pyc在线反编译
得到源码
#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128
code += num
for i in range(l - 1):
code[i] = code[i] ^ code[i + 1]
print code
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']
然后根据源码写出解密脚本
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']
flag=''
for i in reversed(range(22)):
code[i]=chr(ord(code[i+1])^ord(code[i]))
for j in range(23):
flag+=chr(((ord(code[j])-128)%128-j)%128)
print flag
其中有一个地方有点难,就是取余的逆运算([hidden]对于当代痴呆大学生:指我自己[/hidden])
具体可以参考这个:求余逆运算+负数求余
RE17:[BJDCTF2020]JustRE
21.5.9
下载文件,点开看了一下
有个getflag的选项,点一下
弹出一个窗口,点下面click it
会计数,感觉是要动态调试,可惜我不会,于是打开ida,看了一下关键代码
盲猜要点19999下,于是打开ce :Coolapk84:
直接改成19998,最后点一下click it
真不戳
flag:flag{1999902069a45792d233ac}
RE18:rsa
21.5.9
rsa不会,直接抄的BUUCTF RSA
RE21:[2019红帽杯]easyRE
21.5.18
代码好乱,不会,看了一下wp
打开文件,一堆函数,然后shift+f12打开
找到一些东西
看起来就是base64
点进函数
写半天,把这个base64解密了,上面那一串异或了就一个提示
看别人的wp才知道还有个函数在另外一个地方
然后来个脚本
'''a='Iodl>Qnb(ocy'+chr(127)+'y.i'+chr(127)+'d`3w}wek9{iy=~yL@EC'
b=''
for i,j in zip(a,range(len(a))):
b+=chr(ord(i)^j)
print b'''
v1='flag'
v2=[64, 53, 32, 86, 93, 24, 34, 69, 23, 47,
36, 110, 98, 60, 39, 84, 72, 108, 36, 110,
114, 60, 50, 69, 91]
key=''
flag=''
for i in range(4):
key+=chr(v2[i]^ord(v1[i]))
for i in range(len(v2)):
flag+=chr(v2[i]^ord(key[i%4]))
print flag
flag:flag{Act1ve_Defen5e_Test}
RE22:[ACTF新生赛2020]rome
21.5.18
脚本没写出来 :bili大哭
s='Qsw3sj_lz4_Ujw@l'
flag=''
for i in s:
if ord(i)>64 and ord(i)<=90:
flag+=chr((ord(i)-14))
elif ord(i)>96 and ord(i)<=122:
flag+=chr((ord(i)-18))
else:
flag+=i
print flag
有点问题,不知道为啥,后来就直接抄了cnblog BUUCTF--[ACTF新生赛2020]rome
flag:flag{Cae3ar_th4_Gre@t}
RE23:[FlareOn4]login
21.5.26
简单的题
算法都没看,直接试一下alert(rotFlag);
然后随便输入一些字母,发现就是简单的移位
写个脚本
s='PyvragFvqrYbtvafNerRnfl@syner-ba.pbz'
flag=''
for i in s:
if (i>='a' and i<='m') or (i>='A' and i<='M'):
flag+=chr(ord(i)+13)
elif (i>='n' and i<='z') or (i>='N' and i<='Z'):
flag+=chr(ord(i)-13)
else:
flag+=i
print flag
flag:flag{ClientSideLoginsAreEasy@flare-on.com}
RE25:[GUET-CTF2019]re
21.5.26
一堆奇葩东西
手工处理数据之后上脚本
a=[1629056,
6771600,
3682944,
10431000,
3977328,
5138336,
7532250,
5551632,
3409728,
13013670,
6088797,
7884663,
8944053,
5198490,
4544518,
3645600,
10115280,
9667504,
5364450,
13464540,
5488432,
14479500,
6451830,
6252576,
7763364,
7327320,
8741520,
8871876,
4086720,
9374400,
5759124]
b=[166163712,
731332800,
357245568,
1074393000,
489211344,
518971936,
406741500,
294236496,
177305856,
650683500,
298351053,
386348487,
438258597,
249527520,
445362764,
174988800,
981182160,
493042704,
257493600,
767478780,
312840624,
1404511500,
316139670,
619005024,
372641472,
373693320,
498266640,
452465676,
208422720,
515592000,
719890500]
flag=''
for i,j in zip(a,b):
flag+=chr(j/i)
print flag
#坑壁题目缺第七位,看都看不到。。。
坑壁题目缺第七位,看都看不到。。。害我看wp :Coolapk84:
好像要爆破第七位..是1
flag:flag{e165421110ba03099a1c039337}
RE27:相册
21.7.27
时隔多月我又做了一题(主要原因是放假了在玩
首先下载,发现是个apk,那么我们打开jadx看看
这么怪的名字肯定在里面
随便点开几个康康
然后去c2看看
ok,这波属于是写明了是base64了,接下来我们去so文件里面找一下base64的字符
解压得到libcore.so
ida打开,shift+f12
得到几个base64
选中的这个就是flag需要的邮箱了
包上flag提交即可。
flag:flag{18218465125@163.com}
RE29:level1
21.8.3
ida64打开
逻辑很清晰
奇数进行位运算右移,偶数乘以下标
python写个脚本就行了
a=[198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
flag=''
for i in range(1,20):
if (i&1)!=0:
a[i-1]=a[i-1]>>i
else:
a[i-1]=a[i-1]/i
for j in a:
flag+=chr(j)
print flag
flag:ctf2020{d9-dE6-20c}
RE30:[MRCTF2020]Transform
21.8.5
无壳,打开ida64看一下main
主要的加密还是在这两句
这是数据
具体就是根据索引dword_40F040打乱顺序然后再异或,然后我们只需要反过来即可,也就是倒着循环reversed(range(33))然后先异或再flag[dword_40F040[i]]=byte_40F0E0[i]即可
写出python脚本:
dword_40F040=[0x09,0x0A,0x0F,0x17,0x07,0x18,0x0C,0x06,0x01,0x10,0x03,0x11,0x20,0x1D,0x0B,0x1E,0x1B,0x16,0x04,0x0D,0x13,0x14,0x15,0x02,0x19,0x05,0x1F,0x08,0x12,0x1A,0x1C,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
byte_40F0E0=[0x67,0x79,0x7B,0x7F,0x75,0x2B,0x3C,0x52,0x53,0x79,0x57,0x5E,0x5D,0x42,0x7B,0x2D,0x2A,0x66,0x42,0x7E,0x4C,0x57,0x79,0x41,0x6B,0x7E,0x65,0x3C,0x5C,0x45,0x6F,0x62,0x4D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
flag=[0]*33
for i in reversed(range(0,33)):
byte_40F0E0[i]^=(dword_40F040[i])
flag[dword_40F040[i]]=byte_40F0E0[i]
print ''.join([chr(x) for x in flag])
flag:flag{Tr4nsp0sltiON_Clph3r_1s_3z}
RE31:[WUSTCTF2020]level2
21.8.5
???
放到kali里面upx -d,shift+f12就出来了
flag:flag{Justupx-d}
RE34:[MRCTF2020]Xor
21.10.12
反编译失败,调用函数参数有问题,这里删掉三个点这个东西就行了。
超级简单的异或,直接脚本
a='MSAWB~FXZ:J:`tQJ"N@ bpdd}8g'
flag=''
for i in range(27):
flag+=chr(i^ord(a[i]))
print flag
flag:MRCTF{@_R3@1ly_E2_R3verse!}
RE35:[FlareOn4]IgniteMe
21.10.14
今天线下打金华市和美杯 来早了,做了个re
ida打开
只有五个函数,
这两个是关键函数,打开看看
这个函数看起来就是对数组初始化,没啥用
这个就比较有用了,可以看到一个简单的异或操作,但是v4初值不知道,点进sub_401000():
查了下这个函数,也没查出什么,动调看看
断点断在那个for循环上面
然后双击v4,可以看到
他的初值是4。
于是写个脚本
a=[ 13, 38, 73, 69, 42, 23, 120, 68, 43, 108,
93, 94, 69, 18, 47, 23, 43, 68, 111, 110,
86, 9, 95, 69, 71, 115, 38, 10, 13, 19,
23, 72, 66, 1, 64, 77, 12, 2, 105]
flag=''
b=0
v4=4
for i in reversed(a):
b=v4^i
v4=b
flag+=chr(b)
print flag[::-1]
flag:flag{R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com}
RE36:[MRCTF2020]hello_world_go
21.10.14
go语言 逆向出来是真的复杂啊
完全看不懂
主函数就有flag
flag:flag{hello_world_gogogo}
RE37:[WUSTCTF2020]level3
21.10.19
main函数给了个base64
有个奇怪的换表函数,好像在start的时候被调用了(main之前)
直接动调一下看看被改成啥样了(脚本写了但是好像不太对?
真不戳
然后随便找个换表脚本就出来了
flag:wctf2020{Base64_is_the_start_of_reverse}
RE38:[WUSTCTF2020]Cr0ssfun
21.10.19
手动操作复制出来输出,没什么好说的
flag:wctf2020{cpp_@ndr3verse@re_fun}
RE39:[WUSTCTF2020]Cr0ssfun
21.10.19
不太会
参考这个https://blog.csdn.net/weixin_47158947/article/details/107818896
不过md5那个地方X2是变大写,所以这篇文章交不上去,实际flag内需要大写
flag:flag{B8C37E33DEFDE51CF91E}
RE40:[FlareOn6]Overlong
21.10.28
动调改一下就好了1C改成7F
因为字符串很长,而for循环只循环前面28位,改长一点就行了。然后断在start函数的return 0,再点进text复制栈上内容就行了。
flag:flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}
RE41:[ACTF新生赛2020]Oruga
21.10.28
打开先验证格式actf{}
然后进到一个函数,看到+16-16+1-1这个,再看到一个奇怪的256字符的数组,直接猜测是迷宫,实际上也确实是的。
这个题比较迷惑,是左上角开始走的,我被迷惑到了,弄成了0是起点,!是终点
而且移动也不是一个一个走,是滑动,题目名字翻译过来也是履带,估计就是想暗示吧。
迷宫走完就行了
象征性的贴个输出迷宫的脚本
map=[0, 0, 0, 0, 35, 0, 0, 0, 0, 0,
0, 0, 35, 35, 35, 35, 0, 0, 0, 35,
35, 0, 0, 0, 79, 79, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
79, 79, 0, 80, 80, 0, 0, 0, 0, 0,
0, 76, 0, 79, 79, 0, 79, 79, 0, 80,
80, 0, 0, 0, 0, 0, 0, 76, 0, 79,
79, 0, 79, 79, 0, 80, 0, 0, 0, 0,
0, 0, 76, 76, 0, 79, 79, 0, 0, 0,
0, 80, 0, 0, 0, 0, 0, 0, 0, 0,
0, 79, 79, 0, 0, 0, 0, 80, 0, 0,
0, 0, 35, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77, 77, 77, 0, 0, 0, 35, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 77, 77, 77,
0, 0, 0, 0, 69, 69, 0, 0, 0, 48,
0, 77, 0, 77, 0, 77, 0, 0, 0, 0,
69, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 69, 69, 84, 84,
84, 73, 0, 77, 0, 77, 0, 77, 0, 0,
0, 0, 69, 0, 0, 84, 0, 73, 0, 77,
0, 77, 0, 77, 0, 0, 0, 0, 69, 0,
0, 84, 0, 73, 0, 77, 0, 77, 0, 77,
33, 0, 0, 0, 69, 69]
map1=''
for i in range(256):
if i%16==0:
map1+='\n'
if map[i]==0:
map1+='.'
map1+=chr(map[i])
print map1
flag:flag{MEWEMEWJMEWJM}
RE42:[FlareOn3]Challenge1
21.10.29
动调复制被初始化的base64表然后拿换标脚本解密就行了。之前写过类似的题
import base64
import string
str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
'''
a=[0x5A, 0x59, 0x58, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x7A, 0x79, 0x78, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F]
string3=''
for i in a:
string3+=chr(i)
print(string3)
'''
string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))
flag:flag{sh00ting_phish_in_a_barrel@flare-on.com}
RE43:[UTCTF2020]basic-re
22.1.10
都不想放上来...以后这种太简单的题就不放出来了
直接string或者shift+f12就有的
flag:flag{str1ngs_1s_y0ur_fr13nd}
RE44:[Zer0pts2020]easy strcmp
22.1.10
说实话,这个题挺折腾人的,不过也是因为自己python掌握的不好,类型转换老是搞不明白
不过动调能解决的话就很不错了
拿到题目,上来直接一个strcmp,真的很怪
flag也不是这个东西。边上还有几个奇怪的函数,于是找到了这两个
这个把strcmp的地址改了,为了方便,我重新命名了一下
(忽略那个+=,我改过,原来是-=的)
这个“假的”strcmp就是这么个逻辑,把一坨东西和输入进去的相减,最后得到zer0pts{********CENSORED********}
这个东西
那就加回来就行了
python脚本不会类型转换,c语言写也报错,离谱了,于是我直接动调,算是一种新思路吧
这个地方原本是sub的,改成add,然后动调,参数直接写成这样
然后断点在图上那个地方,按几次f4,然后点进去看flag就行了
整个就是属于是一个脑洞题...
flag:flag{l3ts_m4k3_4_DETOUR_t0d4y}
RE45:[ACTF新生赛2020]Universe_final_answer
22.1.11
直接用z3就行了
存个学z3的教程https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/5.8.1_z3.html
打开之后,在这里进入目标函数
一堆公式,丢到python里面用z3求解一下
from z3 import *
solver = Solver()
a1=[BitVec("a1[%d]" % i,16) for i in range(10)]
solver.add(-85 * a1[8] + 58 * a1[7] + 97 * a1[6] + a1[5] + -45 * a1[4] + 84 * a1[3] + 95 * a1[0] - 20 * a1[1] + 12 * a1[2] == 12613)
solver.add(30 * a1[9] + -70 * a1[8] + -122 * a1[6] + -81 * a1[5] + -66 * a1[4] + -115 * a1[3] + -41 * a1[2] + -86 * a1[1] - 15 * a1[0] - 30 * a1[7] == -54400)
solver.add(-103 * a1[9] + 120 * a1[7] + 108 * a1[5] + 48 * a1[3] + -89 * a1[2] + 78 * a1[1] - 41 * a1[0] + 31 * a1[4] - (a1[6] << 6) - 120 * a1[8] == -10283)
solver.add(71 * a1[6] + (a1[5] << 7) + 99 * a1[4] + -111 * a1[2] + 85 * a1[1] + 79 * a1[0] - 30 * a1[3] - 119 * a1[7] + 48 * a1[8] - 16 * a1[9] == 22855)
solver.add(5 * a1[9] + 23 * a1[8] + 122 * a1[7] + -19 * a1[6] + 99 * a1[5] + -117 * a1[4] + -69 * a1[2] + 22 * a1[1] - 98 * a1[0] + 10 * a1[3] == -2944)
solver.add(-54 * a1[9] + -23 * a1[7] + -82 * a1[2] + -85 * a1[0] + 124 * a1[1] - 11 * a1[3] - 8 * a1[4] - 60 * a1[5] + 95 * a1[6] + 100 * a1[8] == -2222)
solver.add(-83 * a1[9] + -111 * a1[5] + -57 * a1[0] + 41 * a1[1] + 73 * a1[2] - 18 * a1[3] + 26 * a1[4] + 16 * a1[6] + 77 * a1[7] - 63 * a1[8] == -13258)
solver.add(81 * a1[9] + -48 * a1[8] + 66 * a1[7] + -104 * a1[6] + -121 * a1[5] + 95 * a1[4] + 85 * a1[3] + 60 * a1[2] + -85 * a1[0] + 80 * a1[1] == -1559)
solver.add(101 * a1[9] + -85 * a1[8] + 7 * a1[6] + 117 * a1[5] + -83 * a1[4] + -101 * a1[3] + 90 * a1[2] + -28 * a1[1] + 18 * a1[0] - a1[7] == 6308)
solver.add(99 * a1[9] + -28 * a1[8] + 5 * a1[7] + 93 * a1[6] + -18 * a1[5] + -127 * a1[4] + 6 * a1[3] + -9 * a1[2] + -93 * a1[1] + 58 * a1[0] == -1697)
if solver.check() == sat:
m = solver.model()
flag1=''
for i in [str(m.eval(a1[i])) for i in range(10)]:
if int(i)>32768:
i=int(i)-32768
flag1+=chr(int(i))
print flag1
然后解出来的东西再放到题目里面运行一下就可以出来flag
flag:flag{F0uRTy_7w@_42}
PART 2
接下来可能不会继续做一分题了(除非找信心)
[MRCTF2020]Shit
题目给出了源码,甚至给了decode函数。不确定的就是key,在启动后会修改。于是使用ollydbg动调出key
源码:
#include<Windows.h>
#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[100],c=2;
int key[7]={'b','k','d','c','e','w'};
unsigned int ks[6]={0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279};//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
FARPROC proc=NULL;
int initHook()
{
HMODULE hModule=LoadLibraryA("Kernel32.dll");
if(hModule)
{
proc=GetProcAddress(hModule,"IsDebuggerPresent");
if(proc==NULL)
return -1;
}
return 0;
}
PDWORD update()
{
if(initHook()!=0)
exit(-1);
HANDLE hProcess=GetModuleHandle(NULL);
PIMAGE_DOS_HEADER dos_header=(PIMAGE_DOS_HEADER)hProcess;
PIMAGE_NT_HEADERS nt_header=(PIMAGE_NT_HEADERS)(dos_header->e_lfanew+(DWORD)hProcess);
IMAGE_OPTIONAL_HEADER* opt_header=&(nt_header->OptionalHeader);
PIMAGE_IMPORT_DESCRIPTOR iat=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hProcess+opt_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while(iat->FirstThunk)
{
PIMAGE_THUNK_DATA data=(PIMAGE_THUNK_DATA)(iat->FirstThunk+(DWORD)hProcess);
while(data->u1.Function)
{
if(IMAGE_SNAP_BY_ORDINAL(data->u1.AddressOfData))
{
data++;
continue;
}
if((DWORD)proc==data->u1.Function)
return &data->u1.Function;
data++;
}
iat++;
}
return NULL;
}
PDWORD table_addr=NULL;
int writeAddr(DWORD addr)
{
if(table_addr==NULL)
table_addr=update();
DWORD dwOldProtect;
MEMORY_BASIC_INFORMATION mbi_thunk;
VirtualQuery(table_addr,&mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION));
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,PAGE_READWRITE,&mbi_thunk.Protect);
*table_addr=(DWORD)addr;
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,mbi_thunk.Protect,&dwOldProtect);
return 0;
}
bool WINAPI CallBackProc()
{
writeAddr((DWORD)proc);
map[0]=2;c--;
key[0]='a';
key[1]='k';
key[2]='e';
key[3]='y';
key[4]='e';
key[5]='z';
if(IsDebuggerPresent())
{
MessageBoxW(NULL,L"U R Using Debugger!",L"U Suck!",MB_OK);
return true;
}
return false;
}
void sleep()
{
sleep();
}
int checkDebug()
{
if(*((unsigned char *)(*(DWORD*)(__readfsdword(0x18)+0x30))+0x2))
sleep();
return 0;
}
int doit=writeAddr((DWORD)CallBackProc),dd=checkDebug();
bool encode(char* ur_flag)
{
unsigned int k=0,bk=0;
for(int i=0;i<strlen(ur_flag);i+=4)
{
k=(((int)ur_flag[i])<<24)|(((int)ur_flag[i+1])<<16)|(((int)ur_flag[i+2])<<8)|((int)ur_flag[i+3]);
k=(k>>key[i/4]) | (k<<(32-key[i/4]));
_asm
{
call sub2
_emit 0xEB
jmp label2
sub2:
add dword ptr[esp],1
retn
label2:
}
k=((~(k>>16))&0x0000ffff) | (k<<16);
k=(1<<key[i/4])^k;
_asm
{
call sub7
_emit 0xE8
jmp label7
sub7:
add dword ptr[esp],1
retn
label7:
}
if(i>0)
k^=bk;
bk=k;
if(k!=ks[i/4])
return false;
}
return true;
}
void genKey()
{
int len=20,keylen=6,maxium=0;
int before;
_asm
{
call sub1
_emit 0xE8
jmp label1
sub1:
add dword ptr[esp],1
retn
label1:
}
srand(time(NULL));
for(int i=1;i<=len;i++)
{
map[i]=map[i-1]+rand()%5;
_asm
{
call sub3
_emit 0xE8
jmp label3
sub3:
add dword ptr[esp],1
retn
label3:
}
maxium=maxium>map[i]?maxium:map[i];
}
_asm
{
call sub4
_emit 0xE8
jmp label4
sub4:
add dword ptr[esp],1
retn
label4:
}
before=time(NULL);
_asm
{
call sub5
_emit 0xE8
jmp label5
sub5:
add dword ptr[esp],1
retn
label5:
}
for(int i=0;i<keylen;i++)
{
int step=0;
long long t=time(NULL);
int delta=t-before;
_asm
{
call sub6
_emit 0xE8
jmp label6
sub6:
add dword ptr[esp],1
retn
label6:
}
if(delta>maxium)
return;
for(int j=0;j<=len;j++)
if(delta<=map[j])
{
step=map[j];
_asm
{
call sub8
_emit 0xE8
jmp label8
sub8:
add dword ptr[esp],1
retn
label8:
}
break;
}
_asm
{
call sub9
_emit 0xE8
jmp label9
sub9:
add dword ptr[esp],1
retn
label9:
}
key[i]=(key[i]*c+step+i*3)%32;
_asm
{
call sub10
_emit 0xE8
jmp label10
sub10:
add dword ptr[esp],1
retn
label10:
}
before=t;
}
}
void decode()
{
unsigned int k=0,bk=0;
for(int i=5;i>=0;i--)
if(i>0)
ks[i]^=ks[i-1];
for(int i=0;i<24;i+=4)
{
k=ks[i/4];
k=(1<<key[i/4])^k;
k=((k>>16)) | ((~(k<<16))&0xffff0000);
k=((k<<key[i/4])) | (k>>(32-key[i/4]));
printf("%X\n",k);
}
}
int main()
{
char ur_flag[50];
cout<<"please input your flag:"<<endl;
cin>>ur_flag;
if(IsDebuggerPresent())
{
cout<<"U suck! 233333"<<endl;
Sleep(2000);
exit(0);
}
if(strlen(ur_flag)!=24)
{
cout<<"Wrong!"<<endl;
Sleep(2000);
exit(0);
}
genKey();
bool flag=encode(ur_flag);
decode();
if(flag)
{
cout<<"U did it!"<<endl<<"GJ!"<<endl;
system("pause");
exit(0);
}
cout<<"Wrong!"<<endl;
Sleep(2000);
return 0;
}
里面还有一些新的花指令,学到了
前面还有时间差反调试,学到许多,直接把time函数nop掉然后把0移进去就好了,其实按f9按得快一点也可以出
在ida nop掉花指令之后(或者直接od nop掉也可以,但是ida有插件快一点)我们用od断在这里,先随便输24位数字,然后看ecx一个一个提取出来就可以了
注意od好像不会自动识别代码,需要按ctrl+a重新识别再动调。
最后取出来keykey[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B }
直接拿源代码改一下就可以了
#include<Windows.h>
#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[100], c = 2;
//int key[7] = { 'a','k','e','y','e','z' };
int key[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B };
unsigned int ks[6] = { 0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279 };//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
FARPROC proc = NULL;
void decode()
{
unsigned int k = 0, bk = 0;
for (int i = 5; i >= 0; i--)
if (i > 0)
ks[i] ^= ks[i - 1];
for (int i = 0; i < 24; i += 4)
{
k = ks[i / 4];
k = (1 << key[i / 4]) ^ k;
k = ((k >> 16)) | ((~(k << 16)) & 0xffff0000);
k = ((k << key[i / 4])) | (k >> (32 - key[i / 4]));
//printf("%X\n", k);
for (int j = 0; j < 4; j++) {
printf("%c", *((char*)&k + 3 - j));
}
}
}
int main()
{
char ur_flag[50];
cout << "please input your flag:" << endl;
//genKey();
//bool flag=encode(ur_flag);
decode();
/*if(flag)
{
cout<<"U did it!"<<endl<<"GJ!"<<endl;
system("pause");
exit(0);
}
cout<<"Wrong!"<<endl;
Sleep(2000);*/
system("pause");
return 0;
}
flag:flag{a_3a2y_re_for_test}
[watevrCTF 2019]Repyc
题目给了一个pyc文件,在线反编译一下,原本有很多佤 = 0 侰 = ~佤 * ~佤 俴 = 侰 + 侰 def 䯂(䵦):
这种东西,用vscode自带的匹配所有,改一下全部改成人看的字符。本来改完就有点想放弃了,直接搜了下wp,发现是一个vm,第一次接触这种题目。还挺有意思的。自己整理了一下做了一遍
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
a = 0
b = ~a * ~a #1
c = b + b #2
def func(x):
f1 = 0
f3 = [a] * 16
f4 = [a] * 100
f5 = []
while x[f1][a] != "exit":
k1 = x[f1][a].lower()
k2 = x[f1][b:]
if k1 == "add":
f3[k2[a]] = f3[k2[b]] + f3[k2[c]]
elif k1 == "xor":
f3[k2[a]] = f3[k2[b]] ^ f3[k2[c]]
elif k1 == "sub":
f3[k2[a]] = f3[k2[b]] - f3[k2[c]]
elif k1 == "x":
f3[k2[a]] = f3[k2[b]] * f3[k2[c]]
elif k1 == "/":
f3[k2[a]] = f3[k2[b]] / f3[k2[c]]
elif k1 == "&":
f3[k2[a]] = f3[k2[b]] & f3[k2[c]]
elif k1 == "|":
f3[k2[a]] = f3[k2[b]] | f3[k2[c]]
elif k1 == "nop":
f3[k2[a]] = f3[k2[a]]
elif k1 == "mov":
f3[k2[a]] = f3[k2[b]]
elif k1 == "mov1":
f3[k2[a]] = k2[b]
elif k1 == "mov2":
f4[k2[a]] = f3[k2[b]]
elif k1 == "mov3":
f3[k2[a]] = f4[k2[b]]
elif k1 == "to0":
f3[k2[a]] = a
elif k1 == "to_0":
f4[k2[a]] = a
elif k1 == "input":
f3[k2[a]] = input(f3[k2[b]])
elif k1 == "input1":
f4[k2[a]] = input(f3[k2[b]])
elif k1 == "print":
print(f3[k2[a]])
elif k1 == "print1":
print(f4[k2[a]])
elif k1 == "\xeb\xad\xbf":
f1 = f3[k2[a]]
elif k1 == "\xeb\xae\x93":
f1 = f4[k2[a]]
elif k1 == "\xeb\xae\xb3":
f1 = f5.pop()
elif k1 == "\xeb\xaf\x83" or f3[k2[b]] > f3[k2[c]]:
f1 = k2[a]
f5.append(f1)
continue
elif k1 == "for_comp?":
f3[7] = a
for i in range(len(f3[k2[a]])):
if f3[k2[a]] != f3[k2[b]]:
f3[7] = b
f1 = f3[k2[c]]
f5.append(f1)
elif k1 == "for_xor":
m = ""
for i in range(len(f3[k2[a]])):
m += chr(ord(f3[k2[a]][i]) ^ f3[k2[b]])
f3[k2[a]] = m
elif k1 == "for_-":
m = ""
for i in range(len(f3[k2[a]])):
m += chr(ord(f3[k2[a]][i]) - f3[k2[b]])
f3[k2[a]] = m
elif k1 == "\xeb\x96\x87" or f3[k2[b]] > f3[k2[c]]:
f1 = f3[k2[a]]
f5.append(f1)
continue
elif k1 == "\xeb\x97\x8b" or f3[k2[b]] > f3[k2[c]]:
f1 = f4[k2[a]]
f5.append(f1)
continue
elif k1 == "\xeb\x98\xb7" or f3[k2[b]] == f3[k2[c]]:
f1 = k2[a]
f5.append(f1)
continue
elif k1 == "\xeb\x9a\xab" or f3[k2[b]] == f3[k2[c]]:
f1 = f3[k2[a]]
f5.append(f1)
continue
elif k1 == "\xeb\x9d\x87" and f3[k2[b]] == f3[k2[c]]:
f1 = f4[k2[a]]
f5.append(f1)
continue
f1 += b
func(
[
["mov1", 0, "Authentication token: "],
["input1", 0, 0],
[
"mov1",
6,
"\xc3\xa1\xc3\x97\xc3\xa4\xc3\x93\xc3\xa2\xc3\xa6\xc3\xad\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9b\xc3\xa3\xc3\xa5\xc3\xa4\xc3\x89\xc3\x96\xc3\x93\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x96\xc3\x93\xc3\xa5\xc3\xa4\xc3\x89\xc3\x93\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x9b\xc3\x93\xc3\xa4\xc3\xa0\xc3\x99\xc3\x94\xc3\x89\xc3\x93\xc3\xa2\xc3\xa6\xc3\x89\xc3\xa0\xc3\x93\xc3\x9a\xc3\x95\xc3\x93\xc3\x92\xc3\x99\xc3\xa6\xc3\xa4\xc3\xa0\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x9a\xc3\x93\xc3\xa1\xc3\x89\xc2\xb7\xc3\x94\xc3\xa2\xc3\x97\xc3\x9a\xc3\x95\xc3\x93\xc3\x94\xc3\x89\xc2\xb3\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x85\xc3\xa4\xc3\x97\xc3\x9a\xc3\x94\xc3\x97\xc3\xa6\xc3\x94\xc3\x89\xc3\x97\xc3\x9a\xc3\xaf\xc3\xa1\xc3\x97\xc3\xaf\xc3\xa5\xc3\x89\xc3\x9f\xc3\x89\xc3\x94\xc3\x99\xc3\x9a\xc3\xa4\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\xa0\xc3\x97\xc3\xa2\xc3\x93\xc3\x89\xc3\x97\xc3\x89\xc3\x91\xc3\x99\xc3\x99\xc3\x94\xc3\x89\xc3\xa2\xc3\x9f\xc3\x94\xc3\x89\xc3\x96\xc3\xa3\xc3\xa4\xc3\x89\xc3\x9f\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa5\xc3\x99\xc3\x9a\xc3\x91\xc3\x89\xc3\x9f\xc3\x89\xc3\xa0\xc3\x99\xc3\xa8\xc3\x93\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\x89\xc3\xa1\xc3\x9f\xc3\x9c\xc3\x9c\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\x9f\xc3\xa4\xc3\x89\xc3\x97\xc3\xa5\xc3\xa1\xc3\x93\xc3\x9c\xc3\x9c\xc2\x97\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\xa4\xc3\xa3\xc3\x96\xc3\x93\xc2\x9a\xc3\x95\xc3\x99\xc3\x9b\xc2\x99\xc3\xa1\xc3\x97\xc3\xa4\xc3\x95\xc3\xa0\xc2\xa9\xc3\xa2\xc2\xab\xc2\xb3\xc2\xa3\xc3\xaf\xc2\xb2\xc3\x95\xc3\x94\xc3\x88\xc2\xb7\xc2\xb1\xc3\xa2\xc2\xa8\xc3\xab",
],
["mov1", 2, 120],
["mov1", 4, 15],
["mov1", 3, 1],
["x", 2, 2, 3],
["add", 2, 2, 4],
["nop", 0, 2],
["to0", 3],
["for_xor", 6, 3],
["mov1", 0, "Thanks."],
["mov1", 1, "Authorizing access..."],
["print", 0],
["mov3", 0, 0],
["for_xor", 0, 2],
["for_-", 0, 4],
["mov1", 5, 19],
["for_comp?", 0, 6, 5],
["print", 1],
["exit"],
["mov1", 1, "Access denied!"],
["print", 1],
["exit"],
]
)
有两个寄存器f3和f4,只要一个一个把注释搞出来就挺清楚的了。先读进去一个input放在f4的0位上面,然后把key读进去放在f3的6上面,先让key和0异或(迷惑行为),再让input和135异或,再减15。
key="á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ׿ÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
flag=''
for i in range(len(key)):
flag+=chr((ord(key[i])+15)^135)
print(flag)
脚本有坑,编码的问题,弄成之前/x的格式出不来,而且必须python3解,不清楚为什么。
flag长得离谱,还有个404网站链接
flag:flag{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Standard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}
[CFI-CTF 2018]powerPacked
拿到手看了下,发现里面有packed by upx的字样,直接upx脱壳
然后ida反编译不能f5
掏出ghrida,确实还是挺好使的
一个巨简单的加减
a=[0x45,0x48,0x4b,0x7d,0x6b,0x61,0x6e,0x71,0x78,0x67,0x61,0x72,0x71,0x79,0x67,0x74,0x72,0x65]
flag=""
for i in a:
flag+=chr(i-2)
print flag
flag:flag{i_love_powerpc}