본문 바로가기

리버싱!

UIUCTF 2025-풀이

import math

def fast_mod_pow(base, exp, mod):
    result = 1
    base = base % mod
    while exp > 0:
        if exp & 1:
            result = (result * base) % mod
        base = (base * base) % mod
        exp >>= 1
    return result

def mod_inverse_fermat(a, p):
    return fast_mod_pow(a, p - 2, p)

def baby_step_giant_step_fixed(base, target, mod):
    if base == 0:
        return 0 if target == 0 else None
    if target == 1:
        return 0
    
    n = mod - 1
    m = int(math.ceil(math.sqrt(n)))
    
    print(f"      Baby-step Giant-step: n={n}, m={m}")
    
    baby_table = {}
    gamma = 1  # base^0
    
    for j in range(m):
        if gamma == target:
            print(f"      Baby step에서 즉시 발견: j={j}")
            return j
        baby_table[gamma] = j
        gamma = (gamma * base) % mod
        
        if j % 50000 == 0 and j > 0:
            print(f"        Baby step 진행: {j}/{m}")
    
    print(f"      Baby steps 완료: {len(baby_table)}개 저장")
    
    # Giant steps
    # base^(-m) 계산
    base_inv = mod_inverse_fermat(base, mod)
    base_inv_m = fast_mod_pow(base_inv, m, mod)
    
    print(f"      base^(-m) = {base_inv_m}")
    
    y = target
    for i in range(m):
        if y in baby_table:
            x = i * m + baby_table[y]
            print(f"      Giant step에서 발견: i={i}, j={baby_table[y]}, x={x}")
            
            # 검증
            if fast_mod_pow(base, x, mod) == target:
                return x
            else:
                print(f"        검증 실패!")
        
        y = (y * base_inv_m) % mod
        
        if i % 10000 == 0 and i > 0:
            print(f"        Giant step 진행: {i}/{m}")
    
    print("      Baby-step Giant-step 실패")
    return None

def simple_brute_force(base, target, mod, max_limit=1000000):
    print(f"      단순 브루트포스 (최대 {max_limit})")
    
    for x in range(max_limit):
        if fast_mod_pow(base, x, mod) == target:
            print(f"      브루트포스 성공: x={x}")
            return x
        
        if x % 100000 == 0 and x > 0:
            print(f"        브루트포스 진행: {x}")
    
    print(f"      브루트포스 실패 (범위: 0-{max_limit})")
    return None

def solve_discrete_log_improved(base, target, mod):

    print(f"    해결 중: {base}^x ≡ {target} (mod {mod})")
    if target == 1:
        return 0
    if base == target:
        return 1

    print(f"    방법 1: 작은 범위 브루트포스")
    result = simple_brute_force(base, target, mod, 100000)
    if result is not None:
        return result

    print(f"    방법 2: Baby-step Giant-step")
    result = baby_step_giant_step_fixed(base, target, mod)
    if result is not None:
        return result

    print(f"    방법 3: 확장 브루트포스")
    result = simple_brute_force(base, target, mod, 5000000)
    if result is not None:
        return result
    
    return None

def solve_using_improved_algorithms():
    """개선된 알고리즘으로 해결"""
    test_pt = [577090037, 2444712010, 3639700191, 3445702192, 
               3280387012, 271041745, 1095513148, 506456969]
    test_ct = [3695492958, 1526668524, 3790189762, 20093842, 
               2409408810, 239453620, 1615481745, 1887562585]
    flag_enc = [605589777, 4254394693, 463430822, 2146232739, 
                4230614750, 1466883317, 31739036, 1703606160]
    mod = 0xFFFFFF2F
    
    print("=== 개선된 이산 로그 해결 ===")
    print(f"모듈러스: {mod} (0x{mod:x})")
    print()
    
    found_inputs = []
    
    for i in range(8):
        print(f"인덱스 {i} 해결 중...")
        
        x = solve_discrete_log_improved(test_pt[i], test_ct[i], mod)
        
        if x is not None:
            found_inputs.append(x)
            print(f"  SUCCESS: x = {x}")
            
            # 즉시 검증
            verify = fast_mod_pow(test_pt[i], x, mod)
            if verify == test_ct[i]:
                print(f"  검증 성공: {test_pt[i]}^{x} ≡ {test_ct[i]} (mod {mod})")
            else:
                print(f"  검증 실패: {verify} ≠ {test_ct[i]}")
                found_inputs[-1] = -1
        else:
            found_inputs.append(-1)
            print(f"  FAILED: 해를 찾지 못함")
        
        print()
    
    print("=== 결과 ===")
    print("찾은 입력값들:", found_inputs)

    success_count = sum(1 for x in found_inputs if x != -1)
    print(f"성공한 인덱스: {success_count}/8")
    
    if success_count > 0:
        print("\n=== 플래그 생성 (성공한 것들만) ===")
        for i in range(8):
            if found_inputs[i] != -1:
                flag_val = fast_mod_pow(flag_enc[i], found_inputs[i], mod)
                if 32 <= flag_val <= 126:
                    print(f"인덱스 {i}: '{chr(flag_val)}' (ASCII: {flag_val})")
                else:
                    print(f"인덱스 {i}: {flag_val} (비출력 문자)")
    
    return found_inputs

def test_algorithm():
    """알고리즘 정확성 테스트"""
    print("=== 알고리즘 테스트 ===")
    test_mod = 1009  # 작은 소수
    test_base = 2
    test_exp = 123
    test_target = fast_mod_pow(test_base, test_exp, test_mod)
    
    print(f"테스트: {test_base}^{test_exp} ≡ {test_target} (mod {test_mod})")
    
    result = solve_discrete_log_improved(test_base, test_target, test_mod)
    
    if result == test_exp:
        print(f"테스트 성공: 찾은 값 = {result}")
        return True
    else:
        print(f"테스트 실패: 찾은 값 = {result}, 기대값 = {test_exp}")
        return False

if __name__ == "__main__":
    if test_algorithm():
        print("\n알고리즘 테스트 통과, 실제 문제 해결 시작...\n")
        solve_using_improved_algorithms()
    else:
        print("\n알고리즘 테스트 실패, 구현을 재검토해야 함")

 

Baby steps: 65,536개 값 저장 (base^j for j=0~65535)

Giant steps: target × (base^(-m))^i 계산하며 매칭 찾기를 GPT를 통해 구현

Baby step Giant step 알고리즘 이후 뽑힌

 

[2127877499, 1930549411, 2028277857, 2798570523, 901749037, 1674216077, 3273968005, 3294916953]

정수값을 보기좋게 HEX로 변환후 1바이트씩 문자로 변환하면 플래그

 

sigpwny{CrackingDiscreteLogs4TheFun/Lols}

'리버싱!' 카테고리의 다른 글

CCE 준비  (2) 2025.08.08
justCTF2025  (0) 2025.08.03
DownUnderCTF2025-풀이  (3) 2025.07.21
cyberarena  (0) 2025.07.06
juniorcrypt2025-올만에 reversing 풀이  (0) 2025.07.03