Challenge:

#!/usr/bin/python3
from Crypto.Util.number import getPrime, long_to_bytes
from secret import flag
from secrets import randbelow

p = getPrime(1024)
r = randbelow(p)
print(f'{r} mod {p}')
n = int(input())
if n%p != r:
    print('no')
    exit()
print(eval(long_to_bytes(n)))


Solve:

My idea is send flag# ...<random bytes> (except null ‘\x00’)

M * 256**j + x ≡ r (mod p)

Choose j precisely so that we have exactly 128 bytes (size of p), rearrange for x, and hope that x has no null bytes.

If it does, then rety until it doesn’t.


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

M = bytes_to_long(b'flag#')

def main():
    io = remote('155.248.210.243', 42114)
    recv = io.recvline().split()
    r = int(recv[0])
    p = int(recv[2])

    j = 1024//8
    x = (r - M * 256**j) % p
    n = M * 256**j + x

    io.sendline(str(n).encode())
    print(io.recv())

    io.close()

while True:
    main()

# ictf{p1Ck3d_y0Ur_W@y_pa$7_th3_P1cKy_m0du1u5}



modjail2

Challenge:

#!/usr/bin/python3
from Crypto.Util.number import getPrime, long_to_bytes
from secret import flag
from secrets import randbelow
from time import sleep

p = getPrime(256)
r = randbelow(p)
print(f'{r} mod {p}')
n = int(input())
if n%p != r:
    print('no')
    exit()

m = long_to_bytes(n).decode()
strikes = 0 # 3 and you're out!
for c in m:
    sleep(0.01)
    if not (ord('a') <= ord(c) <= ord('z')):
        strikes += 1
        print(f'strike {strikes}{"!"*strikes}')
        if strikes >= 3: exit()

print(eval(m))



Solve:

For a valid message, we can send this for some x in range 1 to 127:

    n = bytes_to_long(b'flag#' + <... any junk in a to z...> + bytes([x]))

We should actually use LLL to find valid lsb in a to z!


from os import environ
environ['TERM'] = 'konsole'
from pwn import remote
from Crypto.Util.number import *
load('https://gist.githubusercontent.com/Connor-McCartney/952583ecac836f843f50b785c7cb283d/raw/5718ebd8c9b4f9a549746094877a97e7796752eb/solvelinmod.py')

def main():
    io = remote('155.248.210.243', '42115')
    recv = io.recvline().split()
    r = int(recv[0])
    p = int(recv[2])

    N = 150 # somewhat arbitrary
    xs = [var(f'x{i}') for i in range(N)]
    eq = bytes_to_long(b'flag#') * 256**N + sum(x*256**i for i, x in enumerate(xs)) == r
    bounds = {x: (ord('a'), ord('z')) for x in xs}
    sol = solve_linear_mod([(eq, p)], bounds)
    if sol is None:
        print('no solution, retry')
        io.close()
        return
    else:
        sol = list(sol.values())
        print(f'{all([ord('a')<=i<=ord('z') for i in sol]) = }')
        n = b'flag#' + bytes(sol[::-1])
        print(n)
    

    io.sendline(str(bytes_to_long(n)).encode())
    print(io.recv().decode())

    io.close()

while True:
    main()

# ictf{a_c@R3fU1lY_Cr4fT3d_PayL04d!}



modjail3

Challenge:

#!/usr/bin/python3
from Crypto.Util.number import getPrime, long_to_bytes, bytes_to_long
from secret import flag

def wild(num):
    return bytes_to_long(repr(num).encode())

p = getPrime(64)
print(p)
n = int(input())
if n%p != wild(n)%p:
    print('no')
    exit()
print(eval(long_to_bytes(n)))


Solve:

We kinda need n%p = bytes_to_long(str(n).encode()) % p


def wild(num):
    return bytes_to_long(repr(num).encode())

def my_wild(num):
    return sum([c*256**i for i,c in enumerate(str(num).encode()[::-1])])

n = 12345
assert wild(n) == my_wild(n)


n = b'12345'
print([x-48 for x in n])
print(sum([(x-48)*10**i for i, x in enumerate(n[::-1])]))


from Crypto.Util.number import getPrime, long_to_bytes, bytes_to_long

def wild(num):
    return bytes_to_long(repr(num).encode())

p = getPrime(64)
nbytes = b'flag#abcde'
n = bytes_to_long(nbytes)

LHS = n%p 
RHS = wild(n)%p


def bytes_to_int(x):
    return sum([c*256**i for i,c in enumerate(x[::-1])])

def repr_to_int(x):
    return sum([(c-48)*10**i for i,c in enumerate(x[::-1])])

nrepr = str(n).encode()
assert n == repr_to_int(nrepr)

xs = [ord(i) for i in 'abcde']
nbytes = [ord(i) for i in 'flag#'] + xs

lhs = bytes_to_int(nbytes)
rhs = bytes_to_int(nrepr)
assert LHS == lhs % p
assert RHS == rhs % p


But the problem is from going from bytes/repr to int, you need some modulus operation which is annoying


ys = [int(i) for i in str(n)]
print(n%p)
print(sum([c*10**i for i,c in enumerate(ys[::-1])]) % p)
print(sum([(c+48)*256**i for i,c in enumerate(ys[::-1])]) % p)
print(sum([(c)*256**i for i,c in enumerate(nbytes[::-1])]) % p)


If you just want to solve for any n:

load('https://gist.githubusercontent.com/Connor-McCartney/952583ecac836f843f50b785c7cb283d/raw/5718ebd8c9b4f9a549746094877a97e7796752eb/solvelinmod.py')
from Crypto.Util.number import * 

def check(num):
    return bytes_to_long(repr(num).encode()) % p == num % p

p = getPrime(64)

LEN = 30
ys = [var(f'y{i}') for i in range(LEN)]
bounds = {y: (0, 10) for y in ys}
lhs = sum([c*10**i for i,c in enumerate(ys[::-1])])
rhs = sum([(c+48)*256**i for i,c in enumerate(ys[::-1])])
sol = solve_linear_mod([(lhs==rhs, p)], bounds)
print(sol)
ys = list(sol.values())
n = int(''.join([str(i) for i in ys]))
print(f'found {n = }')
print(f'{check(n) = }')


Now my idea is to tweak the MSB of n so that we get ‘flag#’


Local testing worked

load('https://gist.githubusercontent.com/Connor-McCartney/952583ecac836f843f50b785c7cb283d/raw/5718ebd8c9b4f9a549746094877a97e7796752eb/solvelinmod.py')
from Crypto.Util.number import * 

def check(num):
    return bytes_to_long(repr(num).encode()) % p == num % p

p = getPrime(64)


LEN = 50
ys = [var(f'y{i}') for i in range(LEN)]
bounds = {y: (0, 10) for y in ys}
lhs = sum([c*10**i for i,c in enumerate(ys[::-1])])
rhs = sum([(c+48)*256**i for i,c in enumerate(ys[::-1])])
sol = solve_linear_mod([(lhs==rhs, p)], bounds)
ys = list(sol.values())
n = int(''.join([str(i) for i in ys]))
#print(f'found {n = }')
#print(f'{check(n) = }')


# messy way to get some prefix
l = len(long_to_bytes(n))
n_ = bytes_to_long(b'flag#' + b'\xff'*(l - 5))
ns_ = str(n_)
l = len(ns_)
i = l
while True:
    ns_ = ns_[:i] + '0'*(l-i)
    n_ = int(ns_)
    i -= 1
    if b'flag#' not in long_to_bytes(n_):
        break
    ns__ = ns_
    n__ = n_
print(ns__)
print(long_to_bytes(n__))
pre = [int(i) for i in ns__.split('00000')[0]] + [0]*10 # some arbitrary extra 0's
print(f'{pre = }')
print()



# now try resolve with pre
ys = [var(f'y{i}') for i in range(1 + LEN - len(pre))] # strange i have to add 1...
bounds = {y: (0, 10) for y in ys}
ys = pre + ys
lhs = sum([c*10**i for i,c in enumerate(ys[::-1])])
rhs = sum([(c+48)*256**i for i,c in enumerate(ys[::-1])])
sol = solve_linear_mod([(lhs==rhs, p)], bounds)
ys = pre + list(sol.values())
n = int(''.join([str(i) for i in ys]))
print(f'found {n = }')
print(f'{check(n) = }')
print(f'{long_to_bytes(n) = }')


and remote flag:

from os import environ
environ['TERM'] = 'konsole'
from pwn import remote
load('https://gist.githubusercontent.com/Connor-McCartney/952583ecac836f843f50b785c7cb283d/raw/5718ebd8c9b4f9a549746094877a97e7796752eb/solvelinmod.py')
from Crypto.Util.number import * 

def check(num):
    return bytes_to_long(repr(num).encode()) % p == num % p

io = remote('155.248.210.243', 42111)
p = int(io.recvline())

LEN = 50
ys = [var(f'y{i}') for i in range(LEN)]
bounds = {y: (0, 10) for y in ys}
lhs = sum([c*10**i for i,c in enumerate(ys[::-1])])
rhs = sum([(c+48)*256**i for i,c in enumerate(ys[::-1])])
sol = solve_linear_mod([(lhs==rhs, p)], bounds)
ys = list(sol.values())
n = int(''.join([str(i) for i in ys]))

# messy way to get some prefix
l = len(long_to_bytes(n))
n_ = bytes_to_long(b'flag#' + b'\xff'*(l - 5))
ns_ = str(n_)
l = len(ns_)
i = l
while True:
    ns_ = ns_[:i] + '0'*(l-i)
    n_ = int(ns_)
    i -= 1
    if b'flag#' not in long_to_bytes(n_):
        break
    ns__ = ns_
    n__ = n_
pre = [int(i) for i in ns__.split('00000')[0]] + [0]*10 # some arbitrary extra 0's

# now try resolve with pre
ys = [var(f'y{i}') for i in range(1 + LEN - len(pre))] # strange i have to add 1...
bounds = {y: (0, 10) for y in ys}
ys = pre + ys
lhs = sum([c*10**i for i,c in enumerate(ys[::-1])])
rhs = sum([(c+48)*256**i for i,c in enumerate(ys[::-1])])
sol = solve_linear_mod([(lhs==rhs, p)], bounds)
ys = pre + list(sol.values())
n = int(''.join([str(i) for i in ys]))
print(f'found {n = }')
print(f'{check(n) = }')
print(f'{long_to_bytes(n) = }')


io.sendline(str(n).encode())
print(io.recv())
# ictf{tH3_B1t$iz3_of_T#e_bi7S1Ze_0F_7hE_Pr1m3_15_d3cRE@s!n6_L1ne4RLy...}