---
# System prepended metadata

title: Simple Crypto - 0x08(2023 Lab - dlog)
tags: [Crypto, eductf, CTF]

---

# Simple Crypto - 0x08(2023 Lab - dlog)
## Background
[ [edu-ctf 2023] week03 - crypto2 ](https://www.youtube.com/live/u4ZVc8PuJC0?si=2wbiGreg_BZQ-dff)
[Cryptography and Network Security – Homework 2 - Little Knowledge Proof](https://hackmd.io/@SBK6401/SJobiaxQ3#5-Little-Knowledge-Proof)
## Source code
:::spoiler Source Code
```python
from Crypto.Util.number import isPrime, bytes_to_long
import os

from secret import FLAG

p = int(input("give me a prime: ").strip())
if not isPrime(p):
    print("Do you know what is primes?")
    exit(0)

if p.bit_length() != 1024:
    print("Bit length need to be 1024")
    exit(0)

g = int(input("give me a number: ").strip())
flag = bytes_to_long(FLAG)

print('The hint about my secret:', pow(g, flag, p))

```
:::
## Recon
基本上這一題和上一個學期上的CNS中，作業二的[Little Knowledge Proof](https://hackmd.io/@SBK6401/SJobiaxQ3#5-Little-Knowledge-Proof)概念一模一樣，當時還不知道這是啥騷操作，現在覺得非常簡單，就是套用了Pohlig-Hellman的原理進行破解

1. 首先看source code需要我們提供一個prime($N$)，然後跟一個不重要的底數$g$，接著題目return一個hint就是$hint=g^{flag}\ mod(N)$，因此按照discrete log的難度，我們很難針對hint進行brute force，縱使我們知道N,g,hint也一樣，但因為N是我們提供的，所以我可以故意給他一個smooth prime，也就是$N-1$是由多個prime相乘而得
2. 我們可以用上課教過的Pohlig-Hellman原理去思考，也就是先把群的範圍縮小，再利用BSGS的方法找到$x_i$，這時雖然得到$x_i$但由於是mod $p_i$的結果，就不是真正的$x$，要利用CRT把多個$x_i$還原成原本的$x$，幸虧以上操作sage都做好了

## Exploit
記得要進入conda中sage的環境，如果沒有的話可以直接創一個: `conda create --name sageenv sage=10.0 -c conda-forge -y`，然後可以直接`python exp.py`也可以直接`sage exp.py`，但重點是`from sage.all import *`是一定要加的，如果要像之前CNS那樣使用Pohlig-Hellman的函數，就一定要另外分開寫一個專門的script，因為他沒辦法相容pwntools的remote method，但可以相容local process，真的有點奇怪。另外sage也沒辦法接受`log.info(f"...")`的語法，所以全部都要換成`print`
```python
from pwn import *
from Crypto.Util.number import *
from sage.all import *

smooth_prime = 2
while True:
    bitLen = smooth_prime.bit_length()
    if bitLen > 1024:
        smooth_prime = 2
    if bitLen == 1024:
        if isPrime(smooth_prime + 1):
            print(smooth_prime+1)
            smooth_prime = smooth_prime + 1
            break
    smooth_prime *= getPrime(10)

r = remote("10.113.184.121", 10032)
# r = process(["python", "dlog_bfc156b3a0eec196.py"])

g = 2
r.recvuntil(b": ")
r.sendline(str(smooth_prime).encode())
r.recvuntil(b'give me a number: ')
r.sendline(str(g).encode())
r.recvuntil(b'The hint about my secret: ')
hint = r.recvline()

print(f'Smooth Prime is: {smooth_prime}')
print("g = 2")
print(f'hint = {hint.decode().strip()}')

flag = discrete_log(Mod(hint, smooth_prime), Mod(g, smooth_prime))
print(f"Flag = {long_to_bytes(flag).decode()}")

r.close()
```