NewStar2022wp

Week 2

FindME

ida64打开

image-20220930235535614

打开sub_1BCD函数 发现是一堆return 的函数

image-20220930235700807

image-20220930235756541

找到其中一个有用的函数之后对 s 按 x直接查询交叉引用

image-20220930235909095

从下往上执行

Likemayasp

这题看起来是个ASP壳,但是PE识别的结果是UPX壳

image-20220930230211565

可以利用010修改壳头即可用UPX工具破开。当然也可以利用程序在运行的时候自己解壳的特性来动态调试。

ida打开,选择Local Windows debugger

Debugger——Attach to Process——选择需要调试的进程

image-20220930231158830

动态调试即可到达加密函数

0564fb81e93b43f34e458c7581381f1

对密文进行一个长度判断后,位移后4个数一组进行判断

e812521a5b3609e106010eacfd7fda6

写py脚本解密

1
2
3
4
5
6
7
8
x = [0x0D803C1FC098, 0x0E20360BC097, 0x0FE02A1C00A0, 0x0FA0121040CB, 0x0F2032104092, 0x0D6015884082]
for i in x:
z = ""
z += chr(((i >> 37) ^ 0xA) & 0xff)
z += chr((((i << 27) >> 50) ^ 0x14) & 0xff)
z += chr((((i << 41) >> 55) ^ 0x1E) & 0xff)
z += chr(~(((i << 50) >> 50)) & 0xff)
print(z, end="")
1
flag{x1hu@n_w0_4sp_ma??}

Petals

ida64打开

image-20220930233632468

sub_160C是判断函数

sub_1208 + 1无法跳转到函数,查看汇编

image-20220930233735802

image-20220930233755314

发现花指令,上面多了一行push rbx

D 变为数据后重新定位

image-20220930233854879

不难看出09才是函数的开头

选中后按p定义为函数

image-20220930233940746

image-20220930233952235

然而修改后还有红色的,打开汇编再往下看

image-20220930234022685

jn jnz 花指令

D 完后 nop掉多余的垃圾数据

一定要nop掉,这两节本来应该是同一个函数,被垃圾数据分割后不仅反汇编错误,还错误的将sub1208识别为void,原本应该是有返回值的。不nop掉会导致前半部分的函数不完整而且使得后半部分的函数的变量无法正常继承。

image-20220930234247534

并且将函数的返回值定义为int *

image-20220930234338778

首先初始化一个v5的数组作为码表,然后再进行替换,逆向的方法选择爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import hashlib
x = []
input = [208, 208, 133, 133, 128, 128, 197, 138, 147, 137,
146, 143, 135, 136, 159, 143, 197, 132, 214, 209,
210, 130, 211, 222, 135]
for i in range(0, 256):
x.append(~(i ^ 25)&0xff)

for i in range(0, 25):
for j in range(0, 256):
if(input[i] == x[j]):
print(chr(j),end="")
print()
# 66ccff#luotianyi#b074d58a
m = hashlib.md5()
m.update("66ccff#luotianyi#b074d58a".encode())
print(m.hexdigest())
1
flag{d780c9b2d2aa9d40010a753bc15770de}

Week 3

Zzzzz3333

32位IDA

image-20221005203130856

用z3解出x,然后再输出

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
from z3 import *
x = Ints(f"x{i}" for i in range(0, 8))
s = Solver()
s.add(x[3] + 4 * x[2] + x[7] + 4 * (x[3] + 4 * x[2]) + 3 * (x[4] + 4 * x[0]) + 2 * (x[5] + 4 * x[6]) + 11 * x[1] == 6426)
s.add(11 * (x[0] + x[7] + x[3]) + 4 * (x[5] + 2 * x[4]) + x[2] + 45 * x[1] + 7 * x[6] == 9801)
s.add(5 * x[1] + 2 * (x[4] + x[6] + x[5] + 2 * (x[7] + x[3]) + x[2] + 2 * (x[6] + x[5] + 2 * (x[7] + x[3])) + 8 * x[0]) == 6021)
s.add(19 * x[0] + 9 * x[1] + 67 * x[7] + 5 * (x[2] + x[6]) + 7 * (x[5] + 4 * x[3]) + 4 * x[4] == 14444)
s.add(22 * x[5] + 5 * (x[4] + 2 * (x[3] + x[1] + 2 * x[0])) + 4 * (x[7] + x[6]) + 6 * x[2] == 7251)
s.add(19 * x[3] + 3 * (x[7] + x[2] + 4 * x[7] + x[6] + 2 * (x[7] + x[2] + 4 * x[7])) + 4 * (x[0] + x[5] + x[1] + 2 * (x[0] + x[5])) == 10054)
s.add(7 * x[0] + 17 * (x[3] + x[1]*2) + 11 * (x[4] + 2 * x[5]) + 2 * (x[2] + x[6] + 4 * x[2] + 6 * x[7]) == 10735)
s.add(x[6] + x[4] + 11 * x[2] + 15 * (x[3] + 2 * x[7]) + x[1]*2 + 43 * x[0] + 21 * x[5] == 11646)

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

