March 3, 2022

buu Reverse刷题记录

BUU的刷题记录(非WP),只记录一些自己踩坑和知识点,以及没什么用但舍不得删的解题脚本。

[GUET-CTF2019]re

脱壳之后导入IDA64找加密函数,正常就是写脚本解密,中间少了一位可以爆破。但是这个题,这个题它它它它它中间的17和16居然是倒过来写的,倒过来写的!!!我*&……%¥#@~我我我我我找了好久,找了好久啊,我就说我不可能输反啊扣努压路!
然后就是如何在linux里跑一个elf文件,因为有一位不知道要爆破,就这命令找了半天……
./文件名
这个命令就能跑了,然后是flag脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
flag=[]
a=166163712/1629056
flag.append(a)
a=731332800/6771600
flag.append(a)
a=357245568/3682944
flag.append(a)
a=1074393000/10431000
flag.append(a)
a=489211344/3977328
flag.append(a)
a=518971936/5138336
flag.append(a)
flag.append(ord('1'))
a=406741500/7532250
flag.append(a)
a=294236496/5551632
flag.append(a)
a=177305856/3409728
flag.append(a)
a=650683500/13013670
flag.append(a)
a=298351053/6088797
flag.append(a)
a=386348487/7884663
flag.append(a)
a=438258597/8944053
flag.append(a)
a=249527520/5198490
flag.append(a)
a=445362764/4544518
flag.append(a)
a=981182160/10115280
flag.append(a)
a=174988800/3645600
flag.append(a)
a=493042704/9667504
flag.append(a)
a=257493600/5364450
flag.append(a)
a=767478780/13464540
flag.append(a)
a=312840624/5488432
flag.append(a)
a=1404511500/14479500
flag.append(a)
a=316139670/6451830
flag.append(a)
a=619005024/6252576
flag.append(a)
a=372641472/7763364
flag.append(a)
a=373693320/7327320
flag.append(a)
a=498266640/8741520
flag.append(a)
a=452465676 /8871876
flag.append(a)
a=208422720/4086720
flag.append(a)
a=515592000/9374400
flag.append(a)
a=719890500/5759124
flag.append(a)
s=''
for i in flag:
s+=chr(int(i))
print(s)

[SUCTF2019]SignIn

dbt诚不欺我,二进制手果然还是避不开学密码的命运……
搜字符串,交叉引用,然后F5大法……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char v4[16]; // [rsp+0h] [rbp-4A0h] BYREF
char v5[16]; // [rsp+10h] [rbp-490h] BYREF
char v6[16]; // [rsp+20h] [rbp-480h] BYREF
char v7[16]; // [rsp+30h] [rbp-470h] BYREF
char input[112]; // [rsp+40h] [rbp-460h] BYREF
char v9[1000]; // [rsp+B0h] [rbp-3F0h] BYREF
unsigned __int64 v10; // [rsp+498h] [rbp-8h]

v10 = __readfsqword(0x28u);
puts("[sign in]");
printf("[input your flag]: ");
__isoc99_scanf("%99s", input);
sub_96A(input, (__int64)v9);
__gmpz_init_set_str((__int64)v7, (__int64)"ad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35", 16LL);
__gmpz_init_set_str((__int64)v6, (__int64)v9, 16LL);
__gmpz_init_set_str(
(__int64)v4,
(__int64)"103461035900816914121390101299049044413950405173712170434161686539878160984549",
10LL);
__gmpz_init_set_str((__int64)v5, (__int64)"65537", 10LL);
__gmpz_powm(v6, v6, v5, v4);
if ( (unsigned int)__gmpz_cmp(v6, v7) )
puts("GG!");
else
puts("TTTTTTTTTTql!");
return 0LL;
}

sub_96A函数,看起来就是把字符串转成ASCII码的字符串,左移四位然后加上下一位的ASCII码,这样循环到字符串结束。然后emmm是__gmpz_init_set_str这个看起来有点迷的函数,查了一下才知道是高精度算法库,学习一下查阅官方文档吧嘤嘤嘤
https://gmplib.org/manual/
简单来讲有点像pow函数,不过这个函数最后一位指定进制。然后看到65537 (我DNA动了)这么好的数字怎么能不拿来算RSA呢?!!!
大胆猜测一下,这两串数字应该有一个是密文,有一个是n,那么接下来就干他!
kafu分解大法……得到p,q,写脚本……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import *
import gmpy2
p = 366669102002966856876605669837014229419
q = 282164587459512124844245113950593348271
c=0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n=103461035900816914121390101299049044413950405173712170434161686539878160984549
e=65537
N=gmpy2.invert(e,(p-1)*(q-1))
m=pow(c,N,n)
print(hex(m))
#0x73756374667b50776e5f405f68756e647265645f79656172737d
m=[0x73,0x75,0x63,0x74,0x66,0x7b,0x50,0x77,0x6e,0x5f,0x40,0x5f,0x68,0x75,0x6e,0x64,0x72,0x65,0x64,0x5f,0x79,0x65,0x61,0x72,0x73,0x7d]
for i in m:
print(chr(i),end='')

咳咳……但是不要学我瞎猜做题大法,万一不是就白瞎了……

Youngter-drive

我看了一下这个题的题解感觉都很奇怪呢……?
线程的问题我确实是一点不会 (被打),但是函数还是能看得懂的吧。线程的部分大概意思是,创建两个线程交替进行,一个线程是下面这个加密函数,一个线程是仅仅把字符串往前推。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char *__cdecl sub_411940(int a1, int a2)
{
char *result; // eax
char v3; // [esp+D3h] [ebp-5h]

v3 = *(_BYTE *)(a2 + a1);
if ( (v3 < 97 || v3 > 122) && (v3 < 65 || v3 > 90) )
exit(0);
if ( v3 < 97 || v3 > 122 )
{
result = off_418000[0];
*(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 38];
}
else
{
result = off_418000[0];
*(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 96];
}
return result;
}

