Jailer
Let’s decompile the binary and see what it does
sub_1280(a1, a2, a3);
if ( !(unsigned int)sub_13A0() )
return system(a2[1]);
It seems to expect a command line argument, if provided it calls sub_13A0() to ‘check’ the input and calls system on our input.
Now you can just run cat flag.txt and it will print the flag locally. But let’s dig a bit deeper.
__int64 sub_13A0()
{
int v0; // ebp
int v1; // ebx
v0 = sub_12E0();
v1 = open("flag.txt", 0);
if ( v1 < 0 )
{
v1 = open("/flag.txt", 0);
if ( v1 < 0 )
return 0xFFFFFFFFLL;
}
dup2(v1, v0);
close(v1);
return 0;
}
This seems to open the flag, v0 is calculated in sub_12E0. The file descriptor for the flag is in v1 which then gets closed after a dup2 call. dup2 is used to duplicate the file descriptor.
Let’s look at what it calculate
__int64 sub_12E0()
{
int v0; // ecx
unsigned int v1; // eax
int v2; // edx
__int64 v3; // rax
char v5[10]; // [rsp+Eh] [rbp-1Ah] BYREF
unsigned __int64 v6; // [rsp+18h] [rbp-10h]
v0 = 0;
v6 = __readfsqword(0x28u);
strcpy(v5, "J41lBr34k");
v1 = 4919;
do
{
v2 = __ROL4__(v1, 3);
v3 = v0++;
v1 = 31337 * (v2 ^ (unsigned __int8)v5[v3]);
}
while ( v0 != 9 );
return v1 % 0x61 + 103;
}
Reversing this logic:
- Starting value: 4919
- For each character in “J41lBr34k”:
- Rotate left by 3 bits
- XOR with character
- Multiply by 31337
- Final: result % 97 + 103
We can write a small python script to calculate the fd for us
def rol4(value, shift):
"""Rotate left 32-bit value by shift bits"""
value &= 0xFFFFFFFF # Keep as 32-bit
return ((value << shift) | (value >> (32 - shift))) & 0xFFFFFFFF
def calculate_fd():
key = "J41lBr34k"
v1 = 4919
print(f"Starting value: {v1}")
print(f"Key string: '{key}'")
print("\nStep-by-step calculation:")
print("-" * 60)
for i, char in enumerate(key):
# Rotate left by 3
v2 = rol4(v1, 3)
print(f"Step {i+1}: char='{char}' (ASCII {ord(char)})")
print(f" After ROL4(3): {v1} -> {v2}")
# XOR with character
xor_result = v2 ^ ord(char)
print(f" After XOR with {ord(char)}: {v2} ^ {ord(char)} = {xor_result}")
# Multiply by 31337
v1 = (31337 * xor_result) & 0xFFFFFFFF # Keep as 32-bit
print(f" After multiply by 31337: {v1}")
print()
# Final calculation: v1 % 97 + 103
fd = (v1 % 97) + 103
print("=" * 60)
print(f"Final hash value: {v1}")
print(f"FD calculation: {v1} % 97 + 103 = {v1 % 97} + 103 = {fd}")
print("=" * 60)
return fd
We get the value 128.
In linux, each process has a file descriptor table that can be accessed using /proc/[pid]/fd, in this case… we can do /proc/self/fd/128. This will point to the flag file.
So running
cat /proc/self/fd/128
or
cat <&128
will print the flag.