flag = [102, 97, 108, 108, 119, 49, 110, 100]
for i in flag:
print(chr(i & 0xff), end="")

y = [
0, 13, 13, 11, 12, 107, 20, 30, 28, 82,
95, 95, 40, 120, 29, 59, 37, 14, 3, 0,
86, 16, 79, 25
]

for i in range(0, 24):
print(chr((y[i] & (flag[i & 7] ^ y[i]) | ~y[i] & (~y[i] ^ ~flag[i & 7])) & 0xff), end="")

flag{Zzzz333_Is_Cool!!!}

EzTea

64位ida

image-20221005205054132

点开函数,发现是xxtea加密

image-20221005205253305

只不过修改了MX和magic值

脚本

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
#include <cstdio>
#include <cstdint>

using namespace std;

#define MX (z>>4^y<<2) + (y>>3 ^ z<<5)^(sum^y) + (k[ i&3 ^ e] ^ z);

long btea(unsigned long* v, long n, unsigned long* k)
{
unsigned long z=v[n-1], y=v[0], sum=0, e, DELTA=0x11451400;
long i, q ;
if (n > 1) {
q = 6 + 52/n;
while (q-- > 0) {
sum += DELTA;
e = (sum >> 2) & 3;
for (i=0; i<n-1; i++){
y = v[i+1];
z = v[i] += MX;
}
y = v[0];
z = v[n-1] += MX;
}
return 0 ;
}


else if (n < -1) {
n = -n;
q = 6 + 52/n;
sum = q*DELTA ;
while (sum != 0) {
e = (sum >> 2) & 3;
for (i=n-1; i>0; i--) {
z = v[i-1];
y = v[i] -= MX;
}
z = v[n-1];
y = v[0] -= MX;
sum -= DELTA;
}
return 0;
}
return 1;
}

int main()
{
unsigned long key[] = {0x19, 0x19, 0x08, 0x10};
unsigned long EntryData[] = {0x38FA8A82, 0x0D7501380, 0x0E40969D, 0x4E169120, 0x713A29AB,
0x6CE5393D, 0x0B69D752E, 0x841A88E6, 0x6F31B459 };
btea(EntryData, -9, key);
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 4; k++) {
printf("%c", EntryData[j] & 0xff);
EntryData[j] >>= 8;
}
}
return 0;
}
1
flag{H0P3_U_L1k3_Th15_CUP_0f_TEa.}

The Slider’s Labyrinth

32位ida

image-20221005225658352

这里加了好几个花指令

image-20221005225718061

主要都是这种死循环的,直接nop

image-20221005230022013

还是红的,再将hlt给nop掉

image-20221005230104334

于是就能正常显示了

image-20221005230124689

分析过程

image-20221005230243637

发现将输入减掉97后四个case,即w a s d控制上下左右,while循环让人物一直走到墙才停止,并且每行的长度是16

image-20221005230422289

找到地图

image-20221005230455193

大概就长这样

# # # # # # # # # # # # # # # #
# * # #
# #
# # #
# # #
# # # #
# # #
# #
# # # O #
# # # # # # # # # # # # # # # #

走法不唯一,题目要求的是最短的一条

image-20221005230823504

image-20221005230831060

1
2
3
flag{f71516bdf07abd7bc0668db9d6352364}


Annnnnnggrr

本题主要考察angr的使用

ida无壳

image-20221014225958996

大哥爬楼梯

没什么好说的,基本上就是对着angr的模板写就行

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
import angr
import claripy