第一句if限定了只能是大小写字母,后面的if判断,如果是大写字母,写入off[a2[a1]-38],如果是小写,写入off[a2[a1]-96]。这里加密的是输入,也就是说程序里给的”TOiZiZtOrYaToUwPnToBsOaOapsyS”这么一串字符是需要解密的。
那么去找,偶数位字符的索引,就是a2[a1]-38和a2[a1]-96的值。那么我们怎么知道哪个+38哪个+96呢?看题解大多数是反过来的,即认为大写加密后变成小写,小写加密后变成大写(我超,我当时竟然看了半天没看懂,一直是反着写的)。
个人认为这样不太好,万一加密之后不是反过来的,而是有一个码表呢?所以还是爆破大法好(x
自己原来是照着题解写的脚本,不过后来按自己的思路改了一下,这就爆破吧反正,直接无脑爆破(bushi
然后还有一个坑是因为这个函数,dword_418008的值是0x1d,也就是29,判断>=0的话就是30位字符串,所以题目中给的被加密后的字符串实际上少了一位,打出来的flag是29位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void __stdcall StartAddress_0(int a1)
{
while ( 1 )
{
WaitForSingleObject(hObject, 0xFFFFFFFF);
if ( dword_418008 > -1 )
{
sub_41112C(&Source, dword_418008);
--dword_418008;
Sleep(0x64u);
}
ReleaseMutex(hObject);
}
}

哈啊哈哈哈哈哈,看了好多题解都说猜,这怎么能猜呢(bushi当然是要看一下加密字符串后面还有什么玩意啦~
因为这是个常规情况吧,就是加密之后的字符因为码值比较小,所以没办法显示成字符,只能以数字形式表示。跟进去看看,后边果然跟了个0x10,那就加进去就完事了~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
str="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
de="TOiZiZtOrYaToUwPnToBsOaOapsySy"+chr(0x10)
flag=""
for i in range(len(de)):
if i%2==0:
flag+=de[i]
continue
j=str.find(de[i])
for k in range(ord('A'),ord('Z')+1):
if k-38==j:
flag+=chr(k)
continue
for k in range(ord('a'),ord('z')+1):
if k-96==j:
flag+=chr(k)
print(flag)

[WUSTCTF2020]level1

这个很简单,直接上脚本……注意索引为0的地方随便加个啥东西,不然跑出来不对(别问我怎么知道的……)

1
2
3
4
5
6
7
8
s=[0,198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
for i in range(1,20):
if i&1!=0:
s[i]=s[i]//pow(2,i)
else:
s[i]=s[i]//i
for i in s:
print(chr(i),end='')

[ACTF新生赛2020]usualCrypt

base64变表。其实是网上嫖的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding:utf-8 -*-
import base64

Str = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
model = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
for i in range(6,15):
Str[i],Str[i+10] = Str[i+10],Str[i]
Str = ''.join(Str)
enc = "zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9".swapcase()
dec = ""
for i in range(len(enc)):
dec += model[Str.find(enc[i])]
print (dec)
print (Str)
print (base64.b64decode(dec))

[MRCTF2020]Transform

记得翻转s0 (别问我怎么知道的)
后面的字符串长度不够,补一个0,而且看一下代码逻辑就知道,是以len33为索引补全flag,所以肯定有一个索引是0,也就是len33里必然有一个元素是0。

1
2
3
4
5
6
7
8
9
10
11
12
13
cyber=[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,0x3F]
len33=[9,0x0A,0x0F,0x17,0x7,0x18,0x0C,0x6,0x1,0x10,0x3,0x11,0x20,0x1D,0x0B,0x1E,0x1B,0x16,0x4,0x0D,0x13,0x14,0x15,0x2,0x19,5,0x1F,0x8,0x12,0x1A,0x1C,0x0E,0]
s0=[]
ipt=[]
for i in range(32,-1,-1):
s0.append(cyber[i]^len33[i])
s=list(reversed(s0))
for i in range(33):
ipt.append(0)
for i in range(33):
ipt[len33[i]]=s[i]
for i in ipt:
print(chr(i),end='')

相册

我超有病毒不敢做
咳咳,等我攒几道安卓题一起看看,学一下jeb怎么用的 (才不是因为懒)

来填坑了~咳咳!
感觉安卓逆向跟exe也差不多嘛,找关键字符串定位主要函数,然后分析代码逻辑。不过apk可以解压出来一堆文件,在lib里有个so文件比较关键,这个里面可能会有比较重要的信息,一般是个ELF文件,拖进IDA里找字符串就好了,就是java代码真难看(x
这个题忘记录了,反正就是找mail字符,主函数里看base64加密,然后去so文件里找最长的字符串(因为要的是完整邮箱)解密。IDA里最后三个字符串很明显,都是=结尾。

[WUSTCTF2020]level2

??????这个题搞什么???脱壳之后拖进IDA就有flag???我还以为有坑,交上去竟然对了?做的我一脸黑人问号?(不过今天倒是轻松了)

[HDCTF2019]Maze

呜呜呜呜吃到坏的柚子肚子难受睡不着,来摸几道逆向
首先查壳,有壳的,名字很长,改一个短一点的就能脱掉,也不知道是什么原理~
载入IDA,搜关键字符串,定位到主函数,发现反编译不了,是因为跳转到一个不存在的地址(IDA中会有标红,猜测是花指令)。
之前了解过一点花指令hhhhhh,一眼xor然后jnz,标准的花指令格式(bushi),给它nop掉

选中指令-右键keypatch-patch(快捷键ctrl+alt+k)

懒得搜命令就自己在IDA里瞎找,竟然找到了……
下面的call函数先不要nop,因为可能是关键代码。摁d转成字节数据,然后一个一个试(先将第一个数据nop掉再转成代码,不行再将前俩数据nop……)发现nop掉第一条指令之后就正常了,IDA自动将后面的字节数据转为代码。然后选中main函数中所有关键代码,摁p将其声明为函数,然后F5大法……
题目是迷宫题,wsad上下左右,asc_408078值是7,迷宫抠出来长度是70,推测是7X10的迷宫,那么打出来看看……

1
2
3
4
5
6
7
*******+**
******* **
**** **
** *****
** **F****
** ****
**********

初始位置是+,结束位置在F,因为看结束判断条件是(5,-4),也就是F的坐标。
然后手撕就好了
flag{ssaaasaassdddw}

[GWCTF 2019]xxor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int i; // [rsp+8h] [rbp-68h]
int j; // [rsp+Ch] [rbp-64h]
__int64 input[6]; // [rsp+10h] [rbp-60h] BYREF
__int64 v7[6]; // [rsp+40h] [rbp-30h] BYREF

v7[5] = __readfsqword(0x28u);
puts("Let us play a game?");
puts("you have six chances to input");
puts("Come on!");
input[0] = 0LL;
input[1] = 0LL;
input[2] = 0LL;
input[3] = 0LL;
input[4] = 0LL;
for ( i = 0; i <= 5; ++i )
{
printf("%s", "input: ");
a2 = (char **)((char *)input + 4 * i);
__isoc99_scanf("%d", a2);
}
v7[0] = 0LL;
v7[1] = 0LL;
v7[2] = 0LL;
v7[3] = 0LL;
v7[4] = 0LL;
for ( j = 0; j <= 2; ++j )
{
dword_601078 = input[j];
dword_60107C = HIDWORD(input[j]);
a2 = (char **)&unk_601060;
sub_400686(&dword_601078, &unk_601060);
LODWORD(v7[j]) = dword_601078;
HIDWORD(v7[j]) = dword_60107C;
}
if ( (unsigned int)sub_400770(v7, a2) != 1 )
{
puts("NO NO NO~ ");
exit(0);
}
puts("Congratulation!\n");
puts("You seccess half\n");
puts("Do not forget to change input to hex and combine~\n");
puts("ByeBye");
return 0LL;
}

戳进去sub_400770看看,是个判断,一大堆数字,还有负的,应该是IDA把变量识别为singed的问题,数字本身应该是unsinged,看了下别人转出来都是正的(呜呜呜呜呜呜呜呜),不过应当无影响
用这个方程组把数组a解出来,然后把前面的加密过程逆着写回去就可以了 鹅鹅鹅,我先做了才看见RX的hint说用z3,我直接手解方程组了
当时看见一堆移位异或,还想着是不是什么高深的加密算法,应该不会是倒着写回去就可以的那种,看了题解, 呃好吧,还真是倒着写回去就行(bushi……
a2前面写了一堆没用的赋值,但最后运算的时候用的还是unk_601060,点进去看下,是2,2,3,4中间一堆0,应该是long long的锅,总之a2=[2,2,3,4]。
本来用python写了,但是这个玩意应该是有溢出的舍位,但是python不会溢出啊啊啊啊啊啊啊,打出来好长一串 (裂开),我也不会用python限制数字位数,那就老老实实用C吧……注意小端序就好了,因为我们这是把他原本的long long拆成两个int。
对比了一下代码,我的代码跟别人写的题解都一样,懒得python转c了,直接嫖代码……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main()
{
unsigned int a[6] = { 3746099070, 550153460, 3774025685, 1548802262, 2652626477, 2230518816 };
unsigned int a2[4] = { 2,2,3,4 };
unsigned int v3, v4;
int v5;
for (int j = 0; j <= 4; j += 2) {
v3 = a[j];
v4 = a[j + 1];
v5 = 1166789954 * 64;
for (int i = 0; i <= 0x3F; ++i) {
v4 -= (v3 + v5 + 20) ^ ((v3 << 6) + a2[2]) ^ ((v3 >> 9) + a2[3]) ^ 0x10;
v3 -= (v4 + v5 + 11) ^ ((v4 << 6) + *a2) ^ ((v4 >> 9) + a2[1]) ^ 0x20;
v5 -= 1166789954;
}
a[j] = v3;
a[j + 1] = v4;
}

for (int i = 0; i < 6; ++i)
/*将整型数组作为字符输出,注意计算机小端排序*/
printf("%c%c%c", *((char*)&a[i] + 2), *((char*)&a[i] + 1), *(char*)&a[i]);
return 0;
}

[MRCTF2020]Xor

非常白给异或题~直接反编译主函数会报错,进去报错的那个函数然后反编译,再反编译主函数就可以了。(虽然不明白原理是什么)虽然前面写了一大堆代码,但是直接看判断条件就好了,判断一个长度之后跟索引异或,直接上脚本。

1
2
3
s=chr(0x4d)+r'SAWB~FXZ:J:`tQJ"N@ bpdd}8g'
for i in range(len(s)):
print(chr(i^ord(s[i])),end='')

[FlareOn4]IgniteMe

白给题,直接上脚本
注意这里异或用的是明文
然后就是学习了一下抠数字的快捷方法……

1
2
3
4
5
6
7
8
9
f2                   修改多处同名变量
alt 鼠标左键点击添加多个光标
Ctrl+Alt+上下 添加多个光标
shift+alt+i 选中一段摁住,每行末尾出现光标
ctrl+shift+L
ctrl+f2 在页面中出现这个词的不同地方都出现光标
shift+alt 复制一行
ctrl+U 取消任何光标操作
alt+enter 上下移动一行
1
2
3
4
5
6
7
8
s=[0xd,0x26,0x49,0x45,0x2A,0x17,0x78,0x44,0x2B,0x6C,0x5D,0x5E,0x45,0x12,0x2f,0x17,0x2b,0x44,0x6F,0x6E,0x56,9,0x5f,0x45,0x47,0x73,0x26,0x0A,0xd,0x13,0x17,0x48,0x42,1,0x40,0x4D,0x0C,2,0x69]
j=4
string=[]
for i in range(len(s)-1,-1,-1):
string.append(s[i]^j)
j=string[-1]
for i in range(len(string)-1,-1,-1):
print(chr(string[i]),end='')

[MRCTF2020]hello_world_go

盲猜花指令,IDA进去红一片 ,明天再看看嘤嘤嘤

草,猜错了,是go语言。。。但是没啥用,F5进去之后有个叫aFlagHelloWorld的变量,flag就在这里。。。

[WUSTCTF2020]level3

一个base64变表,啊啊啊啊,对着加密函数看了半天,明明是标准实现,晕了……看了题解才知道前面还有对base64进行变表的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 O_OLookAtYou()
{
__int64 result; // rax
char v1; // [rsp+1h] [rbp-5h]
int i; // [rsp+2h] [rbp-4h]

for ( i = 0; i <= 9; ++i )
{
v1 = base64_table[i];
base64_table[i] = base64_table[19 - i];
result = 19 - i;
base64_table[result] = v1;
}
return result;
}

在这贴个base64标准实现吧……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void encodeBase64(char* str,int len,char** in){
char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//读取3个字节zxc,转换为二进制01111010 01111000 01100011
//转换为4个6位字节,011110 100111 100001 100011
//不足8位在前补0,变成00011110 00100111 00100001 00100011
//若剩余的字节数不足以构成4个字节,补等号
int encodeStrLen = 1 + (len/3)*4 ,k=0;
encodeStrLen += len%3 ? 4 : 0;
char* encodeStr = (char*)(malloc(sizeof(char)*encodeStrLen));
for(int i=0;i<len;i++){
if(len - i >= 3){
encodeStr[k++] = base64[(unsigned char)str[i]>>2];
encodeStr[k++] = base64[((unsigned char)str[i]&0x03)<<4 | (unsigned char)str[++i]>>4];
encodeStr[k++] = base64[((unsigned char)str[i]&0x0f)<<2 | (unsigned char)str[++i]>>6];
encodeStr[k++] = base64[(unsigned char)str[i]&0x3f];
}else if(len-i == 2){
encodeStr[k++] = base64[(unsigned char)str[i] >> 2];
encodeStr[k++] = base64[((unsigned char)str[i]&0x03) << 4 | ((unsigned char)str[++i] >> 4)];
encodeStr[k++] = base64[((unsigned char)str[i]&0x0f) << 2];
encodeStr[k++] = '=';
}else{
encodeStr[k++] = base64[(unsigned char)str[i] >> 2];
encodeStr[k++] = base64[((unsigned char)str[i] & 0x03) << 4]; //末尾补两个等于号
encodeStr[k++] = '=';
encodeStr[k++] = '=';
}
}
encodeStr[k] = '\0';
*in = encodeStr;
}

/**
* 解码既编码的逆过程,先找出编码后的字符在编码之前代表的数字
* 编码中将3位个字符变成4个字符,得到这4个字符的每个字符代表的原本数字
* 因为在编码中间每个字符用base64码表进行了替换,所以这里要先换回来
* 在对换回来的数字进行位运算使其还原成3个字符
*/
void decodeBase64(char* str,int len,char** in){
char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char ascill[129];
int k = 0;
for(int i=0;i<64;i++){
ascill[base64[i]] = k++;
}
int decodeStrlen = len / 4 * 3 + 1;
char* decodeStr = (char*)malloc(sizeof(char)*decodeStrlen);
k = 0;
for(int i=0;i<len;i++){
decodeStr[k++] = (ascill[str[i]] << 2) | (ascill[str[++i]] >> 4);
if(str[i+1] == '='){
break;
}
decodeStr[k++] = (ascill[str[i]] << 4) | (ascill[str[++i]] >> 2);
if(str[i+1] == '='){
break;
}
decodeStr[k++] = (ascill[str[i]] << 6) | (ascill[str[++i]]);
}
decodeStr[k] = '\0';
*in = decodeStr;
}

然后贴这个题的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enc="d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD=="
model='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
#model:标准码表
table=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
#table:现码表
for i in range(10):
v=table[i]
table[i]=table[19-i]
table[19-i]=v

import base64
dec=''
for i in range(len(enc)-2):
dec += model[table.index(enc[i])]
dec+='=='
print (base64.b64decode(dec))

最后贴个base64变表的解码伪代码……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enc="密文"
model='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
#model:标准码表,不变
table=list('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/')
#table:更改后的码表
'''
对table变换,更改为所用码表
'''
import base64
dec=''
for i in range(len(enc)):#此处视情况,根据等号个数减去相应长度
dec += model[table.index(enc[i])]

dec+='=='#若原密文有等号,则在此处添加等号
print (base64.b64decode(dec))

[WUSTCTF2020]Cr0ssfun

很少见的抠ASCII码就能出来的题目……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
a1=[]
for i in range(33):
a1.append(0)
a1[10]=112
a1[13]=64
a1[0]=119
a1[6] = 50
a1[22] = 115
a1[31] = 110
a1[12] = 95
a1[13] = 64
a1[3] = 102
a1[26] = 114
a1[20] = 101
a1[7] = 48
a1[23]=101
a1[11]=112
a1[30]=117
a1[16]=95
a1[15] = 100
a1[8] = 123
a1[18] = 51
a1[28] = 95
a1[21] = 114
a1[2] = 116
a1[9] = 99
a1[32] = 125
a1[19] = 118
a1[5] = 48
a1[14] = 110
a1[4] = 50
a1[29] = 102
a1[17] = 114
a1[17] = 114
a1[24] = 95
a1[1] = 99
a1[25] = 64
a1[27] = 101
for i in a1:
print(chr(i),end='')

[BJDCTF2020]BJD hamburger competition(.net逆向)

看来很有必要了解一下.net和安卓逆向…… (懒,先咕……)

甩个目录:attachment\BJD hamburger competition_Data\Managed\Assembly-CSharp.dll
C#源代码就在这里
关键函数:

1
2
3
4
5
6
7
8
9
10
else if (name == "汉堡顶" && Init.spawnCount == 5)
{
Init.secret ^= 127;
string str = Init.secret.ToString();
if (ButtonSpawnFruit.Sha1(str) == "DD01903921EA24941C26A48F2CEC24E0BB0E8CC7")
{
this.result = "BJDCTF{" + ButtonSpawnFruit.Md5(str) + "}";
Debug.Log(this.result);
}
}

可以看到就是一个字符串的哈希值,SHA1已经给出来了,然后去看看ButtonSpawnFruit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ButtonSpawnFruit : MonoBehaviour
{
// Token: 0x0600000A RID: 10 RVA: 0x00002110 File Offset: 0x00000310
public static string Md5(string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str);
byte[] array = MD5.Create().ComputeHash(bytes);
StringBuilder stringBuilder = new StringBuilder();
foreach (byte b in array)
{
stringBuilder.Append(b.ToString("X2"));
}
return stringBuilder.ToString().Substring(0, 20);
}

取了前20位的MD5,找个在线网站解一下SHA1,然后跑一下MD5,注意转成大写就好了,python都用的小写……

1
2
3
4
5
import hashlib
s='1001'
print(hashlib.md5(s.encode('utf8')).hexdigest()[0:20])
s2='b8c37e33defde51cf91e'
print(s2.upper())

[FlareOn6]Overlong

我真傻,真的,我竟然少写一个else,好多字符跑不出来,绝了……
看了下题解,这个好像是修改长度就行的…… 又小丑了……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
encry=[0xE0,0x81,0x89,0xC0,0xA0,0xC1,0xAE,0xE0,0x81,0xA5,0xC1,0xB6,0xF0,0x80,0x81,0xA5,0xE0,0x81,0xB2,0xF0,0x80,0x80,0xA0,0xE0,0x81,0xA2,0x72,0x6F,0xC1,0xAB,0x65,0xE0,0x80,0xA0,0xE0,0x81,0xB4,0xE0,0x81,0xA8,0xC1,0xA5,0x20,0xC1,0xA5,0xE0,0x81,0xAE,0x63,0xC1,0xAF,0xE0,0x81,0xA4,0xF0,0x80,0x81,0xA9,0x6E,0xC1,0xA7,0xC0,0xBA,0x20,0x49 ,0xF0,0x80,0x81,0x9F,0xC1,0xA1,0xC1,0x9F,0xC1,0x8D,0xE0,0x81,0x9F,0xC1,0xB4,0xF0,0x80,0x81,0x9F,0xF0,0x80 ,0x81,0xA8,0xC1,0x9F,0xF0,0x80,0x81,0xA5,0xE0,0x81,0x9F,0xC1,0xA5,0xE0,0x81,0x9F,0xF0,0x80,0x81,0xAE,0xC1,0x9F,0xF0,0x80,0x81,0x83,0xC1,0x9F,0xE0,0x81,0xAF,0xE0,0x81,0x9F,0xC1,0x84,0x5F,0xE0,0x81,0xA9,0xF0,0x80 ,0x81,0x9F,0x6E ,0xE0,0x81,0x9F,0xE0,0x81,0xA7,0xE0,0x81,0x80 ,0xF0,0x80 ,0x81,0xA6,0xF0,0x80,0x81,0xAC,0xE0,0x81,0xA1,0xC1,0xB2,0xC1,0xA5,0xF0,0x80 ,0x80 ,0xAD,0xF0,0x80 ,0x81,0xAF,0x6E ,0xC0,0xAE,0xF0,0x80 ,0x81,0xA3,0x6F ,0xF0,0x80 ,0x81,0xAD]
text=[]
i=0
while i<len(encry):
if encry[i]>>3==30:
text.append(encry[i+3]&0x3f|(encry[i+2]&0x3f)<<6)
v3=4
elif encry[i]>>4==14:
text.append(encry[i+2]&0x3f|(encry[i+1]&0x3f)<<6)
v3=3
elif encry[i]>>5==6:
text.append(encry[i+1]&0x3f|(encry[i]&0x1f)<<6)
v3=2
else:
text.append(encry[i])
v3=1
i+=v3

for i in text:
print(chr(i),end='')

[ACTF新生赛2020]Oruga

最大的教训:看见四个字符还有一堆数据的一定要想到迷宫

迷宫题,真的很离谱啊这个……这个是走一次遇到障碍物停,不是一步一步走的
搜了下题解都是手动走迷宫的……我干,手动也太强了我一定要学会写深搜走迷宫啊啊啊啊啊
但是现在数据结构还在摆烂,所以就咕……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__ __ __ __ 35 __ __ __ __ __ __ __ 35 35 35 35 
__ __ __ 35 35 __ __ __ 79 79 __ __ __ __ __ __
__ __ __ __ __ __ __ __ 79 79 __ 80 80 __ __ __
__ __ __ 76 __ 79 79 __ 79 79 __ 80 80 __ __ __
__ __ __ 76 __ 79 79 __ 79 79 __ 80 __ __ __ __
__ __ 76 76 __ 79 79 __ __ __ __ 80 __ __ __ __
35 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
__ __ __ __ __ __ __ __ __ __ __ __ 35 __ __ __
__ __ __ __ __ __ 77 77 77 __ __ __ 35 __ __ __
__ __ __ __ __ __ __ 77 77 77 __ __ __ __ 69 69
__ __ __ 48 __ 77 __ 77 __ 77 __ __ __ __ 69 __
__ __ __ __ __ __ __ __ __ __ __ __ __ __ 69 69
84 84 84 73 __ 77 __ 77 __ 77 __ __ __ __ 69 __
__ 84 __ 73 __ 77 __ 77 __ 77 __ __ __ __ 69 __
__ 84 __ 73 __ 77 __ 77 __ 77 33 __ __ __ 69 69
1

[FlareOn3]Challenge1

emmm还是base64变表,没啥好说的,用以前的脚本跑跑就好了。

[Zer0pts2020]easy strcmp(hook)

要学动调啊啊啊啊啊啊啊啊啊啊
草,,,裂开,,,,,看了好久才看懂这题,直接改DLL地址真的太强了……
先咕了,明天再写(bushi,这个题给我的震撼实在太过强烈…… 主要是网上所有题解都用同一段代码就nm离谱 翻到一个外国人写的wp,然后再结合那个全网复制粘贴的wp才看懂到底怎么回事……
wp先贴这里

1
2
3
4
5
6
7
8
9
10
#外国选手的
v = [0x42, 0x09, 0x4a, 0x49, 0x35, 0x43, 0x0a, 0x41, 0xf0, 0x19, 0xe6, 0x0b, 0xf5, 0xf2, 0x0e, 0x0b, 0x2b, 0x28, 0x35, 0x4a, 0x06, 0x3a, 0x0a, 0x4f]
res = ''
pattern = '********CENSORED********'
for i in range(len(v)):
if i in (9, 11, 13, 14):
res += (chr((ord(pattern[i]) + v[i] + 1) % 256))
else:
res += (chr((ord(pattern[i]) + v[i]) % 256))
print("zer0pts{" + res + "}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#全网复制粘贴的(x
#不过不得不说写的是真的很简洁
enc = "********CENSORED********"
m = [0x410A4335494A0942, 0x0B0EF2F50BE619F0, 0x4F0A3A064A35282B]

import binascii

flag = b''
for i in range(3):
p = enc[i*8:(i+1)*8]
a = binascii.b2a_hex(p.encode('ascii')[::-1])
b = binascii.a2b_hex(hex(int(a,16) + m[i])[2:])[::-1]
print(p,a,b)
flag += b
print (flag)

因为是有进位的问题,题目里是long直接加的,分组加的话有的进位就舍弃掉了,外国选手是动调发现这几个索引位置加了1,看了下bbs里track说他是看出来哪里进位的233~不过大概也就是,ASCII码大写字符是0x41到0x5a,那些f,e打头的肯定溢出啊

[UTCTF2020]basic-re

拖进IDA就有flag,交上去竟然对了……

crackMe

代码逻辑都很好理解,花指令也很好认,主要是怎么获得byte_416050数组里拿来跟’dbappsec’异或的数据。
看了很多题解都说是动调,然后我个大傻子动调一直把jz改成jmp,这样有点小问题,改成jnz就可以了。然后树师傅告诉我这个其实可以静态分析出来,具体做法就是抠byte_416050里的数据,然后根据加密过程写脚本。不过byte_416050里的数据其实还是动调得出来的 (我个大菜逼后来写脚本自己复现的时候才想到呜呜呜)
树师傅说这个玩意是rc4,好的,我又双叒叕要开始挖坑了……

1
2
3
4
5
6
7
8
9
10
11
12
enc=[0x5E,0xBE,0x4D,0x43,0x24,0xEB,0x58,0xE4 ,0xC2,0x5C,0xBD,0xC4,0xAB,0x39,0x1D,0x73,0x27,0xD7,0x88,0xB8,0xF6,0xF9,0x01,0xF4 ,0x6D,0xEF,0x00,0x15,0x8C,0xD5,0x98,0x11,0xA5,0x25,0x36,0x1A,0x21,0x47,0xB4,0x50 ,0xDA,0xBF,0x31,0x32,0x70,0xC3,0x60,0xB9,0xDB,0x81,0xAD,0xF2,0xE0,0xC5,0xAC,0xC0 ,0x6F,0x05,0xB3,0x51,0xE7,0xA6,0xAE,0x6B,0x8F,0x7D,0xCF,0x7B,0xA3,0x56,0x5A,0x9A ,0xD4,0x76,0x42,0x9F,0x53,0x80,0xB5,0x0F,0xA0,0xCB,0x8B,0xA1,0x13,0x2D,0x85,0x93 ,0xFE,0xCC,0x1B,0xF0,0x54,0x61,0x20,0x1C,0xFB,0x7F,0x17,0x64,0x4A,0x9D,0xD0,0x03 ,0xA8,0x2F,0x37,0x30,0x3D,0x33,0xE2,0x83,0x8E,0xD9,0xB7,0x18,0xF7,0x59,0xDC,0x0B ,0x77,0xAF,0xEA,0xB1,0x10,0x35,0x7C,0x55,0x4B,0x74,0x26,0xB2,0x8D,0x8A,0x91,0x97 ,0x89,0xE8,0xD2,0x79,0x3C,0x44,0x40,0x5D,0xCE,0x9E,0x9C,0x3E,0x75,0x29,0x72,0x2B ,0xBB,0x1E,0x6A,0x28,0x2E,0x62,0xDF,0xA2,0x02,0x09,0xBA,0xC6,0x3A,0xB6,0x4E,0x7A ,0x71,0x38,0x99,0x65,0xAA,0x9B,0x4C,0xE6,0x0C,0x6C,0xCD,0xA7,0xE3,0x16,0xD3,0x19 ,0x49,0xF5,0x12,0xC8,0x41,0xDE,0x06,0x07,0x95,0xD8,0xFA,0x66,0x2A,0x7E,0x94,0x0D ,0x48,0x90,0xCA,0x04,0xED,0x67,0xE5,0x4F,0x2C,0x1F,0x14,0xC1,0xC9,0xA4,0xF8,0x08 ,0xE1,0xB0,0xEC,0xE9,0xA9,0x34,0xDD,0x57,0x23,0x87,0xC7,0xEE,0x3B,0x5B,0x46,0x69 ,0x84,0x86,0x0E,0x96,0x78,0xD1,0xFD,0xFF,0x68,0xBC,0x63,0xF3,0xD6,0xFC,0x82,0x3F ,0x92,0x52,0x6E,0x5F,0x22,0xF1,0x0A,0x45]
v5,v11,v10=0,0,0
while v5<8:
v11+=1
v10+=enc[v11]
v12=enc[v11]
v10&=0xff
v7=enc[v10]
enc[v10]=v12
enc[v11]=v7
print(hex(enc[(v7+v12)&0xff]),end=',')
v5+=1
1
2
3
4
5
6
7
import hashlib
s1='dbappsec'
passwd = ""
byte_416050 = [0x2a, 0xd7, 0x92, 0xe9, 0x53, 0xe2, 0xc4, 0xcd]
for i in range(8):
passwd += hex(byte_416050[i]^ord(s1[i]))[2:]
print(hashlib.md5(passwd.encode('utf-8')).hexdigest())

[ACTF新生赛2020]Universe_final_answer(z3)

emmm就是z3解方程,直接上脚本,但是最后的flag不是这个,输入程序进去跑一下,会多出来个‘42’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from z3 import *
s = Solver()
v1 =Int('v1')
v2 =Int('v2')
v3 =Int('v3')
v4 =Int('v4')
v5 =Int('v5')
v6 =Int('v6')
v7 =Int('v7')
v8 =Int('v8')
v9 =Int('v9')
v11=Int('v11')
s.add(-85 * v9 + 58 * v8 + 97 * v6 + v7 + -45 * v5 + 84 * v4 + 95 * v2 - 20 * v1 + 12 * v3 == 12613)
s.add(30 * v11 + -70 * v9 + -122 * v6 + -81 * v7 + -66 * v5 + -115 * v4 + -41 * v3 + -86 * v1 - 15 * v2 - 30 * v8 == -54400)
s.add(-103 * v11 + 120 * v8 + 108 * v7 + 48 * v4 + -89 * v3 + 78 * v1 - 41 * v2 + 31 * v5 - (v6 *64) - 120 * v9 == -10283)
s.add(71 * v6 + (v7 *128) + 99 * v5 + -111 * v3 + 85 * v1 + 79 * v2 - 30 * v4 - 119 * v8 + 48 * v9 - 16 * v11 == 22855)
s.add(5 * v11 + 23 * v9 + 122 * v8 + -19 * v6 + 99 * v7 + -117 * v5 + -69 * v3 + 22 * v1 - 98 * v2 + 10 * v4 == -2944)
s.add(-54 * v11 + -23 * v8 + -82 * v3 + -85 * v2 + 124 * v1 - 11 * v4 - 8 * v5 - 60 * v7 + 95 * v6 + 100 * v9 == -2222)
s.add(-83 * v11 + -111 * v7 + -57 * v2 + 41 * v1 + 73 * v3 - 18 * v4 + 26 * v5 + 16 * v6 + 77 * v8 - 63 * v9 == -13258)
s.add(81 * v11 + -48 * v9 + 66 * v8 + -104 * v6 + -121 * v7 + 95 * v5 + 85 * v4 + 60 * v3 + -85 * v2 + 80 * v1 == -1559)
s.add(101 * v11 + -85 * v9 + 7 * v6 + 117 * v7 + -83 * v5 + -101 * v4 + 90 * v3 + -28 * v1 + 18 * v2 - v8 == 6308)
s.add(99 * v11 + -28 * v9 + 5 * v8 + 93 * v6 + -18 * v7 + -127 * v5 + 6 * v4 + -9 * v3 + -93 * v1 + 58 * v2 == -1697)

if s.check() == sat:
result = s.model()

print(result)

a1=[]
for i in range(10):
a1.append(0)
v1 = 48
v6 = 95
v2 = 70
v4 = 82
v11 = 64
v3 = 117
v5 = 84
v7 = 121
v9 = 119
v8 = 55
a1[1]=v1
a1[0]=v2
a1[2]=v3
a1[3]=v4
a1[4]=v5
a1[6]=v6
a1[5]=v7
a1[7]=v8
a1[8]=v9
a1[9]=v11
for i in a1:
print(chr(i),end='')

[WUSTCTF2020]level4(二叉树遍历算法)

忘了,这题竟然没看过……俩二叉树遍历
看来还是得先跑一下程序看看再逆……输出来一个中序遍历一个后序遍历的结果,在网上嫖算法跑一下(bushi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h> 
char post[] = {"20f0Th{2tsIS_icArE}e7__w"};
char mid[] = {"2f0t02T{hcsiI_SwA__r7Ee}"};
void pre(int root, int start, int end)
{
if(start > end)
return ;
int i = start;
while(i < end && mid[i] != post[root]) i++; //定位根在中序的位置
printf("%c",mid[i]); //访问当前处理的树的根
pre(root-1-(end-i), start, i - 1); //递归处理左子树
pre(root-1, i + 1, end); //递归处理右子树
}

int main()
{
pre(24, 0, 24);
return 0;
}

[网鼎杯 2020 青龙组]singal

VM逆向,裂开,看不懂……
草了,第一次见识angr这种东西,嫖一下树师傅的代码
by the way:angr这个库搜了下安装教程全是linux,开开心心在kali上装好之后怀着激动的心情一用,发现自己完全忘了这个题的文件是exe,又爬回windows装angr……装了一下午一直报错,有点绝望就收拾东西准备去操场打个卡。准备走的时候突然想到是不是跟梯子有关系,于是连忙打开电脑关了梯子,直接pip install angr就装好了……md,我是小丑……
但是我不理解,这库在什么时候能用什么时候不能用呢?那就……挖个坑吧~(bushi

1
2
3
4
5
6
import angr
proj = angr.Project('signal.exe',auto_load_libs = False)
state = proj.factory.entry_state() # 根据镜像创建进程
simgr = proj.factory.simgr(state) # 创建一个模拟器,用来模拟执行求解
simgr.explore(find = 0x40179E,avoid = 0x401539) # 成功的地址和失败的地址
print (simgr.found[0].posix.dumps(0)) # 把要找的结果输出

复现,大概有点理解VM了。by the way,IDA里是什么数据类型,写脚本就用什么数据类型,不然会出锅……我tm把程序变量名都改成WP里的变量名一个一个对比,结果发现是char类型的锅,用unsigned char就好了……半年没用C语言真的不会写程序了都……
IDA里直接贴的代码,有点丑,就这样吧懒得修了hhh

首先是根据case7找对比的字符,即密文。然后去找opcode调用的索引,然后根据索引逆序写解密。为什么不能直接写逆序而要先去找调用的索引?因为opcode根据case的不同有不同的偏移,从后往前找调用索引的话要先知道前一个opcode的偏移是多少,但是要去找前一个又要找前一个,hhh,所以只能先找索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<stdio.h>
int main()
{
int opcode[]={0xa,0x4,0x10,0x8,0x3,0x5,0x1,0x4,0x20,0x8,0x5,0x3,0x1,0x3,0x2,0x8,0xb,0x1,0xc,0x8,0x4,0x4,0x1,0x5,0x3,0x8,0x3,0x21,0x1,0xb,0x8,0xb,0x1,0x4,0x9,0x8,0x3,0x20,0x1,0x2,0x51,0x8,0x4,0x24,0x1,0xc,0x8,0xb,0x1,0x5,0x2,0x8,0x2,0x25,0x1,0x2,0x36,0x8,0x4,0x41,0x1,0x2,0x20,0x8,0x5,0x1,0x1,0x5,0x3,0x8,0x2,0x25,0x1,0x4,0x9,0x8,0x3,0x20,0x1,0x2,0x41,0x8,0xc,0x1,0x7,0x22,0x7,0x3f,0x7,0x34,0x7,0x32,0x7,0x72,0x7,0x33,0x7,0x18,0x7,0xffffffa7,0x7,0x31,0x7,0xfffffff1,0x7,0x28,0x7,0xffffff84,0x7,0xffffffc1,0x7,0x1e,0x7,0x7a};
unsigned char v4[]={0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xffffffa7,0x31,0xfffffff1,0x28,0xffffff84,0xffffffc1,0x1e,0x7a};
int index[100]={1,3,4,6,7,9,10,12,13,15,16,17,18,19,20,22,23,25,26,28,29,30,31,32,33,35,36,38,39,41,42,44,45,46,47,48,49,51,52,54,55,57,58,60,61,63,64,66,67,69,70,72,73,75,76,78,79,81,82,83,84};
unsigned char flag[200];
int vm_eip;
int m=15,z=15,x=15,v7=15,v5;
for(int i=60;i>=0;i--)
{
vm_eip=index[i];
switch ( opcode[vm_eip] )
{
case 1:
--z;
--x;
v5=v4[z];
break;
case 2: // 2:rot(v)
flag[x] = v5 - opcode[vm_eip + 1];
break;
case 3: // 3:rot(-v)
flag[x] = v5 + opcode[vm_eip + 1];
break;
case 4: // 4:xor
flag[x] = opcode[vm_eip + 1] ^ v5;
break;
case 5: // 5:mult
flag[x] = v5 / opcode[vm_eip + 1];
break;
case 6: // 6:nop
break;
case 8: // 8:mov
v5 = flag[--m];

break;
case 11: // 11:rot(-1)
flag[x] = v5 + 1;
break;
case 12: // 12:rot(1)
flag[x] = v5 - 1;
break;
}
}
printf("%s",flag);


return 0;
}

firmware(固件逆向)

装包装了一晚上…… 要死最后还是拆出来了,太感动了呜呜呜呜呜
kali整了半天,最后还是屈服于ubuntu了……
谷歌yyds,ubuntu的报错微软浏览器根本搜不到,还是谷歌救我狗命……

[GUET-CTF2019]number_game

裂开……当时没理解前边两个函数在做什么变换,后面赋值和检查操作猜出来应该是数独,自己手动解出来交上去不对,去搜题解才知道前面那两个没看懂的函数是二叉树遍历……昨天晚上才给室友讲了中序遍历,那两个遍历函数就是一个先序一个中序把输入顺序重新排布了一下,我竟然没反应过来,太小丑了,我还奇怪这一堆递归是在干什么……
数据结构不能再摆烂了呜呜呜呜呜二叉树手动走的,下标0-9构造二叉查找树,然后手动中序遍历一下,下标打出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
maze=[0x31,0x34,0x23,0x32,0x33,0x33,0x30,0x23,0x31,0x23,0x30,0x23,0x32,0x33,0x23,0x23,0x33,0x23,0x23,0x30,0x34,0x32,0x23,0x23,0x31]
for i in range(len(maze)):
if i%5==0:
print()
if maze[i]==0x23:
print("#",end=' ')
else:
print(chr(maze[i]),end=' ')

'''
1 4 # 2 3
3 0 # 1 #
0 # 2 3 #
# 3 # # 0
4 2 # # 1
'''
f='0421421430'
flag=''
table=[7,3,8,1,9,4,0,5,2,6]
for i in range(len(f)):
flag+=f[table.index(i)]
print(flag)

特殊的 BASE64

变表,没啥好说的,抄脚本跑就好了……

findKey

1
2
3
s1='0kk`d1a`55k222k2a776jbfgd`06cjjb'
for i in s1:
print(chr(ord(i)^ord('S')),end='')
1
2
3
4
enc='123321'
s2=[0x57,0x5E,0x52,0x54,0x49,0x5F,0x01,0x6D ,0x69,0x46,0x02,0x6E,0x5F,0x02,0x6C,0x57,0x5B,0x54,0x4C]
for i in range(len(s2)):
print(chr(s2[i]^ord(enc[i%6])),end='')

[GXYCTF2019]simple CPP

看了一晚上,属实是麻中麻中麻,最后发现复制错了一个数据,woc………………不想再看了,代码扔这吧……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from z3 import *

x,y,z,w=BitVecs('x y z w',64)

s=Solver()

s.add((~x)&z==0x11204161012)
s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==0x3E3A4717050F791F)
s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==0x8020717153E3013)
s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==0x3E3A4717373E7F1F)
s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|0xC00020130082C0C))

s.check()
m = s.model()
for i in m:
print("%s = 0x%x"%(i,m[i].as_long()))flag=[0x3E,0x3A,0x46,0x05,0x33,0x28,0x6F,0x0D,
0x8C,0x00,0x8A,0x09,0x78,0x49,0x2C,0xAC,
0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06]


y = 0x0c00020130082c0c
x = 0x3e3a460533286f0d
w = 0x32310600
z = 0x08020717153e3013
s='i_will_check_is_debug_or_not'
flag=[0x3e,0x3a,0x46,0x05,0x33,0x28,0x6f,0x0d,
0x0c,0x00,0x02,0x01,0x30,0x08,0x2c,0x0c,
0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06]

t='We1l_D0ne!P0or_algebra_am_i'

for i in range(len(t)):
print(hex(ord(t[i])^ord(s[i])),end=',')

[GWCTF 2019]re3

神奇的题,忘了写了,那就~咕……

[FlareOn5]Minesweeper Championship Registration

属于是打开就有flag……

[网鼎杯 2020 青龙组]jocker

麻中麻中麻中麻中麻中麻一个简单的SMC,解密之后直接分析就好了,然后看伪代码。蚌埠住了,,,都是靠猜的……

1
2
3
4
5
6
7
buff='hahahaha_do_you_find_me?'
a=[0x0E,0x0D,0x09,0x06,0x13,0x05,0x58,0x56,0x3E,0x06,0x0C,0x3C,0x1F,0x57,0x14,0x6B,0x57,0x59,0x0D]
for i in range(len(a)):
print(chr(ord(buff[i])^a[i]),end='')
b='%tp&:'
for i in range(5):
print(chr(ord(b[i])^0x3a^ord('}')),end='')

[2019红帽杯]xx

非常屑的题……转小端序的时候有一个数据小于16所以一个数据中间少打个0,nm这个错误我查了一晚上。啥也不说了,上脚本转大小端序,我真就不信了。
话说这两个过程竟然是一个加密一个解密,不过我不理解为什么解密过程不用逆序……(试了一下逆序也可以……

1
2
3
4
5
6
7
8
9
10
enc=[206, 188, 64, 165, 178, 244, 231, 178, 157, 169, 18, 18, 200, 174, 91, 16, 6, 61, 29, 215, 248, 220, 220, 112]
dec=[206, 188, 64, 107, 124, 58, 149, 192, 239, 155, 32, 32, 145, 247, 2, 53, 35, 24, 2, 200, 231, 86, 86, 250]
for i in range(24):
for j in range(i//3):
enc[i]^=enc[j]
print(enc)
for i in range(23,-1,-1):
for j in range(i//3):
dec[i]^=dec[j]
print(dec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
#include <stdint.h>


#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))


void xxtea(uint32_t* v, int n, uint32_t* key)
{
uint32_t y, z, sum;
unsigned p, rounds, e;

if (n > 1) // encrypt
{
rounds = 6 + 52/n;
sum = 0;
z = v[n-1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++)
{
y = v[p+1];
z = v[p] += MX;
}
y = v[0];
z = v[n-1] += MX;
}
while (--rounds);
}
else if (n < -1) // decrypt
{
n = -n;
rounds = 6 + 52/n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--)
{
z = v[p-1];
y = v[p] -= MX;
}
z = v[n-1];
y = v[0] -= MX;
sum -= DELTA;
}
while (--rounds);
}
}

int main()
{
uint32_t v[6] = {0x40cea5bc,0xe7b2b2f4,0x129d12a9,0x5bc810ae,0x1d06d73d,0xdcf870dc};
uint32_t k[4]= {0x67616c66,0,0,0};
int n = 6;
char *s;
s=(char*)v;

xxtea(v, -n, k);

for(int i=0;i<19;i++)
printf("%c",(char)s[i]);


return 0;
}

[ACTF新生赛2020]SoulLike

代码太长反编译挂了,去配置文件里改了max_funcsize就能反编译出来
不会用pwntools只能复制代码用C强行爆了(捂嘴
怪不得说逆向手也得会点pwn呜呜呜(不就是懒得学pwn
中间的代码太长就不贴了,就是把IDA里的代码复制出来,然后用多光标简单处理一下(结尾u去掉,前面加0X)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<stdio.h>
char a1[11];
void sub(char* a1)
{
……
}

int main(){
int i; // [rsp+1Ch] [rbp-44h]
int v3[14],j,x; // [rsp+20h] [rbp-40h]
char t[20];
v3[0] = 126;
v3[1] = 50;
v3[2] = 37;
v3[3] = 88;
v3[4] = 89;
v3[5] = 107;
v3[6] = 53;
v3[7] = 110;
v3[8] = 0;
v3[9] = 19;
v3[10] = 30;
v3[11] = 56;


for ( i = 0; i <= 11;++i)
{
for(j=0;j<0x7e;j++)
{
for(x=0;x<i;x++)
a1[x]=t[x];

a1[i]=j;
sub(a1);
if(v3[i] == a1[i] )
t[i]=j;
}
}
printf("%s",t);
return 0;
}

[FlareOn5]Ultimate Minesweeper

C#,难顶。把检测错误的代码注释掉,然后跑程序,所有雷都点出来硬莽……看有的师傅的题解是可以查看local类里的数据拿到三个正确的地址,不过不知道为什么我的看不了……还在研究这个问题……

[FlareOn1]Bob Doge

.net逆向,虽然动调更快一些,但还是想学一下怎么在dnspy里dump数据出来。
查看加密函数,是对dat_secret解密,解密后对flag进行一些没啥用的处理,然后显示出来。
左侧资源里有dat_secret,点进去有地址,光标悬停就会显示dat_secret的数据

1
2
3
4
5
6
7
8
s='A1B5448414E4A1B5D470B491B470D491E4C496F45484B5C440647470A46444'
data=[]
text=''
for i in range(0,len(s),2):
data.append(int(s[i:i+2],16))
for i in data:
text+=chr((i>>4|(i<<4&240))^41)
print(text)

equation

emmm js混淆,嫖段代码解码一下brainfuck混淆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<script>
s="……"
#s里写入网站源代码Sources里面if里的一长串,太长就不贴了……

for(var i=0;i<s.length;i++){
num_z = 1
num_f = 0
if(s[i] == 'l'){
document.write("l[")
i += 2
a = ""
while(1){
if(s[i] == '['){num_z += 1}
else if(s[i] == ']'){num_f += 1}

if(num_f == num_z){num_z = 1;num_f = 0;break}

a = a + s[i]
i += 1
}
document.write(eval(a))
document.write("]")
}
else if(s[i] == '='){
document.write(" == ")
i += 2
b = ""
while(s[i] != '&' && s[i]){
b += s[i]
i++
}
document.write(eval(b))
}
else{
if(s[i] == '&'){
document.write('<br/>')
}
else{
document.write(s[i])
}
}
}
</script>

随便扔到一个网站打开跑一下,获得方程组,然后z3解密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
from z3 import *

l=[Int("l[%d]"%i) for i in range(0x2a)]

s=Solver()
s.add(l[40]+l[35]+l[34]-l[0]-l[15]-l[37]+l[7]+l[6]-l[26]+l[20]+l[19]+l[8]-l[17]-l[14]-l[38]+l[1]-l[9]+l[22]+l[41]+l[3]-l[29]-l[36]-l[25]+l[5]+l[32]-l[16]+l[12]-l[24]+l[30]+l[39]+l[10]+l[2]+l[27]+l[28]+l[21]+l[33]-l[18]+l[4] == 861)
s.add(l[31]+l[26]+l[11]-l[33]+l[27]-l[3]+l[12]+l[30]+l[1]+l[32]-l[16]+l[7]+l[10]-l[25]+l[38]-l[41]-l[14]-l[19]+l[29]+l[36]-l[9]-l[28]-l[6]-l[0]-l[22]-l[18]+l[20]-l[37]+l[4]-l[24]+l[34]-l[21]-l[39]-l[23]-l[8]-l[40]+l[15]-l[35] == -448)
s.add(l[26]+l[14]+l[15]+l[9]+l[13]+l[30]-l[11]+l[18]+l[23]+l[7]+l[3]+l[12]+l[25]-l[24]-l[39]-l[35]-l[20]+l[40]-l[8]+l[10]-l[5]-l[33]-l[31]+l[32]+l[19]+l[21]-l[6]+l[1]+l[16]+l[17]+l[29]+l[22]-l[4]-l[36]+l[41]+l[38]+l[2]+l[0] == 1244)
s.add(l[5]+l[22]+l[15]+l[2]-l[28]-l[10]-l[3]-l[13]-l[18]+l[30]-l[9]+l[32]+l[19]+l[34]+l[23]-l[17]+l[16]-l[7]+l[24]-l[39]+l[8]-l[12]-l[40]-l[25]+l[37]-l[35]+l[11]-l[14]+l[20]-l[27]+l[4]-l[33]-l[21]+l[31]-l[6]+l[1]+l[38]-l[29] == -39)
s.add(l[41]-l[29]+l[23]-l[4]+l[20]-l[33]+l[35]+l[3]-l[19]-l[21]+l[11]+l[26]-l[24]-l[17]+l[37]+l[1]+l[16]-l[0]-l[13]+l[7]+l[10]+l[14]+l[22]+l[39]-l[40]+l[34]-l[38]+l[32]+l[25]-l[2]+l[15]+l[6]+l[28]-l[8]-l[5]-l[31]-l[30]-l[27] == 485)
s.add(l[13]+l[19]+l[21]-l[2]-l[33]-l[0]+l[39]+l[31]-l[23]-l[41]+l[38]-l[29]+l[36]+l[24]-l[20]-l[9]-l[32]+l[37]-l[35]+l[40]+l[7]-l[26]+l[15]-l[10]-l[6]-l[16]-l[4]-l[5]-l[30]-l[14]-l[22]-l[25]-l[34]-l[17]-l[11]-l[27]+l[1]-l[28] == -1068)
s.add(l[32]+l[0]+l[9]+l[14]+l[11]+l[18]-l[13]+l[24]-l[2]-l[15]+l[19]-l[21]+l[1]+l[39]-l[8]-l[3]+l[33]+l[6]-l[5]-l[35]-l[28]+l[25]-l[41]+l[22]-l[17]+l[10]+l[40]+l[34]+l[27]-l[20]+l[23]+l[31]-l[16]+l[7]+l[12]-l[30]+l[29]-l[4] == 939)
s.add(l[19]+l[11]+l[20]-l[16]+l[40]+l[25]+l[1]-l[31]+l[28]-l[23]+l[14]-l[9]-l[27]+l[35]+l[39]-l[37]-l[8]-l[22]+l[5]-l[6]+l[0]-l[32]+l[24]+l[33]+l[29]+l[38]+l[15]-l[2]+l[30]+l[7]+l[12]-l[3]-l[17]+l[34]+l[41]-l[4]-l[13]-l[26] == 413)
s.add(l[22]+l[4]-l[9]+l[34]+l[35]+l[17]+l[3]-l[24]+l[38]-l[5]-l[41]-l[31]-l[0]-l[25]+l[33]+l[15]-l[1]-l[10]+l[16]-l[29]-l[12]+l[26]-l[39]-l[21]-l[18]-l[6]-l[40]-l[13]+l[8]+l[37]+l[19]+l[14]+l[32]+l[28]-l[11]+l[23]+l[36]+l[7] == 117)
s.add(l[32]+l[16]+l[3]+l[11]+l[34]-l[31]+l[14]+l[25]+l[1]-l[30]-l[33]-l[40]-l[4]-l[29]+l[18]-l[27]+l[13]-l[19]-l[12]+l[23]-l[39]-l[41]-l[8]+l[22]-l[5]-l[38]-l[9]-l[37]+l[17]-l[36]+l[24]-l[21]+l[2]-l[26]+l[20]-l[7]+l[35]-l[0] == -313)
s.add(l[40]-l[1]+l[5]+l[7]+l[33]+l[29]+l[12]+l[38]-l[31]+l[2]+l[14]-l[35]-l[8]-l[24]-l[39]-l[9]-l[28]+l[23]-l[17]-l[22]-l[26]+l[32]-l[11]+l[4]-l[36]+l[10]+l[20]-l[18]-l[16]+l[6]-l[0]+l[3]-l[30]+l[37]-l[19]+l[21]+l[25]-l[15] == -42)
s.add(l[21]+l[26]-l[17]-l[25]+l[27]-l[22]-l[39]-l[23]-l[15]-l[20]-l[32]+l[12]+l[3]-l[6]+l[28]+l[31]+l[13]-l[16]-l[37]-l[30]-l[5]+l[41]+l[29]+l[36]+l[1]+l[11]+l[24]+l[18]-l[40]+l[19]-l[35]+l[2]-l[38]+l[14]-l[9]+l[4]+l[0]-l[33] == 289)
s.add(l[29]+l[31]+l[32]-l[17]-l[7]+l[34]+l[2]+l[14]+l[23]-l[4]+l[3]+l[35]-l[33]-l[9]-l[20]-l[37]+l[24]-l[27]+l[36]+l[15]-l[18]-l[0]+l[12]+l[11]-l[38]+l[6]+l[22]+l[39]-l[25]-l[10]-l[19]-l[1]+l[13]-l[41]+l[30]-l[16]+l[28]-l[26] == -117)
s.add(l[5]+l[37]-l[39]+l[0]-l[27]+l[12]+l[41]-l[22]+l[8]-l[16]-l[38]+l[9]+l[15]-l[35]-l[29]+l[18]+l[6]-l[25]-l[28]+l[36]+l[34]+l[32]-l[14]-l[1]+l[20]+l[40]-l[19]-l[4]-l[7]+l[26]+l[30]-l[10]+l[13]-l[21]+l[2]-l[23]-l[3]-l[33] == -252)
s.add(l[29]+l[10]-l[41]-l[9]+l[12]-l[28]+l[11]+l[40]-l[27]-l[8]+l[32]-l[25]-l[23]+l[39]-l[1]-l[36]-l[15]+l[33]-l[20]+l[18]+l[22]-l[3]+l[6]-l[34]-l[21]+l[19]+l[26]+l[13]-l[4]+l[7]-l[37]+l[38]-l[2]-l[30]-l[0]-l[35]+l[5]+l[17] == -183)
s.add(l[6]-l[8]-l[20]+l[34]-l[33]-l[25]-l[4]+l[3]+l[17]-l[13]-l[15]-l[40]+l[1]-l[30]-l[14]-l[28]-l[35]+l[38]-l[22]+l[2]+l[24]-l[29]+l[5]+l[9]+l[37]+l[23]-l[18]+l[19]-l[21]+l[11]+l[36]+l[41]-l[7]-l[32]+l[10]+l[26]-l[0]+l[31] == 188)
s.add(l[3]+l[6]-l[41]+l[10]+l[39]+l[37]+l[1]+l[8]+l[21]+l[24]+l[29]+l[12]+l[27]-l[38]+l[11]+l[23]+l[28]+l[33]-l[31]+l[14]-l[5]+l[32]-l[17]+l[40]-l[34]+l[20]-l[22]-l[16]+l[19]+l[2]-l[36]-l[7]+l[18]+l[15]+l[26]-l[0]-l[4]+l[35] == 1036)
s.add(l[28]-l[33]+l[2]+l[37]-l[12]-l[9]-l[39]+l[16]-l[32]+l[8]-l[36]+l[31]+l[10]-l[4]+l[21]-l[25]+l[18]+l[24]-l[0]+l[29]-l[26]+l[35]-l[22]-l[41]-l[6]+l[15]+l[19]+l[40]+l[7]+l[34]+l[17]-l[3]-l[13]+l[5]+l[23]+l[11]-l[27]+l[1] == 328)
s.add(l[22]-l[32]+l[17]-l[9]+l[20]-l[18]-l[34]+l[23]+l[36]-l[35]-l[38]+l[27]+l[4]-l[5]-l[41]+l[29]+l[33]+l[0]-l[37]+l[28]-l[40]-l[11]-l[12]+l[7]+l[1]+l[2]-l[26]-l[16]-l[8]+l[24]-l[25]+l[3]-l[6]-l[19]-l[39]-l[14]-l[31]+l[10] == -196)
s.add(l[11]+l[13]+l[14]-l[15]-l[29]-l[2]+l[7]+l[20]+l[30]-l[36]-l[33]-l[19]+l[31]+l[0]-l[39]-l[4]-l[6]+l[38]+l[35]-l[28]+l[34]-l[9]-l[23]-l[26]+l[37]-l[8]-l[27]+l[5]-l[41]+l[3]+l[17]+l[40]-l[10]+l[25]+l[12]-l[24]+l[18]+l[32] == 7)
s.add(l[34]-l[37]-l[40]+l[4]-l[22]-l[31]-l[6]+l[38]+l[13]-l[28]+l[8]+l[30]-l[20]-l[7]-l[32]+l[26]+l[1]-l[18]+l[5]+l[35]-l[24]-l[41]+l[9]-l[0]-l[2]-l[15]-l[10]+l[12]-l[36]+l[33]-l[16]-l[14]-l[25]-l[29]-l[21]+l[27]+l[3]-l[17] == -945)
s.add(l[12]-l[30]-l[8]+l[20]-l[2]-l[36]-l[25]-l[0]-l[19]-l[28]-l[7]-l[11]-l[33]+l[4]-l[23]+l[10]-l[41]+l[39]-l[32]+l[27]+l[18]+l[15]+l[34]+l[13]-l[40]+l[29]-l[6]+l[37]-l[14]-l[16]+l[38]-l[26]+l[17]+l[31]-l[22]-l[35]+l[5]-l[1] == -480)
s.add(l[36]-l[11]-l[34]+l[8]+l[0]+l[15]+l[28]-l[39]-l[32]-l[2]-l[27]+l[22]+l[16]-l[30]-l[3]+l[31]-l[26]+l[20]+l[17]-l[29]-l[18]+l[19]-l[10]+l[6]-l[5]-l[38]-l[25]-l[24]+l[4]+l[23]+l[9]+l[14]+l[21]-l[37]+l[13]-l[41]-l[12]+l[35] == -213)
s.add(l[19]-l[36]-l[12]+l[33]-l[27]-l[37]-l[25]+l[38]+l[16]-l[18]+l[22]-l[39]+l[13]-l[7]-l[31]-l[26]+l[15]-l[10]-l[9]-l[2]-l[30]-l[11]+l[41]-l[4]+l[24]+l[34]+l[5]+l[17]+l[14]+l[6]+l[8]-l[21]-l[23]+l[32]-l[1]-l[29]-l[0]+l[3] == -386)
s.add(l[0]+l[7]-l[28]-l[38]+l[19]+l[31]-l[5]+l[24]-l[3]+l[33]-l[12]-l[29]+l[32]+l[1]-l[34]-l[9]-l[25]+l[26]-l[8]+l[4]-l[10]+l[40]-l[15]-l[11]-l[27]+l[36]+l[14]+l[41]-l[35]-l[13]-l[17]-l[21]-l[18]+l[39]-l[2]+l[20]-l[23]-l[22] == -349)
s.add(l[10]+l[22]+l[21]-l[0]+l[15]-l[6]+l[20]-l[29]-l[30]-l[33]+l[19]+l[23]-l[28]+l[41]-l[27]-l[12]-l[37]-l[32]+l[34]-l[36]+l[3]+l[1]-l[13]+l[18]+l[14]+l[9]+l[7]-l[39]+l[8]+l[2]-l[31]-l[5]-l[40]+l[38]-l[26]-l[4]+l[16]-l[25] == 98)
s.add(l[28]+l[38]+l[20]+l[0]-l[5]-l[34]-l[41]+l[22]-l[26]+l[11]+l[29]+l[31]-l[3]-l[16]+l[23]+l[17]-l[18]+l[9]-l[4]-l[12]-l[19]-l[40]-l[27]+l[33]+l[8]-l[37]+l[2]+l[15]-l[24]-l[39]+l[10]+l[35]-l[1]+l[30]-l[36]-l[25]-l[14]-l[32] == -412)
s.add(l[1]-l[24]-l[29]+l[39]+l[41]+l[0]+l[9]-l[19]+l[6]-l[37]-l[22]+l[32]+l[21]+l[28]+l[36]+l[4]-l[17]+l[20]-l[13]-l[35]-l[5]+l[33]-l[27]-l[30]+l[40]+l[25]-l[18]+l[34]-l[3]-l[10]-l[16]-l[23]-l[38]+l[8]-l[14]-l[11]-l[7]+l[12] == -95)
s.add(l[2]-l[24]+l[31]+l[0]+l[9]-l[6]+l[7]-l[1]-l[22]+l[8]-l[23]+l[40]+l[20]-l[38]-l[11]-l[14]+l[18]-l[36]+l[15]-l[4]-l[41]-l[12]-l[34]+l[32]-l[35]+l[17]-l[21]-l[10]-l[29]+l[39]-l[16]+l[27]+l[26]-l[3]-l[5]+l[13]+l[25]-l[28] == -379)
s.add(l[19]-l[17]+l[31]+l[14]+l[6]-l[12]+l[16]-l[8]+l[27]-l[13]+l[41]+l[2]-l[7]+l[32]+l[1]+l[25]-l[9]+l[37]+l[34]-l[18]-l[40]-l[11]-l[10]+l[38]+l[21]+l[3]-l[0]+l[24]+l[15]+l[23]-l[20]+l[26]+l[22]-l[4]-l[28]-l[5]+l[39]+l[35] == 861)
s.add(l[35]+l[36]-l[16]-l[26]-l[31]+l[0]+l[21]-l[13]+l[14]+l[39]+l[7]+l[4]+l[34]+l[38]+l[17]+l[22]+l[32]+l[5]+l[15]+l[8]-l[29]+l[40]+l[24]+l[6]+l[30]-l[2]+l[25]+l[23]+l[1]+l[12]+l[9]-l[10]-l[3]-l[19]+l[20]-l[37]-l[33]-l[18] == 1169)
s.add(l[13]+l[0]-l[25]-l[32]-l[21]-l[34]-l[14]-l[9]-l[8]-l[15]-l[16]+l[38]-l[35]-l[30]-l[40]-l[12]+l[3]-l[19]+l[4]-l[41]+l[2]-l[36]+l[37]+l[17]-l[1]+l[26]-l[39]-l[10]-l[33]+l[5]-l[27]-l[23]-l[24]-l[7]+l[31]-l[28]-l[18]+l[6] == -1236)
s.add(l[20]+l[27]-l[29]-l[25]-l[3]+l[28]-l[32]-l[11]+l[10]+l[31]+l[16]+l[21]-l[7]+l[4]-l[24]-l[35]+l[26]+l[12]-l[37]+l[6]+l[23]+l[41]-l[39]-l[38]+l[40]-l[36]+l[8]-l[9]-l[5]-l[1]-l[13]-l[14]+l[19]+l[0]-l[34]-l[15]+l[17]+l[22] == -114)
s.add(l[12]-l[28]-l[13]-l[23]-l[33]+l[18]+l[10]+l[11]+l[2]-l[36]+l[41]-l[16]+l[39]+l[34]+l[32]+l[37]-l[38]+l[20]+l[6]+l[7]+l[31]+l[5]+l[22]-l[4]-l[15]-l[24]+l[17]-l[3]+l[1]-l[35]-l[9]+l[30]+l[25]-l[0]-l[8]-l[14]+l[26]+l[21] == 659)
s.add(l[21]-l[3]+l[7]-l[27]+l[0]-l[32]-l[24]-l[37]+l[4]-l[22]+l[20]-l[5]-l[30]-l[31]-l[1]+l[15]+l[41]+l[12]+l[40]+l[38]-l[17]-l[39]+l[19]-l[13]+l[23]+l[18]-l[2]+l[6]-l[33]-l[9]+l[28]+l[8]-l[16]-l[10]-l[14]+l[34]+l[35]-l[11] == -430)
s.add(l[11]-l[23]-l[9]-l[19]+l[17]+l[38]-l[36]-l[22]-l[10]+l[27]-l[14]-l[4]+l[5]+l[31]+l[2]+l[0]-l[16]-l[8]-l[28]+l[3]+l[40]+l[25]-l[33]+l[13]-l[32]-l[35]+l[26]-l[20]-l[41]-l[30]-l[12]-l[7]+l[37]-l[39]+l[15]+l[18]-l[29]-l[21] == -513)
s.add(l[32]+l[19]+l[4]-l[13]-l[17]-l[30]+l[5]-l[33]-l[37]-l[15]-l[18]+l[7]+l[25]-l[14]+l[35]+l[40]+l[16]+l[1]+l[2]+l[26]-l[3]-l[39]-l[22]+l[23]-l[36]-l[27]-l[9]+l[6]-l[41]-l[0]-l[31]-l[20]+l[12]-l[8]+l[29]-l[11]-l[34]+l[21] == -502)
s.add(l[30]-l[31]-l[36]+l[3]+l[9]-l[40]-l[33]+l[25]+l[39]-l[26]+l[23]-l[0]-l[29]-l[32]-l[4]+l[37]+l[28]+l[21]+l[17]+l[2]+l[24]+l[6]+l[5]+l[8]+l[16]+l[27]+l[19]+l[12]+l[20]+l[41]-l[22]+l[15]-l[11]+l[34]-l[18]-l[38]+l[1]-l[14] == 853)
s.add(l[38]-l[10]+l[16]+l[8]+l[21]-l[25]+l[36]-l[30]+l[31]-l[3]+l[5]-l[15]+l[23]-l[28]+l[7]+l[12]-l[29]+l[22]-l[0]-l[37]-l[14]-l[11]+l[32]+l[33]-l[9]+l[39]+l[41]-l[19]-l[1]+l[18]-l[4]-l[6]+l[13]+l[20]-l[2]-l[35]-l[26]+l[27] == -28)
s.add(l[11]+l[18]-l[26]+l[15]-l[14]-l[33]+l[7]-l[23]-l[25]+l[0]-l[6]-l[21]-l[16]+l[17]-l[19]-l[28]-l[38]-l[37]+l[9]+l[20]-l[8]-l[3]+l[22]-l[35]-l[10]-l[31]-l[2]+l[41]-l[1]-l[4]+l[24]-l[34]+l[39]+l[40]+l[32]-l[5]+l[36]-l[27] == -529)
s.add(l[38]+l[8]+l[36]+l[35]-l[23]-l[34]+l[13]-l[4]-l[27]-l[24]+l[26]+l[31]-l[30]-l[5]-l[40]+l[28]-l[11]-l[2]-l[39]+l[15]+l[10]-l[17]+l[3]+l[19]+l[22]+l[33]+l[0]+l[37]+l[16]-l[9]-l[32]+l[25]-l[21]-l[12]+l[6]-l[41]+l[20]-l[18] == -12)
s.add(l[6]-l[30]-l[20]-l[27]-l[14]-l[39]+l[41]-l[33]-l[0]+l[25]-l[32]-l[3]+l[26]-l[12]+l[8]-l[35]-l[24]+l[15]+l[9]-l[4]+l[13]+l[36]+l[34]+l[1]-l[28]-l[21]+l[18]+l[23]+l[29]-l[10]-l[38]+l[22]+l[37]+l[5]+l[19]+l[7]+l[16]-l[31] == 81)

if s.check()==sat:
m=s.model()
for i in range(0x2a):
print(chr(int(str(m[l[i]]))),end='')

[MRCTF2020]PixelShooter

jeb打开,C#源文件,得到flag……

[2019红帽杯]childRE

我有病,又是抄错一个数据检查半年……如果看不懂加密逻辑,那就爆吧~(手动滑稽

复现此题 感觉以前的解法实在是太憨批了, 遂改了一下代码

1
2
3
4
5
6
7
8
9
model='1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'+chr(0x27)+'A'+'SDFGHJKL:"ZXCVBNM<>?zxcvbnm,./'
s1='55565653255552225565565555243466334653663544426565555525555222'#整除
s2='(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&'#取余
output=''

for i in range(0x3e):
output+=chr(model.find(s1[i])*23+model.find(s2[i]))

print(output)

打出output,然后按照函数名称修饰规则对函数名修饰。最上面一步是个二叉树的排序,就是改变了一下字符串的顺序。懒得逆算法了,就直接打进去一串无重复的字符,然后动调看顺序,把密文按照这个顺序重新排列就好了。

1
2
3
4
5
6
7
8
9
import hashlib
t='0123456789qwertyuiopasdfghjklzx'
d='yu7io83pa9sdq41fgwhje5klrzxt620'
enc='?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'
flag=''
for i in range(len(t)):
flag+=enc[d.index(t[i])]

print(hashlib.md5(flag.encode('utf-8')).hexdigest())

[SWPU2019]ReverseMe

这动调真的太恶心了……真的调到自闭了属于是…… 彻底治好了不敢看汇编的毛病

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
box1=[
0xB3, 0x37, 0x0F, 0xF8, 0xBC, 0xBC, 0xAE, 0x5D, 0xBA, 0x5A,
0x4D, 0x86, 0x44, 0x97, 0x62, 0xD3, 0x4F, 0xBA, 0x24, 0x16,
0x0B, 0x9F, 0x72, 0x1A, 0x65, 0x68, 0x6D, 0x26, 0xBA, 0x6B,
0xC8, 0x67
]
box2=[
0x86, 0x0C, 0x3E, 0xCA, 0x98, 0xD7, 0xAE, 0x19, 0xE2, 0x77,
0x6B, 0xA6, 0x6A, 0xA1, 0x77, 0xB0, 0x69, 0x91, 0x37, 0x05,
0x7A, 0xF9, 0x7B, 0x30, 0x43, 0x5A, 0x4B, 0x10, 0x86, 0x7D,
0xD4, 0x28
]
s="SWPU_2019_CTF"
for i in range(32):
print(chr(ord(s[i%len(s)])^box1[i]^box2[i]),end='')

[羊城杯 2020]easyre

白给题,base64加密之后13个一组移位,然后凯撒位移3……
(虽然我这个sb因为加减写反了检查了好久……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import base64
enc3='EmBmP5Pmn7QcPU4gLYKv5QcMmB3PWHcP5YkPq3=cT6QckkPckoRG'
enc2=''
enc1=''
for i in enc3:
if ord(i)<=ord('@') or ord(i)>ord('Z'):
if ord(i)<=ord('`') or ord(i)>ord('z'):
if ord(i)<=47 or ord(i)>57:
enc2+=i
else:
enc2+=chr((ord(i)-48-3)%10+48)
else:
enc2+=chr((ord(i)-97-3)%26+97)
else:
enc2+=chr((ord(i)-65-3)%26+65)
enc1+=enc2[13:26]
enc1+=enc2[39:52]
enc1+=enc2[0:13]
enc1+=enc2[26:39]
print (base64.b64decode(enc1))

[CFI-CTF 2018]IntroToPE

dnspy打开,看到关键判断函数,跳转,base64,获得flag……

[安洵杯 2019]crackMe

SM4+base64换表
学了密码之后再看这种块加密和流加密的题感觉还是不错的哈哈哈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64
from pysm4 import decrypt

initial='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
enc='1UTAOIkpyOSWGv/mOYFY4R=='
enc_base=''

for i in range(0,len(enc),2):
enc_base+=enc[i+1]
enc_base+=enc[i]

initial=initial.swapcase()
new_list=initial[24:]+initial[:24]
model = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tmp=base64.b64decode(enc_base.translate(str.maketrans(new_list,model)))

enc_sm4 = int(tmp.hex(),16)
key=int(b'where_are_u_now?'.hex(),16)
dec=decrypt(enc_sm4,key)

print('flag{'+bytes.fromhex(hex(dec)[2:]).decode()+'}')

[WUSTCTF2020]funnyre

忘记记录++……

[QCTF2018]Xman-babymips

刚开始一直以为我爆破写错了,结果是我漏了前面一个异或的步骤 裂开什么时候才能不再犯这种神比错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
box=[
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
]
flag=[]
for i in range(5,len(box)+5):
if i&1!=0:
v=((box[i-5]>>6)|(box[i-5]<<2))&0xff
else:
v=((box[i-5]<<6)|(box[i-5]>>2))&0xff
flag.append(v^(32-i))
print("flag{",end='')
for i in flag:
print(chr(i),end='')

[羊城杯 2020]login

pyinstxtractor.py用着真的很烦……为什么要去掉头文件……
这个题基本一大半时间在查这个包怎么用,winhex怎么插文件头,插几个字节……
uncompyle6被雷劈了,目前懒得修,先用在线网站凑合凑合……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from z3 import *

a1 =Int('a1')
a2 =Int('a2')
a3 =Int('a3')
a4 =Int('a4')
a5 =Int('a5')
a6 =Int('a6')
a7 =Int('a7')
a8 =Int('a8')
a9 =Int('a9')
a10 =Int('a10')
a11 =Int('a11')
a12 =Int('a12')
a13 =Int('a13')
a14 =Int('a14')

s=Solver()
s.add((((a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5) + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36) + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60) + a14 * 29 == 22748)
s.add((((a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25) + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66) + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39) + a14 * 17 == 7258)
s.add((((a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65) + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33) + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34) + a14 * 23 == 26190)
s.add((((a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59) + a5 * 49 + a6 * 81 + a7 * 25 + (a8 *128) - a9 * 32) + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60) + a14 * 29 == 37136)
s.add(((a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52) + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36) + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915)
s.add((((a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45) + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26) + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61) + a14 * 28 == 17298)
s.add((((a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42) + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47) + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44) + a14 * 65 == 19875)
s.add(((a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85) + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30) + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784)
s.add((((a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85) + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36) + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64) + a14 * 27 == 9710)
s.add(((((a1 * 67 - a2 * 68) + a3 * 68 - a4 * 51 - a5 * 43) + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38) + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52) + a14 * 31 == 13376)
s.add((((a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51) + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6) + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67) + a14 * 78 == 24065)
s.add((((a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5) + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35) + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61) + a14 * 20 == 27687)
s.add(((a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25) + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92) + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250)
s.add(((a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43) + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36) + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317)
if s.check()==sat:
print(s.model())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
code=[0]*14
a13 = 88
a3 = 10
a4 = 7
a10 = 108
a12 = 74
a1 = 119
a7 = 28
a6 = 43
a9 = 52
a14 = 33
a5 = 104
a8 = 91
a2 = 24
a11 = 88
code[2]=a1
code[1]=a2
code[0]=a3
code[3]=a4
code[4]=a5
code[5]=a6
code[6]=a7
code[7]=a8
code[9]=a9
code[8]=a10
code[10]=a11
code[11]=a12
code[12]=a13
code[13]=a14

for i in range(12,-1,-1):
code[i]=code[i]^code[i+1]
for i in code:
print(chr(i),end='')
#U_G07_th3_k3y!
import hashlib
f='U_G07_th3_k3y!'
print(hashlib.md5(f.encode()).hexdigest())

[RoarCTF2019]polyre

学习了去除控制流平坦化和用idapython脚本去除永真条件……
感觉很nb 原文链接
其实都是抄脚本QAQ
然后就是逆这个CRC64了,好久没做题了,真费劲……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enc=[0x96, 0x62, 0x53, 0x43, 0x6D, 0xF2, 0x8F, 0xBC, 0x16, 0xEE, 
0x30, 0x05, 0x78, 0x00, 0x01, 0x52, 0xEC, 0x08, 0x5F, 0x93,
0xEA, 0xB5, 0xC0, 0x4D, 0x50, 0xF4, 0x53, 0xD8, 0xAF, 0x90,
0x2B, 0x34, 0x81, 0x36, 0x2C, 0xAA, 0xBC, 0x0E, 0x25, 0x8B,
0xE4, 0x8A, 0xC6, 0xA2, 0x81, 0x9F, 0x75, 0x55, 0xB3, 0x26,
0xFA, 0x79, 0x76, 0x4B, 0x00, 0xB0]
key=0xB0004B7679FA26B3
table=[]
for i in range(0,len(enc),8):
t=0
for j in range(8):
t<<=8
t+=enc[i+7-j]
table.append(t)

for i in table:
for j in range(64):
f=i&1
if f==1:
i^=key
i>>=1
if f==1:
i|=0x8000000000000000
print(hex(i))

enc=[0x6666367b67616c66,0x63362d3039333932,0x2d363563342d3032,0x3539612d30376162,0x6631643365383537]
for i in enc:
for j in range(8):
print(chr(i&0xff),end='')
i>>=8

print(chr(0x38),end='')
print(chr(0x7d),end='')

[NPUCTF2020]你好sao啊

呜呜,是rx大人出的题
我麻了,被一个base64折磨一个多小时,屈服了,直接嫖代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# coding:utf-8
s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/'
def My_base64_encode():
inputs = b'\x9e\x9b\x9c\xb5\xfe\x70\xd3\x0f\xb2\xd1\x4f\x9c\x02\x7f\xab\xde\x59\x65\x63\xe7\x40\x9d\xcd\xfa\x04'
# 将字符串转化为2进制
bin_str = []
for i in inputs:
x = str(bin(i)).replace('0b', '')
bin_str.append('{:0>8}'.format(x))
print(bin_str)
# 输出的字符串
outputs = ""
# 不够三倍数,需补齐的次数
nums = 0
while bin_str:
# 每次取三个字符的二进制
temp_list = bin_str[:3]
if(len(temp_list) != 3):
nums = 3 - len(temp_list)
while len(temp_list) < 3:
temp_list += ['0' * 8]
temp_str = "".join(temp_list)
# print(temp_str)
# 将三个8字节的二进制转换为4个十进制
temp_str_list = []
for i in range(0, 4):
temp_str_list.append(int(temp_str[i*6:(i+1)*6], 2))
# print(temp_str_list)
if nums:
temp_str_list = temp_str_list[0:4 - nums]

for i in temp_str_list:
outputs += s[i]
bin_str = bin_str[3:]
outputs += nums * '='
print("Encrypted String:\n%s " % outputs)
My_base64_encode()

[UTCTF2020]babymips

神tm,出来一堆乱码我还以为又错了,结果交了竟然是对的……

1
2
3
4
5
6
7
8
9
10
11
12
box=[
0x62, 0x6C, 0x7F, 0x76, 0x7A, 0x7B, 0x66, 0x73, 0x76, 0x50,
0x52, 0x7D, 0x40, 0x54, 0x55, 0x79, 0x40, 0x49, 0x47, 0x4D,
0x74, 0x19, 0x7B, 0x6A, 0x42, 0x0A, 0x4F, 0x52, 0x7D, 0x69,
0x4F, 0x53, 0x0C, 0x64, 0x10, 0x0F, 0x1E, 0x4A, 0x67, 0x03,
0x7C, 0x67, 0x02, 0x6A, 0x31, 0x67, 0x61, 0x37, 0x7A, 0x62,
0x2C, 0x2C, 0x0F, 0x6E, 0x17, 0x00, 0x16, 0x0F, 0x16, 0x0A,
0x6D, 0x62, 0x73, 0x25, 0x39, 0x76, 0x2E, 0x1C, 0x63, 0x78,
0x2B, 0x74, 0x32, 0x16, 0x20, 0x22, 0x44, 0x19
]
for i in range(len(box)):
print(chr(box[i]^(i+23)),end='')

[安洵杯 2019]game

控制流平坦化……代码真的难看……
check1里有两次交换,一次交换v12和v12+1,这个很好认,就是交换相邻位,判断是v12小于v4(v4是输入长度)。但是有一处交换v12和v11的,瞅了半天没看懂,网上都没有分析,直接交换前后两部分……后来仔细看了看v12和v11的交叉引用,v11的起始是0,往后自增,判断是小于v12>>1……我刚开始还挺疑惑这个v11<v12>>1的,感觉不像是碳基生物能写出来的代码 后来仔细想了一下,v12>>1不就是除以2吗……然后每次给v11和v12自增并且交换,那就是换掉前后两部分……
汗……看起来奇奇怪怪的代码还是不能直接无视啊……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
s='4693641762894685722843556137219876255986'
f=''
flag=[0]*40
for i in range(0,len(s),2):
a=ord(s[i])+20
b=ord(s[i+1])+20
a=(a&0xf3)|(~a&0xc)
b=(b&0xf3)|(~b&0xc)
f+=chr(b)
f+=chr(a)
for i in range(20):
(flag[i],flag[i+20]) = (f[i+20], f[i])
for i in flag:
print(i,end='')

[GUET-CTF2019]encrypt

rc4+位交换,竟然觉得这种纯粹的逆加密算法题异常温柔……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
box=[0xB0 ,0x31,0x75 ,0x70 ,0xF8 ,0xDF,0x07 ,0x3C ,0x78 ,0x71,0x50 ,0x29 ,0x2C ,0x16,0x69 ,0x12 ,0xC8 ,0x2B,0x3B ,0x7F ,0xB2 ,0xE7,0x4B ,0x68 ,0x8C ,0xC5,0xA6 ,0x15 ,0x03 ,0x58,0x47 ,0x04 ,0x13 ,0x8D,0x87 ,0x26 ,0x09 ,0xED,0x17 ,0x8A ,0xC2 ,0xF2,0x43 ,0xC0 ,0xAC ,0x59,0x97 ,0xF5 ,0x3F ,0x67,0x5E ,0x39 ,0x86 ,0xD5,0x72 ,0x61 ,0xDA ,0xF7,0x01 ,0x05 ,0x8B ,0xC3,0xB1 ,0x77 ,0xAF ,0x1D,0x30 ,0xC6 ,0x45 ,0x0E,0x5F ,0xEE ,0xAE ,0xF0,0x28 ,0xCE ,0xCD ,0xA7,0x9B ,0x2A ,0x19 ,0x48,0x08 ,0x44 ,0x20 ,0xFE,0x6D ,0xB5 ,0x2E ,0x6A,0xF1 ,0x34 ,0xBC ,0x1E,0x3E ,0xCC ,0x41 ,0x92,0xD8 ,0xBD ,0xA5 ,0xE8,0x4D ,0x0A ,0x49 ,0x0D,0xA2 ,0xFA ,0x62 ,0x74,0xD4 ,0x83 ,0x96 ,0x94,0x3D ,0xCB ,0x18 ,0x63,0x99 ,0x46 ,0xCA ,0xB7,0x8E ,0xCF ,0xFB ,0xA3,0x6C ,0x7E ,0x51 ,0x27,0x60 ,0x9A ,0x11 ,0xF3,0x5C ,0x6E ,0xBA ,0x42,0x76 ,0x2F ,0xEF ,0xBF,0x21 ,0xAA ,0xE4 ,0xD6,0x1B ,0x55 ,0x7D ,0xBE,0xEA ,0xD3 ,0x10 ,0xF4,0xC7 ,0x4A ,0x23 ,0x79,0x84 ,0xA4 ,0x1C ,0xAB,0x14 ,0xDB ,0x4C ,0x3A,0xB8 ,0x52 ,0xEC ,0x37,0x38 ,0xB6 ,0xD2 ,0xA0,0x5A ,0x5B ,0x98 ,0x66,0x54 ,0x9E ,0x4E ,0x4F,0xB4 ,0xC4 ,0xC9 ,0xD0,0x25 ,0x9C ,0x80 ,0xDE,0x2D ,0x06 ,0x22 ,0x0B,0x91 ,0x6B ,0x9F ,0xF6,0xE6 ,0xE2 ,0xC1 ,0x0F,0x93 ,0x90 ,0x7B ,0x9D,0x8F ,0xDD ,0xE5 ,0x65,0x35 ,0xAD ,0xA9 ,0xDC,0x82 ,0xBB ,0x00 ,0x53,0xD1 ,0xA8 ,0x33 ,0xE9,0x40 ,0x1A ,0xFF ,0xA1,0x95 ,0x36 ,0xD9 ,0xEB,0x89 ,0xE3 ,0x7C ,0x73,0x85 ,0x88 ,0x7A ,0xE0,0xFD ,0x64 ,0x0C ,0x57,0x32 ,0xB3 ,0xB9 ,0x1F,0xD7 ,0xFC ,0x81 ,0xE1,0x02 ,0xF9 ,0x5D ,0x56,0x6F ,0x24]
v5=0
v6=0
xor=[]
for i in range(40):
v5+=1
v5&=0xff
v7=box[v5]
v6=(v6+v7)&0xff
v8=box[v6]
box[v5]=v8
box[v6]=v7
xor.append(box[(v7+v8)&0xff])
enc=[0x5A, 0x60, 0x54, 0x7A, 0x7A, 0x54, 0x72, 0x44, 0x7C, 0x66, 0x51, 0x50, 0x5B, 0x5F, 0x56, 0x56, 0x4C, 0x7C, 0x79, 0x6E, 0x65, 0x55, 0x52, 0x79, 0x55, 0x6D, 0x46, 0x6B, 0x6C, 0x56, 0x4A, 0x67, 0x4C, 0x61, 0x73, 0x4A, 0x72, 0x6F, 0x5A, 0x70, 0x48, 0x52, 0x78, 0x49, 0x55, 0x6C, 0x48, 0x5C, 0x76, 0x5A, 0x45,0x3d]
for i in range(len(enc)):
enc[i]-=61
f=[0]*39
j=0
for i in range(0,len(enc),4):
f[j]=(((enc[i]&0x3f)<<2)|((enc[i+1]&0x3f)>>4))&0xff
f[j+1]=(((enc[i+1])<<4)|((enc[i+2]&0x3f)>>2))&0xff
f[j+2]=(((enc[i+2])<<6)|((enc[i+3])&0x3f))&0xff
j+=3
for i in range(len(f)):
f[i]^=xor[i]
for i in f:
print(chr(i),end='')


[GKCTF 2021]QQQQT

感觉解包不解包好像差不多emmm?……
base58加密,我还以为跟base64一样的,呜呜呜,结果被教育了

[SCTF2019]babyre

思想升华了属于是

修花指令,神tm,函数必须选中才能分析……(脏话

第一部分,第一次见三维迷宫,还是挺有意思的。出题人还是比较温柔,用的是5*5*5的迷宫,对我这种手解废物来说还是比较容易(x
x下一层,y上一层,手动走迷宫:ddwwxxssxaxwwaasasyywwdd

1
2
3
4
5
6
7
8
s=r'**************.****.**s..*..******.****.***********..***..**..#*..***..***.********************.**..*******..**...*..*.*.**.*'
print(len(s))
for i in range(125):
if i%5==0:
print()
if i%25==0:
print()
print(s[i],end='')

第二部分,神tm,逆算法逆了半天然后告诉我就是个base64……这咋看出来base64的啊……这base的码表不能这么长(zhang)吧……难道是另一种实现方式吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
s='sctf_9102'
box=[0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F
,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F
,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x7F,0x7F,0x7F ,0x7F,0x3E,0x7F,0x7F ,0x7F,0x3F
,0x34,0x35 ,0x36,0x37,0x38,0x39 ,0x3A,0x3B,0x3C,0x3D ,0x7F,0x7F,0x7F,0x40 ,0x7F,0x7F
,0x7F, 0 ,0x01,0x02,0x03,0x04 ,0x05,0x06,0x07,0x08 ,0x09,0x0A,0x0B,0x0C ,0x0D,0x0E
,0x0F,0x10 ,0x11,0x12,0x13,0x14 ,0x15,0x16,0x17,0x18 ,0x19,0x7F,0x7F,0x7F ,0x7F,0x7F
,0x7F,0x1A ,0x1B,0x1C,0x1D,0x1E ,0x1F,0x20,0x21,0x22 ,0x23,0x24,0x25,0x26 ,0x27,0x28
,0x29,0x2A ,0x2B,0x2C,0x2D,0x2E ,0x2F,0x30,0x31,0x32 ,0x33,0x7F,0x7F,0x7F ,0x7F,0x7F]
f=0
for i in range(3):
for j in range(3):
f=ord(s[i*3+j])|(f<<8)
dec=''
dec+=chr(box.index((f>>18)&0x3f))
dec+=chr(box.index((f>>12)&0x3f))
dec+=chr(box.index((f>>6)&0x3f))
dec+=chr(box.index(f&0x3f))
print(dec,end='')

第三部分,用了一个类似生成SM4轮密钥(去掉S盒)的过程,出题人还是很好心地换成了大端序(x 总之移位异或的过程是不用改变可以直接解密回来的,我刚开始竟然没看到循环,罪过罪过,又是改脚本改半年
我真是sb啊……写脚本的时候一直在想,加密过程是取四个中的第一个与后三个的加密结果异或,那解密的时候也应该异或一组里面的第一个。我真是sb啊……1和enc(2,3,4)生成5,那么解密肯定要用5来异或enc(2,3,4)才能产生1啊……也就是解密的异或应该用一组里的最后一个……我是什么sb,我自己爬呜呜呜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def rol(x,y):
return ((x<<y)|(x>>(32-y)))&0xffffffff
def ror(x,y):
return ((x>>y)|(x<<(32-y)))&0xffffffff

def enc(x):
return rol(x,12)^rol(x,8)^ror(x,2)^ror(x,6)

def sub(x):
t1=box[x&0xff]
t2=box[(x&0xff00)>>8]
t3=box[(x&0xff0000)>>16]
t4=box[(x&0xff000000)>>24]
v=t1|(t2<<8)|(t3<<16)|(t4<<24)
return enc(v)

box=[0xD6 ,0x90 ,0xE9 ,0xFE,0xCC ,0xE1 ,0x3D ,0xB7,0x16 ,0xB6 ,0x14 ,0xC2,0x28 ,0xFB ,0x2C ,0x05,0x2B ,0x67 ,0x9A ,0x76,0x2A ,0xBE ,0x04 ,0xC3,0xAA ,0x44 ,0x13 ,0x26,0x49 ,0x86 ,0x06 ,0x99,0x9C ,0x42 ,0x50 ,0xF4,0x91 ,0xEF ,0x98 ,0x7A,0x33 ,0x54 ,0x0B ,0x43,0xED ,0xCF ,0xAC ,0x62,0xE4 ,0xB3 ,0x1C ,0xA9,0xC9 ,0x08 ,0xE8 ,0x95,0x80 ,0xDF ,0x94 ,0xFA,0x75 ,0x8F ,0x3F ,0xA6,0x47 ,0x07 ,0xA7 ,0xFC,0xF3 ,0x73 ,0x17 ,0xBA,0x83 ,0x59 ,0x3C ,0x19,0xE6 ,0x85 ,0x4F ,0xA8,0x68 ,0x6B ,0x81 ,0xB2,0x71 ,0x64 ,0xDA ,0x8B,0xF8 ,0xEB ,0x0F ,0x4B,0x70 ,0x56 ,0x9D ,0x35,0x1E ,0x24 ,0x0E ,0x5E,0x63 ,0x58 ,0xD1 ,0xA2,0x25 ,0x22 ,0x7C ,0x3B,0x01 ,0x21 ,0x78 ,0x87,0xD4 ,0 ,0x46 ,0x57,0x9F ,0xD3 ,0x27 ,0x52,0x4C ,0x36 ,0x02 ,0xE7,0xA0 ,0xC4 ,0xC8 ,0x9E,0xEA ,0xBF ,0x8A ,0xD2,0x40 ,0xC7 ,0x38 ,0xB5,0xA3 ,0xF7 ,0xF2 ,0xCE,0xF9 ,0x61 ,0x15 ,0xA1,0xE0 ,0xAE ,0x5D ,0xA4,0x9B ,0x34 ,0x1A ,0x55,0xAD ,0x93 ,0x32 ,0x30,0xF5 ,0x8C ,0xB1 ,0xE3,0x1D ,0xF6 ,0xE2 ,0x2E,0x82 ,0x66 ,0xCA ,0x60,0xC0 ,0x29 ,0x23 ,0xAB,0x0D ,0x53 ,0x4E ,0x6F,0xD5 ,0xDB ,0x37 ,0x45,0xDE ,0xFD ,0x8E ,0x2F,0x03 ,0xFF ,0x6A ,0x72,0x6D ,0x6C ,0x5B ,0x51,0x8D ,0x1B ,0xAF ,0x92,0xBB ,0xDD ,0xBC ,0x7F,0x11 ,0xD9 ,0x5C ,0x41,0x1F ,0x10 ,0x5A ,0xD8,0x0A ,0xC1 ,0x31 ,0x88,0xA5 ,0xCD ,0x7B ,0xBD,0x2D ,0x74 ,0xD0 ,0x12,0xB8 ,0xE5 ,0xB4 ,0xB0,0x89 ,0x69 ,0x97 ,0x4A,0x0C ,0x96 ,0x77 ,0x7E,0x65 ,0xB9 ,0xF1 ,0x09,0xC5 ,0x6E ,0xC6 ,0x84,0x18 ,0xF0 ,0x7D ,0xEC,0x3A ,0xDC ,0x4D ,0x20,0x79 ,0xEE ,0x5F ,0x3E,0xD7 ,0xCB ,0x39 ,0x48,0xC6 ,0xBA ,0xB1 ,0xA3,0x50 ,0x33 ,0xAA ,0x56,0x97 ,0x91 ,0x7D ,0x67,0xDC ,0x22 ,0x70 ,0xB2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

cmp=[0]*26+[0xbe040680,0xc5af7647,0x9fcc401f,0xd8bf92ef]

for k in range(25,-1,-1):
cmp[k]=cmp[k+4]^sub(cmp[k+1]^cmp[k+2]^cmp[k+3])

s=''

for i in range(4):
s+=chr(cmp[i]&0xff)
s+=chr((cmp[i]&0xff00)>>8)
s+=chr((cmp[i]&0xff0000)>>16)
s+=chr((cmp[i]&0xff000000)>>24)
print(s)

[WMCTF2020]easy_re

好奇怪的题

[SCTF2019]Strange apk

安卓,8会,爬了

[2019红帽杯]Snake

好怪的题,再看一眼

1
2
3
4
5
6
7
8
9
10
import ctypes

def baopo(i):
dll = ctypes.cdll.LoadLibrary("D:\\code\\python\\Interface.dll")#进入interface.dll这个文件
print(i)
dll.GameObject(i)#调用GameObject()这个函数

for i in range(0,100):#从0~99开始爆破
baopo(i)

[SCTF2019]creakme

源码
windows调试附加

看懂SEH之后写篇博客……现在只是在track神的指导下调出来那段SMC了,呜呜,还是太菜了。
基本上我现在是大概能够理解,SEH之所以经常作为反调试的手段,因为它在调试状态下不会被运行的,而且catch段的代码不会被ida反编译出来。这个题里正好就是SMC那一段没有反编译出来,所以突然return一段乱码数据还挺诡异的……(bushi)而其实是那段数据先被SMC,然后再作为函数被调用。
要调试SEH里的代码,必须先找到catch块,然后手动改EIP跳转到相应地址。之前问track神怎么找catch块,他回答在汇编里嗯翻……cao……
前几天看《逆向工程核心原理》,好像可以在FS寄存器指向的寄存器里找到TEB的地址,然后固定偏移的地方有存SEH链表的地址,学习ing……

SMC解密部分代码对密文加密后的还原:

1
2
3
4
5
s='>pvfqYc,4tTc2UxRmlJ,sB{Fh4Ck2:CFOb4ErhtIcoLo'
new=''
for i in s:
new+=chr(ord(i)-1)
print(new[::-1])

AES解密部分:

1
2
3
4
5
6
7
from Crypto.Cipher import AES
import base64
key=b"sycloversyclover"
iv=b"sctfsctfsctfsctf"
cipher=base64.b64decode("nKnbHsgqD3aNEB91jB3gEzAr+IklQwT1bSs3+bXpeuo=")
aes=AES.new(key,AES.MODE_CBC,iv)
print(aes.decrypt(cipher))

[SCTF2019]Who is he

[CISCN2018]2ex

白给……

[watevrCTF 2019]Timeout

明文字符串……

[FlareOn2]very_success

太黑了……

{.line-numbers}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int __usercall sub_401084@<eax>(int result@<eax>, int a2, char *a3, int a4)
{
__int16 v4; // bx
int v5; // ecx
_BYTE *v7; // edi
char enc; // al
unsigned int v9; // kr00_4
char enc1; // al
char v11; // cf
__int16 v12; // ax
bool v13; // zf
_BYTE *v14; // edi
int xor; // [esp+0h] [ebp-Ch]

v4 = 0;
v5 = 37;
if ( a4 >= 37 )
{
v7 = (_BYTE *)(a2 + 36);
while ( 1 )
{
LOWORD(result) = 0x1C7;
xor = result;
enc = *a3++;
v9 = __readeflags();
enc1 = xor ^ enc;
__writeeflags(v9);
v12 = (unsigned __int8)(__ROL1__(1, v4 & 3) + v11 + enc1);
v4 += v12;
v13 = *v7 == (unsigned __int8)v12;
v14 = v7 + 1;
if ( !v13 )
LOWORD(v5) = 0;
result = xor;
if ( !v5 )
break;
v7 = v14 - 2;
if ( !--v5 )
return result;
}
}
return 0;
}

注意第19行是v7 = (_BYTE *)(a2 + 36);,也就是把v2[36]赋给v7,此后与v7赋值有关的操作分别是v14 = v7 + 1;v7 = v14 - 2;,等价于v7-=1,也就是从后往前比较的。
算法很好逆,地址动调一下也能找到,不知道当时为什么没写,可能看到一坨浆糊的代码脑子就不好使了吧hhhhhh

1
2
3
4
5
6
7
8
9
10
11
12
v7=[0xAF, 0xAA, 0xAD, 0xEB, 0xAE, 0xAA, 0xEC, 0xA4, 0xBA, 0xAF, 
0xAE, 0xAA, 0x8A, 0xC0, 0xA7, 0xB0, 0xBC, 0x9A, 0xBA, 0xA5,
0xA5, 0xBA, 0xAF, 0xB8, 0x9D, 0xB8, 0xF9, 0xAE, 0x9D, 0xAB,
0xB4, 0xBC, 0xB6, 0xB3, 0x90, 0x9A, 0xA8]
v4=0
f=''
for i in range(len(v7)-1,-1,-1):
rol=((1<<(v4&3))|(1>>(8-(v4&3))))&0xff
f+=chr((v7[i]-rol-1)^0xc7)
v4+=v7[i]
v4&=0xff
print(f)

[网鼎杯 2020 青龙组]bang

下了一堆安卓脱壳的软件不会用,还有模拟器什么的,网上的教程都有亿点简略……最后开谷歌搜到了BlackDex这玩意,下在手机上直接脱壳了 不就是懒得装模拟器

脱壳完之后是几个文件,也不知道逆哪个,readme里也没写咋用……麻了啊
我根据我对于apk的朴素认知猜测了一下,新建文件夹,把脱壳产生的几个文件丢进去,然后打成压缩包,后缀改成apk,放进jadx里反编译搜字符串,成功~

[SUCTF2018]babyre

刚开始写脚本每次没有把v6清零导致每次运算都带上次结果,所以怎么也跑不出来,呜呜呜
每次新的循环赋值一定要把之前的内容清零啊啊喂
还有就是看着tqdm真是个好东西啊哈哈哈,省去了等待的不安

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
v4=[2,3,2,1,4,7,4,5,10,11,10,9,14,15,12,13,16,19,16,17,20,23,22,19,28,25,30,31,28,25,26,31]
v5=[ord(i) for i in "$!\"'$!\"#().+$-&/81:;4=>7092;<567HIBBDDFGHIJJMMONPPRSUTVWYYZ[\\]^^``ccdeggiikklmnnpprstuwwxy{{}}"]+[0]*60
v5[94] = 127
v5[95] = 127
v5[96] = 0x81
v5[97] = 0x81
v5[98] = 0x83
v5[99] = 0x83
v5[100] = 0x8C
v5[101] = 0x8D
v5[102] = 0x8E
v5[103] = 0x8F
v5[104] = 0x88
v5[105] = 0x89
v5[106] = 0x8A
v5[107] = 0x8B
v5[108] = 0x8C
v5[109] = 0x8D
v5[110] = 0x8E
v5[111] = 0x87
v5[112] = 0x98
v5[113] = 0x91
v5[114] = 0x92
v5[115] = 0x93
v5[116] = 0x94
v5[117] = 0x95
v5[118] = 0x96
v5[119] = 0x97
v5[120] = 0x98
v5[121] = 0x99
v5[122] = 0x9A
v5[123] = 0x9A
v5[124] = 0x9C
v5[125] = 0x9C
v5[126] = 0x9E
v5[127] = 0x9E
v5[128] = 0xA0
v5[129] = 160
v5[130] = 0xA2
v5[131] = 0xA2
v5[132] = 0xA4
v5[133] = 0xA4
v5[134] = 0xA6
v5[135] = 0xA6
v5[136] = 0xA8
v5[137] = 0xA8
v5[138] = 0xAA
v5[139] = 0xAA
v5[140] = 0xAC
v5[141] = 0xAC
v5[142] = 0xAE
v5[143] = 0xAE
v5[144] = 0xB0
v5[145] = 0xB1
v5[146] = 0xB2
v5[147] = 0xB3
v=v4+v5

from tqdm import trange
for key in trange(0x10000):
i=8
v6=[0]*100
while i!=0:
i-=1
j=22
while j!=0:
v9=v[22*i+j-1]
j-=1
v10=(v9>>((key>>(2*i))&3))&1
v6[j]|=v10<<i
v6[j]&=0xff
if v6[0]==ord('S') and v6[1]==ord('U') and v6[2]==ord('C') and v6[3]==ord('T') and v6[4]==ord('F') and v6[5]==ord('{'):
break

for f in v6:
if f==0:
break
else:
print(chr(f),end='')

[MRCTF2020]EasyCpp

C++代码真滴丑……
异或1,然后分解质因数,把质因数从小到大拼接起来,中间用空格(后面换成等号)就是密文。为了方便,手动把最前面的等号删了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
s=[]
s.append('zqE=z=z=z')
s.append('lzzE')
s.append('ll=T=s=s=E')
s.append('zATT')
s.append('s=s=s=E=E=E')
s.append('EOll=E')
s.append('lE=T=E=E=E')
s.append('EsE=s=z')
s.append('AT=lE=ll')
f=''
for i in s:
i=i.replace('O','0')
i=i.replace('l','1')
i=i.replace('z','2')
i=i.replace('E','3')
i=i.replace('A','4')
i=i.replace('s','5')
i=i.replace('G','6')
i=i.replace('T','7')
i=i.replace('B','8')
i=i.replace('q','9')
t=i.split('=')
num=1
for j in t:
num*=int(j)
f+=str(num^1)
print(f)
import hashlib
print(hashlib.md5(f.encode()).hexdigest().swapcase())

Dig the way

pwn题,8会(逃

[羊城杯 2020]Bytecode

属于是体力活

[HDCTF2019]MFC

MFC,8会(bushi

[ACTF新生赛2020]Splendid_MineCraft

两个SMC,又忘了异或的运算优先级比加法低,被折磨N年……
这个题真的做的想死…… 第一步还好说,第二步动调的时候不知道IDA为啥SMC老出不来,然后又破罐子破摔试了几次居然又可以了emmmm 不知道到底是什么问题,我不就把F8换成F7了吗…… SMC调好之后的汇编代码反编译出来也是一言难尽,还不如硬刚汇编……其实真的去看汇编也没想象中那么难懂emmm,还是克服一下畏惧吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
box=[
0xF6,0xA3,0x5B,0x9D,0xE0,0x95,0x98,0x68
,0x8C,0x65,0xBB,0x76,0x89,0xD4,0x09,0xFD,0xF3,0x5C,0x3C,0x4C,0x36,0x8E,0x4D,0xC4
,0x80,0x44,0xD6,0xA9,0x01,0x32,0x77,0x29,0x90,0xBC,0xC0,0xA8,0xD8,0xF9,0xE1,0x1D
,0xE4,0x67,0x7D,0x2A,0x2C,0x59,0x9E,0x3D,0x7A,0x34,0x11,0x43,0x74,0xD1,0x62,0x60
,0x02,0x4B,0xAE,0x99,0x57,0xC6,0x73,0xB0,0x33,0x18,0x2B,0xFE,0xB9,0x85,0xB6,0xD9
,0xDE,0x7B,0xCF,0x4F,0xB3,0xD5,0x08,0x7C,0x0A,0x71,0x12,0x06,0x37,0xFF,0x7F,0xB7
,0x46,0x42,0x25,0xC9,0xD0,0x50,0x52,0xCE,0xBD,0x6C,0xE5,0x6F,0xA5,0x15,0xED,0x64
,0xF0,0x23,0x35,0xE7,0x0C,0x61,0xA4,0xD7,0x51,0x75,0x9A,0xF2,0x1E,0xEB,0x58,0xF1
,0x94,0xC3,0x2F,0x56,0xF7,0xE6,0x86,0x47,0xFB,0x83,0x5E,0xCC,0x21,0x4A,0x24,0x07
,0x1C,0x8A,0x5A,0x17,0x1B,0xDA,0xEC,0x38,0x0E,0x7E,0xB4,0x48,0x88,0xF4,0xB8,0x27
,0x91,0x00,0x13,0x97,0xBE,0x53,0xC2,0xE8,0xEA,0x1A,0xE9,0x2D,0x14,0x0B,0xBF,0xB5
,0x40,0x79,0xD2,0x3E,0x19,0x5D,0xF8,0x69,0x39,0x5F,0xDB,0xFA,0xB2,0x8B,0x6E,0xA2
,0xDF,0x16,0xE2,0x63,0xB1,0x20,0xCB,0xBA,0xEE,0x8D,0xAA,0xC8,0xC7,0xC5,0x05,0x66
,0x6D,0x3A,0x45,0x72,0x0D,0xCA,0x84,0x4E,0xF5,0x31,0x6B,0x92,0xDC,0xDD,0x9C,0x3F
,0x55,0x96,0xA1,0x9F,0xCD,0x9B,0xE3,0xA0,0xA7,0xFC,0xC1,0x78,0x10,0x2E,0x82,0x8F
,0x30,0x54,0x04,0xAC,0x41,0x93,0xD3,0x3B,0xEF,0x03,0x81,0x70,0xA6,0x1F,0x22,0x26
,0x28,0x6A,0xAB,0x87,0xAD,0x49,0x0F,0xAF,0x90,0x90,0x33,0xFF,0x51,0x53,0x83,0xFF
]
s=[0x30, 0x04, 0x04, 0x03, 0x30, 0x63]
for i in range(6):
print(chr(box.index(s[i])^(0x83+i)),end='')

[GWCTF 2019]babyvm

忘了记录

[ACTF新生赛2020]fungame

出题人脑洞好大哈哈哈哈哈哈哈

[NPUCTF2020]Baby Obfuscation

这符号表不扣还不如扣了……这个出题人终于完成了我一直以来的梦想:手动扣符号表(就是自己把函数名字改成奇奇怪怪的没人认识的字母(bushi
不过这种纯逆算法的题,还是肝就能出来的,好吧~试了一下angr爆不出来,只好手逆了,看过track神手过混淆的那篇文章之后觉得大为震撼,虽然看起来是一团浆糊的代码,但其实还是能看出来挺多东西的hhhhhhhhh 直接克服了我对这种一团浆糊的代码的恐惧
加密逻辑一共有五处,但其实有两处走不到,所以就剩三处,剩的三处也很简单,一次加一次异或,话说不知道为啥我开始调试的时候那个i_0是等于1的 不过这block第一位怎么看都不可能参与运算的吧啊喂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'''
block=~(~(flag[i-1])+index[(i-1)%4])
block^=~(~(flag[i-1])+index[(i-1)%4])
block*=8+2
'''
ind=[2,3,4,5]
flag=''
block=[0,0x1E79, 0x1E79, 0x2135, 0x170D, 0x1F41, 0x1901, 0x2CED,
0x11F9, 0x2649, 0x2581, 0x2DB5, 0x14B5, 0x25E5, 0x2A31, 0x30D5]
for i in range(1,len(block)):
block[i]//=100
block[i]^=ind[(i-1)%4]
block[i]+=ind[(i-1)%4]
flag+=chr(block[i])
print(flag)

???两分钟速通题???
直接jadx打开,base64转图片,结束

[SUCTF2019]hardcpp

纪念我手逆出来的第一个OLLVM啊hhhhhhhhhh 不就是懒得学怎么去除控制流平坦化嘛
不过感觉上OLLVM也就是增加了几个控制条件而已,然后多了一些糨糊代码, 看不懂的直接略过就可以了 理论上还是可以手逆出来的~
至于这个题就是只有while中间那一坨代码有用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
int v5; // ecx
int v6; // eax
int v7; // eax
int v8; // eax
int v9; // eax
int v10; // eax
char v11; // al
char v12; // al
char v13; // al
char v14; // al
char v15; // al
int v16; // ecx
int v17; // eax
int v18; // eax
int v19; // eax
int v20; // eax
int v21; // eax
int v22; // ecx
char v24; // al
char v25; // al
char v26; // al
char v27; // al
int v28; // [rsp+9Ch] [rbp-94h]
char v29[8]; // [rsp+A0h] [rbp-90h] BYREF
char v30[8]; // [rsp+A8h] [rbp-88h] BYREF
char v31[8]; // [rsp+B0h] [rbp-80h] BYREF
char v32[8]; // [rsp+B8h] [rbp-78h] BYREF
char v33[8]; // [rsp+C0h] [rbp-70h] BYREF
char v34[7]; // [rsp+C8h] [rbp-68h] BYREF
char v35; // [rsp+CFh] [rbp-61h]
int cir_i; // [rsp+D0h] [rbp-60h]
int v37; // [rsp+D4h] [rbp-5Ch]
int rand_sub1; // [rsp+D8h] [rbp-58h]
int rand1; // [rsp+DCh] [rbp-54h]
char ipt; // [rsp+E0h] [rbp-50h] BYREF
char v41[23]; // [rsp+E1h] [rbp-4Fh] BYREF
char v42[8]; // [rsp+F8h] [rbp-38h] BYREF
char v43[8]; // [rsp+100h] [rbp-30h] BYREF
char v44[8]; // [rsp+108h] [rbp-28h] BYREF
char v45[4]; // [rsp+110h] [rbp-20h] BYREF
int rand2; // [rsp+114h] [rbp-1Ch]
const char **v47; // [rsp+118h] [rbp-18h]
int v48; // [rsp+120h] [rbp-10h]
int v49; // [rsp+124h] [rbp-Ch]
int rand_sub2; // [rsp+128h] [rbp-8h]
bool v51; // [rsp+12Eh] [rbp-2h]
bool v52; // [rsp+12Fh] [rbp-1h]

v49 = 0;
v48 = argc;
v47 = argv;
rand2 = time(0LL);
puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");
ipt = getchar();
fgets(v41, 21, stdin);
rand1 = time(0LL);
rand_sub1 = rand1 - rand2;
rand_sub2 = rand1 - rand2;
v28 = 1883240069;
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( v28 == -2090540314 )
{
v35 = rand_sub1 ^ *(&ipt + cir_i);// v35=input[i]^rand_sub
v34[0] = main::$_0::operator()(v44, (unsigned int)v35);// v34=v35
v33[0] = main::$_1::operator()(v42, (unsigned int)*(&ipt + rand_sub1 + cir_i - 1));// v33=input[rand_sub+i-1]
v11 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v33, 7);// v11=enc%7
v35 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()((__int64)v34, v11);// v35=v34+v11
v32[0] = main::$_2::operator()(v45, (unsigned int)v35);// v32=v35
v31[0] = main::$_2::operator()(v45, (unsigned int)*(&ipt + rand_sub1 + cir_i - 1));// v31=input[rand_sub+i-1]
v12 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v31, 18);// v12=v31^18
v30[0] = main::$_3::operator()(v43, (unsigned int)v12);// v30=v12
v13 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v30, 3LL);// v13=v30*3
v29[0] = main::$_0::operator()(v44, (unsigned int)v13);// v29=v13
v14 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()((__int64)v29, 2);// v14=v29+2
v15 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v32, v14);// v15=v32^v14
v16 = 1299792285;
v35 = v15;
v52 = enc[cir_i - 1] != v15;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v16 = -424557443;
v28 = v16;
}
if ( v28 != -1957245689 )
break;
v28 = 1587023630;
}
if ( v28 != -1884297895 )
break;
v28 = -984930794;
puts("You win");
}
if ( v28 != -1852837876 )
break;
v18 = 1375414539;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v18 = 1154698238;
v28 = v18;
}
if ( v28 != -1220297252 )
break;
v21 = -1884297895;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v21 = -984930794;
v28 = v21;
}
if ( v28 != 0xC54B2616 )
break;
puts("You win");
v22 = -1884297895;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v22 = 456293525;
v28 = v22;
}
if ( v28 != -740226431 )
break;
v4 = 2137069843;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v4 = 739060228;
v28 = v4;
}
if ( v28 == -459161563 )
exit(0);
if ( v28 != -424557443 )
break;
v17 = 1856799435;
if ( v52 )
v17 = -1852837876;
v28 = v17;
}
if ( v28 != -350248402 )
break;
v28 = -55540564;
}
if ( v28 != -294402024 )
break;
v6 = 1721328217;
if ( v51 )
v6 = -459161563;
v28 = v6;
}
if ( v28 != -226137905 )
break;
v28 = 24093646;
}
if ( v28 != -55540564 )
break;
v20 = -350248402;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v20 = -226137905;
v28 = v20;
}
if ( v28 != 24093646 )
break;
++cir_i;
v28 = 1587023630;
}
if ( v28 == 456293525 )
break;
switch ( v28 )
{
case 506113758:
puts("Let the silent second hand take the place of my doubt...");
exit(0);
case 623475433:
cir_i = 1;
v28 = 1132336453;
break;
case 739060228:
v37 = strlen(&ipt);
v51 = v37 != 21;
v5 = 2137069843;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v5 = -294402024;
v28 = v5;
break;
case 1011555671:
v10 = 1299792285;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v10 = -2090540314;
v28 = v10;
break;
case 1132336453:
v8 = 623475433;
cir_i = 1;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v8 = -1957245689;
v28 = v8;
break;
case 1154698238:
exit(0);
case 1299792285:
v35 = rand_sub1 ^ *(&ipt + cir_i);
v34[0] = main::$_0::operator()(v44, (unsigned int)v35);
v33[0] = main::$_1::operator()(v42, (unsigned int)*(&ipt + rand_sub1 + cir_i - 1));
v24 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v33, 7);
v35 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()((__int64)v34, v24);
v32[0] = main::$_2::operator()(v45, (unsigned int)v35);
v31[0] = main::$_2::operator()(v45, (unsigned int)*(&ipt + rand_sub1 + cir_i - 1));
v25 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v31, 18);
v30[0] = main::$_3::operator()(v43, (unsigned int)v25);
v26 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v30, 3LL);
v29[0] = main::$_0::operator()(v44, (unsigned int)v26);
v27 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()((__int64)v29, 2);
v35 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v32, v27);
v28 = -2090540314;
break;
case 1375414539:
exit(0);
case 1587023630:
v9 = -1220297252;
if ( cir_i < 21 )
v9 = 1011555671;
v28 = v9;
break;
case 1721328217:
v7 = 623475433;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v7 = 1132336453;
v28 = v7;
break;
case 1856799435:
v19 = -350248402;
if ( y < 10 || ((((_BYTE)x - 1) * (_BYTE)x) & 1) == 0 )
v19 = -55540564;
v28 = v19;
break;
case 1883240069:
v3 = -740226431;
if ( rand_sub2 > 0 )
v3 = 506113758;
v28 = v3;
break;
default:
v37 = strlen(&ipt);
v28 = 739060228;
break;
}
}
return 0;
}

