maplectf 2023
This commit is contained in:
parent
d98befe85a
commit
c797501c70
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,38 @@
|
||||||
|
# mapleCTF 2023
|
||||||
|
|
||||||
|
what IS UP chat we're back at it again with another writeup post
|
||||||
|
|
||||||
|
last weekend i played [MapleCTF 2023](https://ctf2023.maplebacon.org) with my team
|
||||||
|
[BLÅHAJ](https://blahaj.awoo.systems) (raised from the dead, i don't remember when the last time i
|
||||||
|
played as/with BLÅHAJ was but it's been like. a hot second)
|
||||||
|
|
||||||
|
there were a couple of interesting challenges in this CTF. BLÅHAJ ended up placing 5th, with a team
|
||||||
|
of like just a handful of people, which i thought was actually pretty impressive
|
||||||
|
|
||||||
|
the challenges we solved that were valued the most points at the end of the CTF were
|
||||||
|
|
||||||
|
- flakey ci (misc, 489 points). this was surprising! flakey ci was literally trivial, so i'm
|
||||||
|
surprised more people didn't solve it. maybe they were scared of nix. perhaps i had an unfair
|
||||||
|
advantage being a nix user.....
|
||||||
|
- merkle (crypto, 472 points). also surprising! i'm not sure i would classify merkle as a crypto
|
||||||
|
challenge, it was more just implementing state recovery of internal data structures using
|
||||||
|
probabalistic output. it was not the most time consuming ever to solve, by far
|
||||||
|
- lost-in-space (pwn, 456 points). still surprising,,, like this was a fairly straightforward
|
||||||
|
challenge that required you to implement a graph search algorithm in shellcode with a limited
|
||||||
|
amount of program memory/stack. it was interesting, but it wasn't *hard* imo
|
||||||
|
- AaaS (misc, 436 points). i wasn't involved in solving this one, but it was basically just python
|
||||||
|
trivia. a writeup on this wouldn't be very involved
|
||||||
|
- **coinflip** (misc, 425 points). this one was actually really interesting imo. the discussion on
|
||||||
|
this challenge goes into some depth
|
||||||
|
|
||||||
|
so basically here's a writeup on coinflip. the writeup is structured in a way to guide you through
|
||||||
|
the background information required to develop a solution and the thought process involved, so if
|
||||||
|
you don't rly care about that you can skip to the end with the actual solution script
|
||||||
|
|
||||||
|
enjoy~
|
||||||
|
|
||||||
|
<!--
|
||||||
|
writeup index:
|
||||||
|
|
||||||
|
- [misc: coinflip](#manipulating-python-rng-using-the-seed-coinflip)
|
||||||
|
-->
|
|
@ -0,0 +1,452 @@
|
||||||
|
## manipulating python RNG using the seed: `coinflip`
|
||||||
|
|
||||||
|
>Your fate lies in a coin flip. Will you take control of your destiny?
|
||||||
|
>
|
||||||
|
>Author: nneonneo
|
||||||
|
>
|
||||||
|
>`nc coinflip.ctf.maplebacon.org 1337`
|
||||||
|
|
||||||
|
Files:
|
||||||
|
[server.py](https://git.lain.faith/haskal/writeups/raw/branch/main/2023/maple/coinflip/server.py)
|
||||||
|
|
||||||
|
|
||||||
|
### summary
|
||||||
|
|
||||||
|
python `Random` is used to generate random coin flips as `1` or `0` bits, where if you get `1` then
|
||||||
|
you lose money, and if you get `0` you win money. user input directly seeds the RNG, which can be
|
||||||
|
constructed in a way that forces most of the coin flips to go in the `0` direction. using this
|
||||||
|
computed seed, we can trick the server into giving us lots of money and winning the game
|
||||||
|
|
||||||
|
### challenge source
|
||||||
|
|
||||||
|
we are given the source code, in python for the challenge. it's not very long, so reviewing it is
|
||||||
|
straightforward
|
||||||
|
|
||||||
|
|
||||||
|
#### the `Coin` class
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Coin:
|
||||||
|
def __init__(self, coin_id):
|
||||||
|
self.random = Random(coin_id)
|
||||||
|
self.flips_left = 0
|
||||||
|
self.buffer = None
|
||||||
|
|
||||||
|
def flip(self):
|
||||||
|
if self.flips_left == 0:
|
||||||
|
self.buffer = self.random.getrandbits(32)
|
||||||
|
self.flips_left = 32
|
||||||
|
res = self.buffer & 1
|
||||||
|
self.buffer >>= 1
|
||||||
|
self.flips_left -= 1
|
||||||
|
return res
|
||||||
|
```
|
||||||
|
|
||||||
|
this is an implementation of random coin flips, which uses python's builtin `Random` class with a
|
||||||
|
given seed `coin_id`. every time a coin flip is needed, it is taken as the next bit of 32-bit output
|
||||||
|
from the `Random` instance, and when all bits are used a new 32-bit value is requested from `Random`
|
||||||
|
|
||||||
|
this is an interesting implementation because you might expect something more typical like
|
||||||
|
`random.randint(0, 1)` or `random.choice([True, False])` which might be more idiomatic
|
||||||
|
|
||||||
|
#### the "main function"
|
||||||
|
|
||||||
|
```python
|
||||||
|
if __name__ == "__main__":
|
||||||
|
signal.alarm(60)
|
||||||
|
print("Welcome to Maple Betting!")
|
||||||
|
print("We'll be betting on the outcome of a fair coin flip.")
|
||||||
|
print("You'll start with $1 - try to make lots of money and you'll get flags!")
|
||||||
|
|
||||||
|
game_id = input("Which coin would you like to use? ")
|
||||||
|
num_rounds = input("How many rounds do you want to go for? ")
|
||||||
|
num_rounds = int(num_rounds)
|
||||||
|
if num_rounds > 20_000_000:
|
||||||
|
print("Can't play that long, I'm afraid.")
|
||||||
|
exit(1)
|
||||||
|
```
|
||||||
|
|
||||||
|
there is a time limit of 60 seconds to interact with the server, and we are asked for a "game id"
|
||||||
|
and a number of rounds to play. this is the only user input to the program
|
||||||
|
|
||||||
|
```python
|
||||||
|
print("Alright, let's go!")
|
||||||
|
coin = Coin(int(game_id, 0))
|
||||||
|
money = 1
|
||||||
|
for nr in range(num_rounds):
|
||||||
|
money += [1, -1][coin.flip()]
|
||||||
|
if money <= 0:
|
||||||
|
print(f"Oops, you went broke at round {nr+1}!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
the "game id" is used to construct `Coin` (and becomes the seed for the RNG). then, the server plays
|
||||||
|
the rounds you requested. on each round, a `1` or `0` bit is generated, and if the result is `0`,
|
||||||
|
you win `$1`, and if the result is `1` then you lose `$1`
|
||||||
|
|
||||||
|
```python
|
||||||
|
print(f"You finished with ${money} in the pot.")
|
||||||
|
if money < 18_000:
|
||||||
|
print("At least you didn't go broke!")
|
||||||
|
elif money < 7_000_000:
|
||||||
|
print(f"Pretty good!")
|
||||||
|
else:
|
||||||
|
print(f"What the hell?! You bankrupted the casino! Take your spoils: {FLAG}")
|
||||||
|
```
|
||||||
|
|
||||||
|
so in order to win the game and get the flag, we need to make an amount of money over `$7000000`
|
||||||
|
|
||||||
|
|
||||||
|
### naive approach
|
||||||
|
|
||||||
|
since we can control the seed, one approach is to try seed values until one wins the necessary
|
||||||
|
amount of games
|
||||||
|
|
||||||
|
something like this
|
||||||
|
|
||||||
|
```python
|
||||||
|
seed = 0
|
||||||
|
best_seed = 0
|
||||||
|
best_money = 0
|
||||||
|
while True:
|
||||||
|
coin = Coin(seed)
|
||||||
|
money = 0
|
||||||
|
for _ in range(20_000_000):
|
||||||
|
money += [1, -1][coin.flip()]
|
||||||
|
if money > best_money:
|
||||||
|
best_money = money
|
||||||
|
best_seed = seed
|
||||||
|
|
||||||
|
if money <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
seed += 1
|
||||||
|
```
|
||||||
|
|
||||||
|
running this for a while might get you money up to like, `$15000` or so depending on how long you run
|
||||||
|
it, but ultimately it's nowhere near the needed `$7000000` and the improvements rapidly diminish with
|
||||||
|
further running time. clearly this approach is not going to work
|
||||||
|
|
||||||
|
### background: python RNG (Mersenne twister)
|
||||||
|
|
||||||
|
to find out how we can manipulate the python RNG, let's take a closer look at the implementation
|
||||||
|
|
||||||
|
the RNG in python is a [Mersenne Twister](https://en.wikipedia.org/wiki/Mersenne_Twister). a quick
|
||||||
|
summary of how the Mersenne twister works
|
||||||
|
|
||||||
|
- a state array `MT` of 32-bit integers is initialized using a given seed value
|
||||||
|
- index `index` set to `n`
|
||||||
|
- to generate a value, pick the next `MT[index]` and increment `index`. additionally the output
|
||||||
|
value is "tempered" with some bitwise operations
|
||||||
|
- if `index >= n`, run the `twist` operation (notice `twist` is also run the first time a random
|
||||||
|
value is generated)
|
||||||
|
- `twist` scrambles `MT` using some more bitwise operations
|
||||||
|
|
||||||
|
we can find the full implementation of the Mersenne twister in CPython in
|
||||||
|
[Modules/_randommodule.c](https://github.com/python/cpython/blob/main/Modules/_randommodule.c)
|
||||||
|
|
||||||
|
here's the implementation of generating a 32 bit number, if you do some tracing through calls in
|
||||||
|
CPython, you can find that this is the underlying C function that gets called by the
|
||||||
|
`getrandbits(32)` call of `Coin.flip`. i've added comments to explain the main parts of the function
|
||||||
|
|
||||||
|
```c
|
||||||
|
static uint32_t
|
||||||
|
genrand_uint32(RandomObject *self)
|
||||||
|
{
|
||||||
|
uint32_t y;
|
||||||
|
static const uint32_t mag01[2] = {0x0U, MATRIX_A};
|
||||||
|
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||||
|
uint32_t *mt;
|
||||||
|
|
||||||
|
mt = self->state;
|
||||||
|
|
||||||
|
// XXX: the contents of this block are the "twist" operation
|
||||||
|
|
||||||
|
if (self->index >= N) { /* generate N words at one time */
|
||||||
|
int kk;
|
||||||
|
|
||||||
|
for (kk=0;kk<N-M;kk++) {
|
||||||
|
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||||
|
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U];
|
||||||
|
}
|
||||||
|
for (;kk<N-1;kk++) {
|
||||||
|
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
|
||||||
|
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U];
|
||||||
|
}
|
||||||
|
y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
|
||||||
|
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U];
|
||||||
|
|
||||||
|
self->index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: the following extracts the MT array value and applies the "temper" operation
|
||||||
|
|
||||||
|
y = mt[self->index++];
|
||||||
|
y ^= (y >> 11);
|
||||||
|
y ^= (y << 7) & 0x9d2c5680U;
|
||||||
|
y ^= (y << 15) & 0xefc60000U;
|
||||||
|
y ^= (y >> 18);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
to recap, in order to win the coinflip game, we need a lot of coin flips to be a `0` bit; which
|
||||||
|
means we need a lot of the output values to have mostly `0` bits in them
|
||||||
|
|
||||||
|
looking at the "temper" operation above, we can see that if the value `y` is `0x00000000` before
|
||||||
|
tempering, it will still be `0x00000000` after tempering. this means that we need the state array
|
||||||
|
elements themselves to be `0x00000000` to get what we want
|
||||||
|
|
||||||
|
additionally, during the "twist" operation we also find that having `MT` values of mostly
|
||||||
|
`0x00000000` results in "twist" producing an output `MT` which still contains mostly `0x00000000`
|
||||||
|
|
||||||
|
it's starting to look pretty convenient that `0` is the bit needed to win money!
|
||||||
|
|
||||||
|
### `init_by_array`: how to get known values into `MT`
|
||||||
|
|
||||||
|
the last step of background information is to understand how python generates the `MT` array using a
|
||||||
|
given seed
|
||||||
|
|
||||||
|
this is the C function that seeds the RNG using a given Python argument
|
||||||
|
|
||||||
|
```c
|
||||||
|
static int
|
||||||
|
random_seed(RandomObject *self, PyObject *arg)
|
||||||
|
{
|
||||||
|
int result = -1; /* guilty until proved innocent */
|
||||||
|
PyObject *n = NULL;
|
||||||
|
uint32_t *key = NULL;
|
||||||
|
size_t bits, keyused;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (arg == NULL || arg == Py_None) {
|
||||||
|
// ... seed from /dev/urandom ...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
n = /* coerce argument into PyLong */;
|
||||||
|
// ...
|
||||||
|
|
||||||
|
/* Now split n into 32-bit chunks, from the right. */
|
||||||
|
bits = _PyLong_NumBits(n);
|
||||||
|
if (bits == (size_t)-1 && PyErr_Occurred())
|
||||||
|
goto Done;
|
||||||
|
|
||||||
|
/* Figure out how many 32-bit chunks this gives us. */
|
||||||
|
keyused = bits == 0 ? 1 : (bits - 1) / 32 + 1;
|
||||||
|
|
||||||
|
/* Convert seed to byte sequence. */
|
||||||
|
key = (uint32_t *)PyMem_Malloc((size_t)4 * keyused);
|
||||||
|
if (key == NULL) {
|
||||||
|
PyErr_NoMemory();
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
res = _PyLong_AsByteArray((PyLongObject *)n,
|
||||||
|
(unsigned char *)key, keyused * 4,
|
||||||
|
PY_LITTLE_ENDIAN,
|
||||||
|
0); /* unsigned */
|
||||||
|
if (res == -1) {
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
/* XXX: call init_by_array using uint32_t[] from the PyLong value */
|
||||||
|
init_by_array(self, key, keyused);
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
to summarize, the way seeding works is
|
||||||
|
|
||||||
|
- given a `PyLong` value (ie, any integer in python), an array of `uint32_t` is produced consisting
|
||||||
|
of 32-bit chunks of the given value
|
||||||
|
- `init_by_array` is called with the given array
|
||||||
|
|
||||||
|
next, let's look at `init_by_array` and its helper function `init_genrand`
|
||||||
|
|
||||||
|
```c
|
||||||
|
/* initializes mt[N] with a seed */
|
||||||
|
static void
|
||||||
|
init_genrand(RandomObject *self, uint32_t s)
|
||||||
|
{
|
||||||
|
int mti;
|
||||||
|
uint32_t *mt;
|
||||||
|
|
||||||
|
mt = self->state;
|
||||||
|
mt[0]= s;
|
||||||
|
for (mti=1; mti<N; mti++) {
|
||||||
|
mt[mti] =
|
||||||
|
(1812433253U * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
|
||||||
|
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||||
|
/* In the previous versions, MSBs of the seed affect */
|
||||||
|
/* only MSBs of the array mt[]. */
|
||||||
|
/* 2002/01/09 modified by Makoto Matsumoto */
|
||||||
|
}
|
||||||
|
self->index = mti;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize by an array with array-length */
|
||||||
|
/* init_key is the array for initializing keys */
|
||||||
|
/* key_length is its length */
|
||||||
|
static void
|
||||||
|
init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length)
|
||||||
|
{
|
||||||
|
size_t i, j, k; /* was signed in the original code. RDH 12/16/2002 */
|
||||||
|
uint32_t *mt;
|
||||||
|
|
||||||
|
mt = self->state;
|
||||||
|
init_genrand(self, 19650218U);
|
||||||
|
i=1; j=0;
|
||||||
|
k = (N>key_length ? N : key_length);
|
||||||
|
for (; k; k--) {
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U))
|
||||||
|
+ init_key[j] + (uint32_t)j; /* non linear */
|
||||||
|
i++; j++;
|
||||||
|
if (i>=N) { mt[0] = mt[N-1]; i=1; }
|
||||||
|
if (j>=key_length) j=0;
|
||||||
|
}
|
||||||
|
for (k=N-1; k; k--) {
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U))
|
||||||
|
- (uint32_t)i; /* non linear */
|
||||||
|
i++;
|
||||||
|
if (i>=N) { mt[0] = mt[N-1]; i=1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
this departs from the traditional method of seeding a Mersenne twister. the original method is
|
||||||
|
`init_genrand`, which implements the canonical seeding function. the procedure here is:
|
||||||
|
|
||||||
|
- call `init_genrand` with a *static seed*
|
||||||
|
- combine the resulting `MT` array with the `init_key` (recall this is 32-bit chunks of the seed
|
||||||
|
value from python) using some bitwise operations and arithmetic
|
||||||
|
|
||||||
|
this is useful for us, because this means it is actually possible to control almost all values in
|
||||||
|
`MT` (except for the first one, which is hardcoded to `0x80000000`). this would not be possible with
|
||||||
|
just the canonical seeding implementation
|
||||||
|
|
||||||
|
### cracking the Mersenne twister (actually)
|
||||||
|
|
||||||
|
[z3](https://github.com/Z3Prover/z3) can be used to reverse the `init_by_array` function and produce
|
||||||
|
an input that causes `MT` to contain the desired values. this is particularly made possible by the
|
||||||
|
operations being all deterministic arithmetic on 32-bit integers, and all loops being a fixed number
|
||||||
|
of iterations
|
||||||
|
|
||||||
|
first, we set up `init_state.txt` which contains the output of `init_genrand(19650218)` since that
|
||||||
|
is static
|
||||||
|
|
||||||
|
then, the following script implements the reversing
|
||||||
|
|
||||||
|
```python
|
||||||
|
N = 624
|
||||||
|
L = N
|
||||||
|
|
||||||
|
with open("init_state.txt", "r") as f:
|
||||||
|
init_mt = [int(x.strip()) for x in f]
|
||||||
|
|
||||||
|
def crack():
|
||||||
|
s = z3.Solver()
|
||||||
|
|
||||||
|
init_key = [z3.BitVec(f"init_key_{i}", 32) for i in range(L)]
|
||||||
|
mt = [z3.BitVecVal(x, 32) for x in init_mt]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
we initialize a `init_key` of all symbolic values, and a `MT` (which in the real code would have
|
||||||
|
just been generated by `init_genrand`) to the required concrete values
|
||||||
|
|
||||||
|
next, we simulate the same operations as `init_by_array`, implemented in python
|
||||||
|
|
||||||
|
```python
|
||||||
|
i = 1
|
||||||
|
j = 0
|
||||||
|
k = N
|
||||||
|
while k > 0:
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * z3.BitVecVal(1664525, 32))) + init_key[j] + z3.BitVecVal(j, 32)
|
||||||
|
i += 1
|
||||||
|
j += 1
|
||||||
|
if i >= N:
|
||||||
|
mt[0] = mt[N-1]
|
||||||
|
i = 1
|
||||||
|
if j >= L:
|
||||||
|
j = 0
|
||||||
|
|
||||||
|
k -= 1
|
||||||
|
|
||||||
|
k = N - 1
|
||||||
|
while k > 0:
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * z3.BitVecVal(1566083941, 32))) - z3.BitVecVal(i, 32)
|
||||||
|
i += 1
|
||||||
|
if i >= N:
|
||||||
|
mt[0] = mt[N-1]
|
||||||
|
i = 1
|
||||||
|
|
||||||
|
k -= 1
|
||||||
|
```
|
||||||
|
|
||||||
|
finally, we add constraints on the output values `1..N` so that they are all zero
|
||||||
|
|
||||||
|
```python
|
||||||
|
for idx in range(1, N):
|
||||||
|
s.add(mt[idx] == 0)
|
||||||
|
```
|
||||||
|
|
||||||
|
now, we are ready to solve with z3 and output the result as an integer literal which would be passed
|
||||||
|
to the `Random` constructor, which we concatenate from the 32-bit chunks
|
||||||
|
|
||||||
|
```python
|
||||||
|
s.check()
|
||||||
|
m = s.model()
|
||||||
|
|
||||||
|
x = bytearray()
|
||||||
|
for ik in init_key:
|
||||||
|
ikv = m[ik].as_long()
|
||||||
|
x += struct.pack("<I", ikv)
|
||||||
|
|
||||||
|
print(hex(int.from_bytes(x, byteorder='little')))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
crack()
|
||||||
|
```
|
||||||
|
|
||||||
|
running this produces a solution value fairly quickly. the full script can be found at
|
||||||
|
[coinflip_crack.py](https://git.lain.faith/haskal/writeups/raw/branch/main/2023/maple/coinflip_crack.py)
|
||||||
|
and
|
||||||
|
[init_state.txt](https://git.lain.faith/haskal/writeups/raw/branch/main/2023/maple/init_state.txt)
|
||||||
|
|
||||||
|
next, we need to find out how many rounds to run with this seed
|
||||||
|
|
||||||
|
```python
|
||||||
|
from server import Coin
|
||||||
|
with open("computed_seed.txt", "r") as f:
|
||||||
|
seed = int(f.read().strip(), 0)
|
||||||
|
coin = Coin(seed)
|
||||||
|
money = 0
|
||||||
|
for i in range(20_000_000):
|
||||||
|
money += [1, -1][coin.flip()]
|
||||||
|
if money > 7_000_000:
|
||||||
|
print(i)
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
with this we get `14819684`
|
||||||
|
|
||||||
|
### jackpot!!!
|
||||||
|
|
||||||
|
running the server with the computed seed and number of rounds results in the flag! (reproduced here
|
||||||
|
only locally, i don't remember what the server flag was)
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ (sleep 2; cat seed.txt; sleep 2; echo 14819684) | python3 server.py
|
||||||
|
Welcome to Maple Betting!
|
||||||
|
We'll be betting on the outcome of a fair coin flip.
|
||||||
|
You'll start with $1 - try to make lots of money and you'll get flags!
|
||||||
|
Which coin would you like to use? How many rounds do you want to go for? Alright, let's go!
|
||||||
|
You finished with $7000001 in the pot.
|
||||||
|
What the hell?! You bankrupted the casino! Take your spoils: ctf{test_flag_test_flag}
|
||||||
|
```
|
|
@ -0,0 +1,5 @@
|
||||||
|
## the end
|
||||||
|
|
||||||
|
```hex
|
||||||
|
6a 3c 58 0f 05
|
||||||
|
```
|
|
@ -0,0 +1,16 @@
|
||||||
|
builddir = build
|
||||||
|
|
||||||
|
pandocflags = --filter writefreely-validate --wrap=none --strip-comments
|
||||||
|
|
||||||
|
postid = 7tlde1rgiq
|
||||||
|
|
||||||
|
rule pandoc
|
||||||
|
command = pandoc $pandocflags -o $out $in
|
||||||
|
description = pandoc $out
|
||||||
|
|
||||||
|
rule upload
|
||||||
|
command = writefreely-cli $postid $in
|
||||||
|
description = upload $postid
|
||||||
|
|
||||||
|
build $builddir/post-full.md: pandoc 00-intro.md 01-misc-coinflip.md 02-end.md
|
||||||
|
build upload: upload $builddir/post-full.md
|
|
@ -0,0 +1,48 @@
|
||||||
|
from random import Random
|
||||||
|
from secret import FLAG
|
||||||
|
import signal
|
||||||
|
|
||||||
|
class Coin:
|
||||||
|
def __init__(self, coin_id):
|
||||||
|
self.random = Random(coin_id)
|
||||||
|
self.flips_left = 0
|
||||||
|
self.buffer = None
|
||||||
|
|
||||||
|
def flip(self):
|
||||||
|
if self.flips_left == 0:
|
||||||
|
self.buffer = self.random.getrandbits(32)
|
||||||
|
self.flips_left = 32
|
||||||
|
res = self.buffer & 1
|
||||||
|
self.buffer >>= 1
|
||||||
|
self.flips_left -= 1
|
||||||
|
return res
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
signal.alarm(60)
|
||||||
|
print("Welcome to Maple Betting!")
|
||||||
|
print("We'll be betting on the outcome of a fair coin flip.")
|
||||||
|
print("You'll start with $1 - try to make lots of money and you'll get flags!")
|
||||||
|
|
||||||
|
game_id = input("Which coin would you like to use? ")
|
||||||
|
num_rounds = input("How many rounds do you want to go for? ")
|
||||||
|
num_rounds = int(num_rounds)
|
||||||
|
if num_rounds > 20_000_000:
|
||||||
|
print("Can't play that long, I'm afraid.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
print("Alright, let's go!")
|
||||||
|
coin = Coin(int(game_id, 0))
|
||||||
|
money = 1
|
||||||
|
for nr in range(num_rounds):
|
||||||
|
money += [1, -1][coin.flip()]
|
||||||
|
if money <= 0:
|
||||||
|
print(f"Oops, you went broke at round {nr+1}!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
print(f"You finished with ${money} in the pot.")
|
||||||
|
if money < 18_000:
|
||||||
|
print("At least you didn't go broke!")
|
||||||
|
elif money < 7_000_000:
|
||||||
|
print(f"Pretty good!")
|
||||||
|
else:
|
||||||
|
print(f"What the hell?! You bankrupted the casino! Take your spoils: {FLAG}")
|
|
@ -0,0 +1,55 @@
|
||||||
|
import z3
|
||||||
|
import struct
|
||||||
|
|
||||||
|
N = 624
|
||||||
|
L = N
|
||||||
|
|
||||||
|
with open("init_state.txt", "r") as f:
|
||||||
|
init_mt = [int(x.strip()) for x in f]
|
||||||
|
|
||||||
|
def crack():
|
||||||
|
s = z3.Solver()
|
||||||
|
|
||||||
|
init_key = [z3.BitVec(f"init_key_{i}", 32) for i in range(L)]
|
||||||
|
mt = [z3.BitVecVal(x, 32) for x in init_mt]
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
j = 0
|
||||||
|
k = N
|
||||||
|
while k > 0:
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * z3.BitVecVal(1664525, 32))) + init_key[j] + z3.BitVecVal(j, 32)
|
||||||
|
i += 1
|
||||||
|
j += 1
|
||||||
|
if i >= N:
|
||||||
|
mt[0] = mt[N-1]
|
||||||
|
i = 1
|
||||||
|
if j >= L:
|
||||||
|
j = 0
|
||||||
|
|
||||||
|
k -= 1
|
||||||
|
|
||||||
|
k = N - 1
|
||||||
|
while k > 0:
|
||||||
|
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * z3.BitVecVal(1566083941, 32))) - z3.BitVecVal(i, 32)
|
||||||
|
i += 1
|
||||||
|
if i >= N:
|
||||||
|
mt[0] = mt[N-1]
|
||||||
|
i = 1
|
||||||
|
|
||||||
|
k -= 1
|
||||||
|
|
||||||
|
for idx in range(1, N):
|
||||||
|
s.add(mt[idx] == 0)
|
||||||
|
|
||||||
|
s.check()
|
||||||
|
m = s.model()
|
||||||
|
|
||||||
|
x = bytearray()
|
||||||
|
for ik in init_key:
|
||||||
|
ikv = m[ik].as_long()
|
||||||
|
x += struct.pack("<I", ikv)
|
||||||
|
|
||||||
|
print(hex(int.from_bytes(x, byteorder='little')))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
crack()
|
|
@ -0,0 +1,624 @@
|
||||||
|
19650218
|
||||||
|
2194844435
|
||||||
|
874550967
|
||||||
|
1417962806
|
||||||
|
719805879
|
||||||
|
2188372024
|
||||||
|
721660136
|
||||||
|
1814940559
|
||||||
|
2833403150
|
||||||
|
3889680837
|
||||||
|
1003665704
|
||||||
|
1330738387
|
||||||
|
2892331238
|
||||||
|
3489052161
|
||||||
|
3855278296
|
||||||
|
3311200630
|
||||||
|
1422571577
|
||||||
|
2585306665
|
||||||
|
2882769417
|
||||||
|
2783805802
|
||||||
|
4207719964
|
||||||
|
2400416080
|
||||||
|
2341377904
|
||||||
|
2590753297
|
||||||
|
3924081815
|
||||||
|
1211472509
|
||||||
|
3057012486
|
||||||
|
3436335279
|
||||||
|
551149560
|
||||||
|
1318655221
|
||||||
|
1900533858
|
||||||
|
3537525294
|
||||||
|
2107812065
|
||||||
|
3148644481
|
||||||
|
594136785
|
||||||
|
1814262168
|
||||||
|
1224061569
|
||||||
|
653651109
|
||||||
|
254650943
|
||||||
|
2832785922
|
||||||
|
3699583528
|
||||||
|
2088609312
|
||||||
|
3529585711
|
||||||
|
41492871
|
||||||
|
2876012911
|
||||||
|
4240588078
|
||||||
|
1402615791
|
||||||
|
1934126869
|
||||||
|
3096545044
|
||||||
|
2890863071
|
||||||
|
80499043
|
||||||
|
970921794
|
||||||
|
3007610686
|
||||||
|
750866145
|
||||||
|
799115259
|
||||||
|
3629971774
|
||||||
|
2864380489
|
||||||
|
3888374480
|
||||||
|
2087741561
|
||||||
|
3146346387
|
||||||
|
3269762417
|
||||||
|
2727485495
|
||||||
|
2488668711
|
||||||
|
2964190680
|
||||||
|
2116659522
|
||||||
|
4141458096
|
||||||
|
3537107937
|
||||||
|
3667677805
|
||||||
|
2429248426
|
||||||
|
2452306317
|
||||||
|
3015982257
|
||||||
|
499957222
|
||||||
|
2360410630
|
||||||
|
4194693085
|
||||||
|
147288288
|
||||||
|
3359074475
|
||||||
|
1635136148
|
||||||
|
4073107990
|
||||||
|
3628367767
|
||||||
|
3898116531
|
||||||
|
275612352
|
||||||
|
2842514961
|
||||||
|
3115851985
|
||||||
|
3103448722
|
||||||
|
302309156
|
||||||
|
22171017
|
||||||
|
2075519075
|
||||||
|
3671007489
|
||||||
|
3949991970
|
||||||
|
1963601502
|
||||||
|
4167967445
|
||||||
|
804406473
|
||||||
|
1055110313
|
||||||
|
3894654986
|
||||||
|
2278780139
|
||||||
|
34711884
|
||||||
|
4121261916
|
||||||
|
3468881884
|
||||||
|
2287991389
|
||||||
|
393453278
|
||||||
|
548699130
|
||||||
|
1499706375
|
||||||
|
332872900
|
||||||
|
1556864443
|
||||||
|
1043137738
|
||||||
|
4174970395
|
||||||
|
1614747618
|
||||||
|
669116410
|
||||||
|
1897615374
|
||||||
|
3255278936
|
||||||
|
1370736725
|
||||||
|
1550777747
|
||||||
|
1685794058
|
||||||
|
1862314184
|
||||||
|
2400528575
|
||||||
|
2672900100
|
||||||
|
1647333586
|
||||||
|
3524644532
|
||||||
|
1765506473
|
||||||
|
2857335743
|
||||||
|
3636393737
|
||||||
|
2932986219
|
||||||
|
1203228647
|
||||||
|
1628511289
|
||||||
|
3647085204
|
||||||
|
2987412752
|
||||||
|
2905279128
|
||||||
|
2631768385
|
||||||
|
4014428911
|
||||||
|
1727529885
|
||||||
|
1124854030
|
||||||
|
2262104686
|
||||||
|
2499713312
|
||||||
|
2421398767
|
||||||
|
4134715143
|
||||||
|
2358935835
|
||||||
|
1002066021
|
||||||
|
340444514
|
||||||
|
3268366900
|
||||||
|
1112268606
|
||||||
|
1897974631
|
||||||
|
3331577291
|
||||||
|
2922602614
|
||||||
|
3423543891
|
||||||
|
1267030560
|
||||||
|
2344564886
|
||||||
|
1942259446
|
||||||
|
3179572998
|
||||||
|
1573187880
|
||||||
|
1205933762
|
||||||
|
3025229445
|
||||||
|
4246102746
|
||||||
|
346693941
|
||||||
|
2002220930
|
||||||
|
1829519945
|
||||||
|
3309743875
|
||||||
|
1904872348
|
||||||
|
955816590
|
||||||
|
2796353700
|
||||||
|
668528669
|
||||||
|
2648785169
|
||||||
|
2704726048
|
||||||
|
893089804
|
||||||
|
738773343
|
||||||
|
2832484895
|
||||||
|
2050343702
|
||||||
|
104744889
|
||||||
|
3439545764
|
||||||
|
980222603
|
||||||
|
422274176
|
||||||
|
3865519914
|
||||||
|
2026267864
|
||||||
|
539814729
|
||||||
|
4137805178
|
||||||
|
1140607595
|
||||||
|
2537690753
|
||||||
|
3971218783
|
||||||
|
1931293181
|
||||||
|
3089667358
|
||||||
|
1133695167
|
||||||
|
399772074
|
||||||
|
3682192071
|
||||||
|
4293649418
|
||||||
|
1029228868
|
||||||
|
3902327948
|
||||||
|
1974090788
|
||||||
|
3344730195
|
||||||
|
2795804747
|
||||||
|
3396216457
|
||||||
|
366677807
|
||||||
|
416687433
|
||||||
|
930072460
|
||||||
|
901228284
|
||||||
|
1521860141
|
||||||
|
3484259358
|
||||||
|
478803252
|
||||||
|
3138556488
|
||||||
|
4137898487
|
||||||
|
3807832586
|
||||||
|
3773310804
|
||||||
|
3221624091
|
||||||
|
3076008769
|
||||||
|
4156878137
|
||||||
|
406561453
|
||||||
|
3897607181
|
||||||
|
623564883
|
||||||
|
2247148685
|
||||||
|
1696011322
|
||||||
|
2911604503
|
||||||
|
3979653402
|
||||||
|
742342831
|
||||||
|
3881512158
|
||||||
|
2282092805
|
||||||
|
2681274264
|
||||||
|
3681829528
|
||||||
|
46152446
|
||||||
|
3126539534
|
||||||
|
3635632789
|
||||||
|
1012335624
|
||||||
|
3686064131
|
||||||
|
2587648220
|
||||||
|
2008745587
|
||||||
|
2556071384
|
||||||
|
1788453345
|
||||||
|
861781568
|
||||||
|
2727104545
|
||||||
|
758340017
|
||||||
|
1880693944
|
||||||
|
2136364769
|
||||||
|
1370367813
|
||||||
|
798286522
|
||||||
|
506003017
|
||||||
|
2520802485
|
||||||
|
2991500316
|
||||||
|
3489134272
|
||||||
|
3275208410
|
||||||
|
1640252809
|
||||||
|
3797759893
|
||||||
|
4271912220
|
||||||
|
3111882026
|
||||||
|
140581304
|
||||||
|
2568658569
|
||||||
|
2686841033
|
||||||
|
3059852298
|
||||||
|
293994524
|
||||||
|
1890650113
|
||||||
|
1797269750
|
||||||
|
3428669802
|
||||||
|
1401714789
|
||||||
|
2643788909
|
||||||
|
3727894469
|
||||||
|
2833360921
|
||||||
|
1622853283
|
||||||
|
3832221927
|
||||||
|
277065458
|
||||||
|
3711010937
|
||||||
|
4192871202
|
||||||
|
3356722694
|
||||||
|
680496635
|
||||||
|
2574997514
|
||||||
|
1476265004
|
||||||
|
3232676806
|
||||||
|
3318710975
|
||||||
|
4210635059
|
||||||
|
4159903992
|
||||||
|
2116300560
|
||||||
|
2532158399
|
||||||
|
718792604
|
||||||
|
2539969944
|
||||||
|
3164133583
|
||||||
|
2649636591
|
||||||
|
2200349072
|
||||||
|
2851998122
|
||||||
|
670873689
|
||||||
|
2613796143
|
||||||
|
3562264788
|
||||||
|
1174445287
|
||||||
|
1149173203
|
||||||
|
2225964784
|
||||||
|
4266377361
|
||||||
|
3119455410
|
||||||
|
1518371465
|
||||||
|
1816545474
|
||||||
|
2516586762
|
||||||
|
240910660
|
||||||
|
2681595121
|
||||||
|
1301176317
|
||||||
|
3127753611
|
||||||
|
862342957
|
||||||
|
771183330
|
||||||
|
438085196
|
||||||
|
1046497567
|
||||||
|
922186079
|
||||||
|
1222939296
|
||||||
|
51184555
|
||||||
|
1757804190
|
||||||
|
426665187
|
||||||
|
2730510776
|
||||||
|
2573705612
|
||||||
|
1312406577
|
||||||
|
667742236
|
||||||
|
3239950393
|
||||||
|
2582034960
|
||||||
|
3759737929
|
||||||
|
1601926242
|
||||||
|
2947737408
|
||||||
|
975540284
|
||||||
|
1285948639
|
||||||
|
3761027786
|
||||||
|
1226457986
|
||||||
|
34782949
|
||||||
|
2916146832
|
||||||
|
142734034
|
||||||
|
569716755
|
||||||
|
4042990521
|
||||||
|
3947471773
|
||||||
|
1575951506
|
||||||
|
3517313596
|
||||||
|
3100986137
|
||||||
|
2199197158
|
||||||
|
3376719924
|
||||||
|
4087139828
|
||||||
|
3705107125
|
||||||
|
1482533137
|
||||||
|
1541227668
|
||||||
|
1678953742
|
||||||
|
2056318769
|
||||||
|
3045003063
|
||||||
|
1622629937
|
||||||
|
487578169
|
||||||
|
4137196231
|
||||||
|
3764647071
|
||||||
|
2241527512
|
||||||
|
2558474063
|
||||||
|
1038354351
|
||||||
|
2094837850
|
||||||
|
2481932343
|
||||||
|
3229539130
|
||||||
|
3756851151
|
||||||
|
1006180559
|
||||||
|
4181103103
|
||||||
|
3565909441
|
||||||
|
2371373280
|
||||||
|
1493415041
|
||||||
|
160348120
|
||||||
|
1285104017
|
||||||
|
3595587370
|
||||||
|
4264242568
|
||||||
|
1161124915
|
||||||
|
2042766103
|
||||||
|
737713932
|
||||||
|
3481808155
|
||||||
|
478389208
|
||||||
|
1300643225
|
||||||
|
1007986266
|
||||||
|
1168231653
|
||||||
|
3652705112
|
||||||
|
2909421388
|
||||||
|
3924670764
|
||||||
|
1731016690
|
||||||
|
4084014919
|
||||||
|
4205099837
|
||||||
|
1373900512
|
||||||
|
2937538864
|
||||||
|
2730075174
|
||||||
|
957417377
|
||||||
|
3258199283
|
||||||
|
87174175
|
||||||
|
792789163
|
||||||
|
2527971304
|
||||||
|
2716998340
|
||||||
|
3091367825
|
||||||
|
97659251
|
||||||
|
1782441684
|
||||||
|
919015551
|
||||||
|
735476370
|
||||||
|
87326482
|
||||||
|
926205331
|
||||||
|
1888657273
|
||||||
|
3715638227
|
||||||
|
1715499660
|
||||||
|
1922410526
|
||||||
|
4175228089
|
||||||
|
1525608673
|
||||||
|
3578587616
|
||||||
|
2042086160
|
||||||
|
3730509879
|
||||||
|
3607443975
|
||||||
|
3879209240
|
||||||
|
3652717612
|
||||||
|
2372597521
|
||||||
|
3471943430
|
||||||
|
2765853569
|
||||||
|
3643232056
|
||||||
|
3297105617
|
||||||
|
2692883557
|
||||||
|
1805942063
|
||||||
|
1394934451
|
||||||
|
3337180104
|
||||||
|
1181922214
|
||||||
|
2331394419
|
||||||
|
306465830
|
||||||
|
3736887952
|
||||||
|
1729663122
|
||||||
|
3390355091
|
||||||
|
2379159653
|
||||||
|
3851731257
|
||||||
|
4021176185
|
||||||
|
1079541434
|
||||||
|
433656928
|
||||||
|
1831627642
|
||||||
|
2892512290
|
||||||
|
4063025724
|
||||||
|
406246264
|
||||||
|
1293199350
|
||||||
|
1120564498
|
||||||
|
3926678815
|
||||||
|
1350089133
|
||||||
|
4273098366
|
||||||
|
3385122292
|
||||||
|
993379095
|
||||||
|
725502136
|
||||||
|
25504318
|
||||||
|
752278045
|
||||||
|
3729298457
|
||||||
|
2392480235
|
||||||
|
2657233815
|
||||||
|
320925812
|
||||||
|
2950230896
|
||||||
|
989728679
|
||||||
|
506301841
|
||||||
|
1404204260
|
||||||
|
1413065993
|
||||||
|
865242585
|
||||||
|
866785615
|
||||||
|
1859142878
|
||||||
|
589268143
|
||||||
|
775553472
|
||||||
|
1410495094
|
||||||
|
1607063978
|
||||||
|
3888932143
|
||||||
|
704411669
|
||||||
|
3513884419
|
||||||
|
3370826939
|
||||||
|
2896358996
|
||||||
|
439226283
|
||||||
|
2352722741
|
||||||
|
1626809714
|
||||||
|
246502175
|
||||||
|
189424636
|
||||||
|
1337937966
|
||||||
|
3719088974
|
||||||
|
4178799653
|
||||||
|
2794717891
|
||||||
|
1831166187
|
||||||
|
1862432793
|
||||||
|
2263235392
|
||||||
|
3847861459
|
||||||
|
802662362
|
||||||
|
3621709005
|
||||||
|
2634319122
|
||||||
|
3245216029
|
||||||
|
1466421412
|
||||||
|
1528864744
|
||||||
|
349292989
|
||||||
|
3152395874
|
||||||
|
3374677426
|
||||||
|
2279952808
|
||||||
|
1238578150
|
||||||
|
107682552
|
||||||
|
913857966
|
||||||
|
3747681661
|
||||||
|
3560958606
|
||||||
|
3617063034
|
||||||
|
1988620951
|
||||||
|
1854864649
|
||||||
|
1862999556
|
||||||
|
2962654934
|
||||||
|
1498851202
|
||||||
|
2003448718
|
||||||
|
2942754891
|
||||||
|
798789550
|
||||||
|
3882536840
|
||||||
|
3338815162
|
||||||
|
3066948065
|
||||||
|
2057094004
|
||||||
|
4171611151
|
||||||
|
4284063395
|
||||||
|
2325690120
|
||||||
|
2659914459
|
||||||
|
165909127
|
||||||
|
2783186990
|
||||||
|
2161504072
|
||||||
|
343671839
|
||||||
|
2751150377
|
||||||
|
3621950182
|
||||||
|
222528329
|
||||||
|
3219381950
|
||||||
|
238911006
|
||||||
|
2710753737
|
||||||
|
2982111755
|
||||||
|
1115859074
|
||||||
|
156211365
|
||||||
|
228231184
|
||||||
|
2302165064
|
||||||
|
933165355
|
||||||
|
4181545713
|
||||||
|
2201173365
|
||||||
|
291303663
|
||||||
|
19134280
|
||||||
|
3581811046
|
||||||
|
68817880
|
||||||
|
1037069880
|
||||||
|
2445243929
|
||||||
|
2507869609
|
||||||
|
1468655994
|
||||||
|
2646143627
|
||||||
|
2709652242
|
||||||
|
559859542
|
||||||
|
2657856757
|
||||||
|
248278651
|
||||||
|
656698256
|
||||||
|
2682159578
|
||||||
|
3542996035
|
||||||
|
2775252812
|
||||||
|
1761180115
|
||||||
|
3646714856
|
||||||
|
2330951878
|
||||||
|
834843492
|
||||||
|
3951905925
|
||||||
|
744286448
|
||||||
|
3621804227
|
||||||
|
2822882772
|
||||||
|
1168938371
|
||||||
|
3349647456
|
||||||
|
672527398
|
||||||
|
1163635478
|
||||||
|
3445281068
|
||||||
|
722448549
|
||||||
|
3543924788
|
||||||
|
2823456463
|
||||||
|
1931863550
|
||||||
|
2483173049
|
||||||
|
4148604134
|
||||||
|
3081487737
|
||||||
|
2916138664
|
||||||
|
940193076
|
||||||
|
4142650279
|
||||||
|
2563327448
|
||||||
|
3737140007
|
||||||
|
2407111514
|
||||||
|
243557343
|
||||||
|
1657192483
|
||||||
|
3995730323
|
||||||
|
1012445178
|
||||||
|
2365602253
|
||||||
|
2830079959
|
||||||
|
2287658550
|
||||||
|
2893719730
|
||||||
|
2373631903
|
||||||
|
4215513121
|
||||||
|
189686171
|
||||||
|
2003138393
|
||||||
|
3410898923
|
||||||
|
1020530876
|
||||||
|
1103312993
|
||||||
|
1976606742
|
||||||
|
899447370
|
||||||
|
1949555562
|
||||||
|
3167671920
|
||||||
|
595304244
|
||||||
|
1919198655
|
||||||
|
2929333298
|
||||||
|
619161901
|
||||||
|
623498751
|
||||||
|
2063591130
|
||||||
|
763251111
|
||||||
|
4291719204
|
||||||
|
3951567013
|
||||||
|
2998385089
|
||||||
|
758818611
|
||||||
|
1375945828
|
||||||
|
2510752543
|
||||||
|
4188334520
|
||||||
|
121785359
|
||||||
|
3225750324
|
||||||
|
1354685949
|
||||||
|
1643999927
|
||||||
|
911976986
|
||||||
|
518523023
|
||||||
|
3993561529
|
||||||
|
2326708913
|
||||||
|
336174575
|
||||||
|
853096604
|
||||||
|
2873283550
|
||||||
|
4022490143
|
||||||
|
3010604384
|
||||||
|
2080594943
|
||||||
|
1702902668
|
||||||
|
3360749048
|
||||||
|
4184957279
|
||||||
|
2421794725
|
||||||
|
4155016765
|
||||||
|
3104188113
|
||||||
|
1576615579
|
||||||
|
604774175
|
||||||
|
2739462297
|
||||||
|
4096823942
|
||||||
|
1932918233
|
||||||
|
1779286169
|
||||||
|
2544260698
|
||||||
|
1430072091
|
||||||
|
2196303270
|
||||||
|
4237199385
|
||||||
|
2613550760
|
||||||
|
1481676153
|
||||||
|
2920297152
|
||||||
|
2463881971
|
||||||
|
1098865791
|
||||||
|
2939219489
|
||||||
|
2494804283
|
||||||
|
3108728554
|
||||||
|
1635052534
|
||||||
|
2905164258
|
Loading…
Reference in New Issue