proj = angr.Project("./Annnnnggrr.exe", auto_load_libs=False)
star = 0x140001103 # 跳过输入
state = proj.factory.blank_state(addr=star)


password = claripy.BVS("password", 32 * 8)


ans = 0x140005640
state.memory.store(ans, password)

simg = proj.factory.simulation_manager(state)
check_addr = 0x14000248A
simg.explore(find = check_addr)

key = [0x4F, 0x17, 0x0C, 0x56, 0xDB, 0x67, 0x5D, 0x67,
0x32, 0x2B, 0x36, 0x03, 0x02, 0xF3, 0xA1, 0xE4,
0xC7, 0x27, 0xC1, 0xB6, 0x4C, 0xD7, 0x59, 0xA1,
0x71, 0x52, 0x9A, 0xE2, 0x21, 0x96, 0x0C, 0xCA]

if simg.found:
check_state = simg.found[0]
for i in range(32):
ch = check_state.memory.load(ans + i, 1)
check_state.solver.add(ch == key[i]) # 添加约束条件

sol = check_state.solver.eval(password, cast_to=bytes)
print(sol)

else:
print("Not Solution")
1
flag{umm_I_can't_calc_1t_@t_all}

funnyOTL_1

ida64位

这题主要是对c++的库函数的熟悉度

image-20221014230455452

输入flag{}包裹的总长为24位的密码

image-20221014230607425

然后就是加密后交换,唯一问题是这个随机数的问题,经过测试,Linux环境下随机数的值和Windows下是不一样的,以后要注意系统之间的差异

写脚本

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
enc =[ 76, 171, 120,  73, 104, 157,  81, 121, 117,  95,
125, 197, 99, 82, 76, 180, 79, 123, 103, 97,
111, 110, 107, 95]

key = [0x12,0x6,0x8,0xa,0x6,0x14,0xa,0x14,0,0xc,0x2,0x4]

for i in range(11, -1, -1):
sec1 = enc[i*2]
sec2 = enc[i*2+1]

fir1 = enc[key[i]]
fir2 = enc[key[i] + 1]


fir1 = fir1 ^ key[i]
fir2 = (~fir2) ^ key[i]

enc[i*2] = fir1
enc[i*2+1] = fir2

enc[key[i]] = sec1
enc[key[i] + 1] = sec2

s = ''
for i in enc:
s = chr(i & 0xff) + s
print(s)
1
flag{OTL_n0w_u_know_STL}

Week4

Hash

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
import hashlib

enc = [
'a2f17ed1c6a8bc31769cdf654df4b8a937042cb6',
'0ca8a2edb0c1d34a432a5a4464e0d6abd847c831',
'c359d69f3f08bb920f2c3b51133205533462093e',
'cc5c3fe6e7356a26a134cff5633349f597c40a9d',
'4ac4bb3f27f245ba9178651aa5cdedcbb2862e2a',
'a01e33f4dcdb6ba1ae9f34a97cf8f6deeedf1a8d',
'd3af70912a8c1b22cfdece071ba36bc4662b58fa',
'9395eab195d25b676d7d07075d3838a9ac19df21',
'fdb43c5ef76ecda0c1661d6d199b5bfac1db538a',
'da8e9997a010be78b20108ce79fec1fb9c63d8dc',
'809da627f1ad01d65864c376e3179b62d9d74261',
'8f61ee21ac7579626934e0ffb6a62b3d4a82eec4',
'e2a954758fdb61f869998e9788b7b7e48480b832',
'b8e3349b97532b27aa62b8718b68240179158144'
]

flag = ''

for i in range(14):

for x in range(33, 128):
for y in range(33, 128):
for z in range(33, 128):
ans = ''
ans = ans + chr(x&0xff) + chr(y&0xff) + chr(z&0xff)
m = hashlib.sha1()
m.update(ans.encode('utf-8'))
if m.hexdigest() == enc[i]:
flag = flag + ans

print(flag)
1
flag{Easy_Hash_And_Y0u_Solve_1t_Quickly!!}

Exception

32位ida

image-20221014223810878

乍一看只是单纯的tea,但是直接逆是解不出来的

image-20221014223948342

在tea加密里面塞入了一个try块

image-20221014224033090

分析异常,发现异常过滤器的返回值恒为1,即一定进入异常处理

image-20221014224158198

于是直接分析异常处理

image-20221014224231224

这里将delta 异或了一个0x12345678,编写脚本

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
#include <cstdio>
#include <cstdint>
#include <string>
#include <iostream>

using namespace std;

void decrypt(unsigned long* EntryData, unsigned long* Key)
{
unsigned long Mup = EntryData[0];
unsigned long Mdown = EntryData[1];

unsigned long sum = 0;
unsigned long delta = 0x9E3779B9;
int n=32;

//计算delta最后的值
for(int j = 0; j < 32; j++){
sum += delta;
delta ^= 0x12345678;
}

for(int i=0;i<n;i++){
Mdown -= ((Mup << 4) + Key[2]) ^ (Mup + sum) ^ ((Mup >> 5) + Key[3]);
Mup -= ((Mdown << 4) + Key[0]) ^ (Mdown + sum) ^ ((Mdown >> 5) + Key[1]);
delta ^= 0x12345678;//每次循环将delta异或后再减
sum -= delta;
}
EntryData[0] = Mup;
EntryData[1] = Mdown;
}

int main()
{
unsigned long key[] = {1,2,3,4};
unsigned char flag[] =
{
206, 33, 232, 136, 112, 157, 0, 11, 143, 230,
177, 145, 150, 234, 49, 1, 125, 157, 32, 163,
251, 125, 24, 169, 202, 197, 82, 196, 83, 103,
105, 169
};
for (size_t i = 0; i < 8; i+=2)
{
decrypt((unsigned long *)&flag[i*4],key);
}
for (size_t i = 0; i < 32; i++)
{
cout<<flag[i];
}
return 0;
}

1
flag{44C3A7F112DA2BE728F451C5E2D09558}

HelpMe

image-20221011124833051

解压后发现有一个ps1的owershell的脚本文件

题目的意思是一个excel文件被加密了

.enc是一个二进制文件,突破点在于Help.ps1脚本

1
2
$mypath = Split-Path -Parent $MyInvocation.MyCommand.Definition
&([scriptblock]::create((New-Object System.IO.StreamReader(New-Object System.IO.Compression.GzipStream((New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String('H4sIAKxePWMA/31RT2+bMBS/8yksxAHUYCVI66RMm5TQdJq6LFXJdslycPGDeDU2wi9a0LTv3mdos2yHXZDfD//++UWoGnAompa9Z/HuRiBsCdlUlQPcxx8BU4+xsBDINiWy6Yxl0yyjzzzL5tksTBK+tV+NOnleAaU10sVJED1BT5Jf4Ge6efwBxFz2CLs9m10HXvVBGGkblq7FiWVvrllaABYAkl0k+hCZo9ZBZTsWR8pIOJHi9B17OacaSe11vLpK2C/vuhvnPd3dPZLn2OIfv+R3EC1Wxd8Ji94hNJxKHDuFPc+7vkVbd6I99HwBbi2MqEEOTH439POG47y2EggIV/kyHJF7IaUytc/xX+WXe15gP5/f3+XF2yCqlB7koqZvBR6+N32tKuQn7RqS973chfCnDb8lAtEfQMiF1v6xXRwOMiFtY2XKwbLzmX24vAPa6xn2GwNTSoHC3zjjfNsJ42gDza0yQi+1LZ/i0X7CphM2HvlnMDUeLn34jXKtdeCFvd+fkRad5tYgGGTpN6GPwM7WKfHt8Gi+ALX3+Tn9DYNn5mIx06oCAAA='))),[System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))

真正的脚本应该是那段base64数据,python解密后再用gzip解压(这个是看网上那些恶意代码分析的文章看来了)

1
2
3
4
import base64
import gzip
text = "H4sIAKxePWMA/31RT2+bMBS/8yksxAHUYCVI66RMm5TQdJq6LFXJdslycPGDeDU2wi9a0LTv3mdos2yHXZDfD//++UWoGnAompa9Z/HuRiBsCdlUlQPcxx8BU4+xsBDINiWy6Yxl0yyjzzzL5tksTBK+tV+NOnleAaU10sVJED1BT5Jf4Ge6efwBxFz2CLs9m10HXvVBGGkblq7FiWVvrllaABYAkl0k+hCZo9ZBZTsWR8pIOJHi9B17OacaSe11vLpK2C/vuhvnPd3dPZLn2OIfv+R3EC1Wxd8Ji94hNJxKHDuFPc+7vkVbd6I99HwBbi2MqEEOTH439POG47y2EggIV/kyHJF7IaUytc/xX+WXe15gP5/f3+XF2yCqlB7koqZvBR6+N32tKuQn7RqS973chfCnDb8lAtEfQMiF1v6xXRwOMiFtY2XKwbLzmX24vAPa6xn2GwNTSoHC3zjjfNsJ42gDza0yQi+1LZ/i0X7CphM2HvlnMDUeLn34jXKtdeCFvd+fkRad5tYgGGTpN6GPwM7WKfHt8Gi+ALX3+Tn9DYNn5mIx06oCAAA="
print(gzip.decompress(base64.b64decode(text)).decode())

跑完就会出现真正的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$timestamp = ([DateTimeOffset](Get-Date "Sat Oct 01 2022 20:22:21")).ToUnixTimeSeconds()
$key = New-Object Byte[] 16
Get-Random -Max 256 -SetSeed $timestamp >$null
for ($index = 0; $index -lt 16; $index++) {$key[$index] = [byte](Get-Random -Max 256)}
$AES = New-Object System.Security.Cryptography.AesManaged
$AES.Key = $key
$AES.Mode = "ECB"
$AES.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7
$file = "$mypath\mygift.xlsm"
$bytes = [System.IO.File]::ReadAllBytes("$file")
$Encryptor = $AES.CreateEncryptor()
$encdata = $Encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
$Encryptor.Dispose()
$AES.Dispose()
Set-Content -Value $encdata -Encoding Byte "$file.enc"

首先用Sat Oct 01 2022 20:22:21生成16位随机数,然后再AES的ECB模式加密文件

首先写脚本,用powershell跑出key

1
2
3
4
5
6
7
8
9
$timestamp = ([DateTimeOffset](Get-Date "Sat Oct 01 2022 20:22:21")).ToUnixTimeSeconds()
$key = New-Object Byte[] 16
Get-Random -Max 256 -SetSeed $timestamp >$null
for ($index = 0; $index -lt 16; $index++) {$key[$index] = [byte](Get-Random -Max 256)}

for ($index = 0; $index -lt 16; $index++) {
Write-Host $key[$index]
Write-Host ","
}
1
2
key = [105, 192, 50, 118, 175, 152, 128, 155, 147, 80, 183, 37, 190, 22, 242, 78]
key = b'i\xc02v\xaf\x98\x80\x9b\x93P\xb7%\xbe\x16\xf2N'

然后AES对mygift.xlsm.gift文件进行解密

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Cipher import AES
file = open("C:\\Users\\74592\\Desktop\\NewStarCTF2022\\week4\\HelpMe\\mygift.xlsm.enc", "rb")
data = file.read()

key = b'i\xc02v\xaf\x98\x80\x9b\x93P\xb7%\xbe\x16\xf2N'

aes = AES.new(key, AES.MODE_ECB)

out = aes.decrypt(data)

file2 = open("C:\\Users\\74592\\Desktop\\NewStarCTF2022\\week4\\HelpMe\\ans.xls", "wb")
file2.write(out)

然后就会生成一个ans.xls文件。题目说是excel工作表就直接加.xls上去了

image-20221011125910800

但是文件损坏了,用在线xls修复工具修复后再打开

image-20221011125948035

出现一个数组并且有个宏,猜测有可能是宏里面写了什么东西,Alt + F11打开vba编辑器,发现加密的代码

image-20221011130105675

大意是将excel里面是数组按照arr数组里面的顺序和x异或,然后x = (a * x + b) % 255,脚本解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enc = [ 62, 163, 115, 241, 149,	89,	216,  45,
20, 138, 220, 8, 75, 42, 135, 93,
161, 60, 115, 215, 169, 66, 32, 132,
141, 21, 184, 95, 159, 3, 121, 91]


arr = [ 2, 19, 16, 21, 14, 24, 18, 15,
5, 0, 6, 23, 13, 29, 11, 9,
7, 10, 20, 12, 1, 26, 30, 31,
27, 25, 3, 28, 8, 22, 17, 4]

a = 20
b = 22
x = 21

for i in range(32):
tmp = enc[arr[i]]
tmp = tmp ^ x
x = (a * x + b) % 255
print(chr(tmp&0xff), end="")
1
flag{This_is_@_begin_about@hack}

Week5

拔丝溜肆

64位ida无壳

image-20221017225121337

记住这个srand(114514)

点进base64plus函数

image-20221017225219365

发现在基本的base64上还多了个函数

image-20221017225240067

这里每次循环都生成一个随机数然后让key,即码表整体向右循环位移

随机数种子则是之前出现过的114514

写脚本得出随机数

1
2
3
4
5
6
7
8
9
int main()
{
srand(114514);
for(int i = 0; i < 14; i++){
printf("%d, ", rand()%64);
}
return 0;
}
// randnum = {41, 40, 57, 10, 62, 30, 59, 25, 12, 0, 46, 58, 1, 24}

然后只要在base64解码的时候加入码表移动就好了

当然也可以解码14次只取对应位置的三个字符

flag{12573882-1CF1-EB5E-C965-035B1F263C38}

E4sy_Mix

ida32位无壳

image-20221017224048755

SMC自修改,使用idc脚本

1
2
3
4
5
6
7
8
9
10
#include <idc.idc>
static main()
{
auto addr = 0x402000;
auto i = 0;
for(i = 0; i < 53; i++)
{
PatchByte(addr+i,Byte(addr+i)^0x54);
}
}

image-20221017224154988

分析之后发现第一个函数只是单纯的初始化一个key数组

image-20221017224238012

下断点动调后对着抄跑一边就行了

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
flag = [
161, 191, 182, 112, 99, 91, 59, 237, 244, 145,
129, 164, 189, 58, 83, 134, 91, 140, 219, 65,
27, 115, 225, 209, 242, 178, 223, 110, 22, 86,
34, 66, 252]

key = [
97, 7, 213, 138, 105, 120, 45, 86, 209, 124,
30, 14, 12, 15, 100, 48, 20, 197, 60, 176,
55, 65, 28, 23, 106, 181, 74, 185, 61, 77,
242, 183, 56, 184, 123, 159, 72, 127, 229, 210,
168, 238, 179, 47, 193, 90, 206, 11, 42, 148,
80, 202, 113, 114, 169, 225, 103, 222, 40, 118,
49, 9, 62, 226, 63, 167, 32, 254, 38, 66,
122, 217, 76, 214, 99, 35, 52, 195, 8, 146,
171, 24, 145, 59, 173, 26, 78, 165, 240, 131,
182, 5, 119, 199, 198, 142, 144, 93, 25, 109,
51, 27, 248, 69, 172, 154, 150, 166, 121, 192,
0, 2, 219, 83, 104, 107, 16, 111, 152, 223,
132, 10, 71, 64, 19, 243, 175, 18, 186, 139,
215, 203, 155, 246, 200, 156, 224, 1, 91, 227,
162, 6, 3, 218, 46, 117, 194, 116, 221, 251,
253, 234, 161, 129, 187, 101, 37, 68, 216, 36,
57, 191, 87, 13, 236, 112, 252, 189, 89, 75,
73, 134, 205, 231, 115, 160, 141, 29, 220, 94,
151, 135, 201, 204, 125, 126, 128, 22, 188, 211,
235, 244, 88, 81, 67, 249, 207, 190, 241, 102,
212, 247, 4, 95, 33, 237, 50, 174, 21, 39,
239, 44, 233, 54, 250, 92, 41, 147, 53, 149,
232, 163, 82, 110, 143, 180, 228, 157, 170, 98,
58, 164, 208, 79, 140, 70, 34, 178, 177, 137,
85, 158, 255, 17, 196, 43, 31, 230, 108, 133,
96, 245, 153, 136, 130, 84]

v4 = 0
v3 = 0
for i in range(0, 33):
v3 = (v3 + 1) % 256
v5 = key[v3]
v4 = (v5 + v4) % 256
key[v3] = key[v4]
key[v4] = v5
flag[i] ^= key[(v5 + key[v3]) % 256]
print(chr(flag[i]&0xff), end="")
1
flag{RC4_and_SMC_is_interesting!}

Petals Level Up

这道题的关键在于花指令

64位无壳

image-20221101212138136

很明显有花指令

image-20221101212217081

很明显,最后跳转的地址等于0x1755 + (0xcd ^ 0xc4) = 0x175e

然后将0x173a 到 0x175c这段给nop掉

类似的还有几个

最后应该是

image-20221101213002285

image-20221101213044304

写出脚本

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
import hashlib

len = 32
key = [0] * 256
for i in range(256):
key[i] = (~(i ^ len)) & 0xff


enc = [0xB3, 0x79, 0xF1, 0x70, 0xB3, 0x79, 0xF1, 0x70, 0xB3, 0x31,
0xC3, 0x6E, 0x24, 0xE3, 0x7C, 0xFF, 0xDA, 0xF9, 0x75, 0xF2,
0x60, 0xBF, 0x33, 0xE3, 0x65, 0xA6, 0x62, 0x2A, 0x65, 0x24,
0xB4, 0xBA]


for i in range(31, -1, -1):
enc[i] ^= enc[(i + 1) % len]
enc[i] ^= 0x7A
enc[i] = (enc[i] << 4 | enc[i] >> 4) & 0xff
enc[i] ^= 0x64
enc[i] = (enc[i] >> 5 | enc[i] << 3) & 0xff
enc[i] ^= 0x73
enc[i] = (enc[i] >> 6 | enc[i] << 2) & 0xff
enc[i] ^= 0x71
enc[i] = (enc[i] >> 7 | enc[i] << 1) & 0xff

flag = ""
for i in range(32):
enc[i] = key.index(enc[i])
flag += chr(enc[i] & 0xff)


a = hashlib.md5()
a.update((flag).encode(encoding='utf-8'))
print("flag{"+a.hexdigest() + "}")
1
flag{d5658c0b4c44d4672d76b563a8505a66}

babycode

.ll 文件是llvm下的字节码的文本形式

于是我们需要将其转换为可执行文件来进行分析

将字节码变为汇编后就能用clang编译

1
llvm-as task.ll
1
clang task.bc -o struct

然后拖进ida进行分析

image-20221104153648189

不难但是有几个点是要留意的

这里输入靠溢出分成了两节,先rc4加密前半节,然后将后16位和前16位异或后再用同一个s盒rc4加密,再整体base64

rc4是标准的,key = llvmbitc

base64坑有点多

image-20221104154113755

一个是他3转4是时候顺序不太一样,但是结尾的3转4顺序是正常的

码表则是以;开头的64位

写脚本

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
s = [0] * 256
t = [0] * 256


def rc_init():
key = [0x6c, 0x6c, 0x76, 0x6d, 0x62, 0x69, 0x74, 0x63]
for i in range(256):
s[i] = i
t[i] = key[i % 8]

v3 = 0
for i in range(256):
v3 = (t[i] + s[i] + v3) % 256
s[i], s[v3] = s[v3], s[i]


def rc_decode(enc):
elen = len(enc)
v4 = 0
v5 = 0
for i in range(elen):
v5 = (v5 + 1) % 256
v4 = (s[v5] + v4) % 256
s[v5], s[v4] = s[v4], s[v5]
enc[i] ^= s[(s[v4] + s[v5]) % 256] ^ 0x59


flag = []
enc = "TSz`kWKgbMHszXaj`@kLBmRrnTxsNtZsSOtZzqYikCw"
x = len(enc)
keyboard = ";<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz"
v4 = 0
for i in range(10):
x1 = keyboard.index(enc[i * 4])
x2 = keyboard.index(enc[i * 4 + 2])
x3 = keyboard.index(enc[i * 4 + 1])
x4 = keyboard.index(enc[i * 4 + 3])
flag.append((x1 << 2) & 0xff | ((x2 >> 4) & 0x3))
flag.append(((x2 & 0xf) << 4) | (x3 >> 2) & 0xf)
flag.append(((x3 & 0x3) << 6) | x4)

x1 = keyboard.index('k')
x2 = keyboard.index('C')
x3 = keyboard.index('w')

flag.append((x1 << 2) & 0xff | (x2 >> 4) & 0x3)
flag.append(((x2 & 0xf) << 4) | (x3 >> 2) & 0xf)

print(flag)
f1 = flag[0:16]
f2 = flag[16:32]

rc_init()
rc_decode(f1)
rc_decode(f2)
print(f1)
print(f2)
for i in range(16):
f2[i] ^= flag[i]

for i in f1:
print(chr(i & 0xff), end="")
for i in f2:
print(chr(i & 0xff), end="")
1
flag{Hacking_for_fun@reverser$!}