所以最后的表达式就是

1
enc[i-1]=(s[i]^rand_sub+s[rand_sub+i-1]%7)^((s[rand_sub+i-1]^18)*3+2)

而这个rand_sub盲猜一波应该是0,不然索引对不上,不过就算不是0也可以在0到enc的长度之内爆破,所以问题不大hhh
s[0]不知道,在32到0x7f之内爆破一下
这个题有狗啊,这是SUCTF的题,我本来盲猜开头是SUCTF{,赌s[0]是’S’,结果出不来,看了一下题解开头是’#flag{‘,出题人真的太狗了啊hhhhhh

1
2
3
4
5
6
7
8
9
10
11
12
13
enc=[0xF3, 0x2E, 0x18, 0x36, 0xE1, 0x4C, 0x22, 0xD1, 0xF9, 0x8C, 
0x40, 0x76, 0xF4, 0x0E, 0x00, 0x05, 0xA3, 0x90, 0x0E, 0xA5]
for k in range(32,0x7f):
r=[]
r.append(k)
for i in range(1,len(enc)+1):
r.append(((enc[i-1]^((r[i-1]^18)*3+2))-(r[i-1]%7))&0xff)
f=''
for i in r:
f+=chr(i)
if '{' in f and '}' in f:
print(f)

[NPUCTF2020]BasicASM

水题,学会看汇编……别骂了我就是只会F5的呜呜呜呜呜呜呜呜

1
2
3
4
5
6
7
8
9
s='662e61257b26301d7972751d6b2c6f355f3a38742d74341d61776d7d7d'
f=[]
for i in range(0,len(s),2):
f.append(int(s[i:i+2],16))

for i in range(1,len(f),2):
f[i]^=0x42
for i in f:
print(chr(i),end='')

[MRCTF2020]Shit

我不理解,为什么给了源码,源码里还有注释的解密脚本

[De1CTF2019]Re_Sign

8会脱壳

[watevrCTF 2019]Repyc

虚拟机真tm难搞……动调把报错的代码都删了,好多没用上的代码还列表越界,就离谱……
还是尽量用uncompyle6反编译pyc吧,虽然麻烦了一点……被那个网站的编码坑惨了。不知道是怎么回事,这种字符用那个网站解码出来跟uncompyle6的不一样,可能是编码方式的问题,关键是它显示的也是十六进制流啊,搞不懂这为什么会出错……差点心态爆炸了属于是
不过感觉渐渐摸到一点虚拟机的门槛吧……呜呜呜呜呜呜呜呜我真的感觉虚拟机好难搞啊为什么他们做虚拟机看起来都这么轻松呜呜呜呜呜呜呜呜呜

{.line-numbers}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def fun1(op):
eax = 0
t2 = 0
t3 = [0] * 2 ** (2 * 2)
t4 = [0] * 100
stack = []
while op[eax][0] != 'nop':
opcode = op[eax][0].lower()
this_list = op[eax][1:]
if opcode == 'add':
t3[this_list[0]] = t3[this_list[1]] + t3[this_list[2]]
elif opcode == 'xor':
t3[this_list[0]] = t3[this_list[1]] ^ t3[this_list[2]]
elif opcode == 'sub':
t3[this_list[0]] = t3[this_list[1]] - t3[this_list[2]]
elif opcode == 'mul':
t3[this_list[0]] = t3[this_list[1]] * t3[this_list[2]]
elif opcode == 'div':
t3[this_list[0]] = t3[this_list[1]] / t3[this_list[2]]
elif opcode == 'and':
t3[this_list[0]] = t3[this_list[1]] & t3[this_list[2]]
elif opcode == 'or':
t3[this_list[0]] = t3[this_list[1]] | t3[this_list[2]]
elif opcode == 'equ':
t3[this_list[0]] = t3[this_list[0]]
elif opcode == 'lea':
t3[this_list[0]] = t3[this_list[1]]
elif opcode == 'mov':
t3[this_list[0]] = this_list[1]
elif opcode == 'mov1':
t4[this_list[0]] = t3[this_list[1]]
elif opcode == 'mov2':
t3[this_list[0]] = t4[this_list[1]]
elif opcode == 'clear0':
t3[this_list[0]] = 0
elif opcode == 'clear1':
t4[this_list[0]] = 0
elif opcode == 'input':
t3[this_list[0]] = input(t3[this_list[1]])
elif opcode == 'input0':
t4[this_list[0]] = input(t3[this_list[1]])
elif opcode == 'print':
print(t3[this_list[0]])
elif opcode == 'print0':
print(t4[this_list[0]])
elif opcode == 'mov3':
eax = t3[this_list[0]]
elif opcode == 'mov4':
eax = t4[this_list[0]]
elif opcode == 'pop':
eax = stack.pop()

elif opcode == 'cmp+push1':
t3[7] = 0
for i in range(len(t3[this_list[0]])):
if t3[this_list[0]] != t3[this_list[1]]:
t3[7] = 1
eax = t3[this_list[2]]
stack.append(eax)
elif opcode == 'xor+mov':
k3 = ''
for i in range(len(t3[this_list[0]])):
k3 += chr(ord(t3[this_list[0]][i]) ^ t3[this_list[1]])

t3[this_list[0]] = k3
elif opcode == 'sub+mov':
k3 = ''
for i in range(len(t3[this_list[0]])):
k3 += chr(ord(t3[this_list[0]][i]) - t3[this_list[1]])

t3[this_list[0]] = k3
eax += 1

fun1([
['mov',0,'Authentication token: '],
['input0',0,0],
['mov',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'],
['mov',2,2 ** (3 * 2 + 1) - 2 ** (2 + 1)],
['mov',4,15],
['mov',3,1],
['mul',2,2,3],
['add',2,2,4],
['equ',0,2],
['claer0',3],
['xor+mov',6,3],
['mov',0,'Thanks.'],
['mov',1,'Authorizing access...'],
['print',0],
['mov2',0,0],
['xor+mov',0,2],
['sub+mov',0,4],
['mov',5,19],
['cmp+push1',0,6,5],
['print',1],
['nop'],
['mov',1,'Access denied!'],
['print',1],
['nop']])

这是用在线网站反编译的python代码,当然,我修了一下诡异的字符,然后删去了报错还没用的cmp部分来动调观察用来异或和减的值是多少。
77行的mov将密文放到索引为6的地方,93行比较索引为6的地方(即密文)和索引为0的地方(可以推测是明文加密后的结果),此前在索引为0的地方加密的只有90和91行的异或和减,所以整个过程就是把明文异或然后减,要恢复明文只需加然后异或就可以了。至于减和异或的值,可以自己手动调试取得。

1
2
3
4
5
6
a='á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë'
b = ''
for i in a:
b += chr(ord(i) + 15 ^ 135)

print(b)

HellScream

RSA,8会

[FlareOn1]Javascrap

PHP真好玩……

[FlareOn6]Memecat Battlestation

好奇怪的题,两次验证,一次明文一次异或。
但是我很好奇,最后成功会显示flag图片,但是为什么资源文件里找不到

1
2
3
s="\x03 &$-\x1e\x02 //./"
for i in s:
print(chr(ord(i)^ord('A')),end='')

[FlareOn1]Shellolololol

动调看栈窗口出的,emmm没懂考点在哪里 难道就是动调吗

[CFI-CTF 2018]powerPacked

ELF的upx壳,嗯,长知识了,我一直以为只有PE有UPX壳的……
CFI{i_love_powerpc 这玩意怎么看都不可能是flag吧啊喂
但它真的是flag诶,加个大括号就好了……

[b01lers2020]chugga_chugga

嘶,翻buu发现这题flag交了,但是这里忘了记录了,emmm应该不难吧(逃

关于本文

本文作者 云之君, 许可由 CC BY-NC 4.0.