Reverse Engineering
{"author": ["ret2basic"]}

Transformation

Solved by: ret2basic

Challenge

I wonder what this really is... enc ''.join([chr((ord(flag[i]) << 8) + ord(flag[i + 1])) for i in range(0, len(flag), 2)])

Analysis

The encoding scheme acts on two characters from the flag each time. The first character is used as higher 8 bits, while the second character is used as lower 8 bits. Together, the 2-character pair is transformed into a 16-bit binary number and this binary number is converted to ASCII character.

Implementation

1
#!/usr/bin/env python3
2
3
with open("enc", "r") as f:
4
encoded = f.read()
5
6
flag = ""
7
for ch in encoded:
8
binary = "{0:016b}".format(ord(ch))
9
first_half, second_half = binary[:8], binary[8:]
10
flag += chr(int(first_half, 2))
11
flag += chr(int(second_half, 2))
12
13
print(flag)
Copied!

Flag

1
picoCTF{16_bits_inst34d_of_8_04c0760d}
Copied!

keygenme-py

Solved by: ret2basic

Challenge

Source Code

1
def check_key(key, username_trial):
2
3
global key_full_template_trial
4
5
if len(key) != len(key_full_template_trial):
6
return False
7
else:
8
# Check static base key part --v
9
i = 0
10
for c in key_part_static1_trial:
11
if key[i] != c:
12
return False
13
14
i += 1
15
16
# TODO : test performance on toolbox container
17
# Check dynamic part --v
18
if key[i] != hashlib.sha256(username_trial).hexdigest()[4]:
19
return False
20
else:
21
i += 1
22
23
if key[i] != hashlib.sha256(username_trial).hexdigest()[5]:
24
return False
25
else:
26
i += 1
27
28
if key[i] != hashlib.sha256(username_trial).hexdigest()[3]:
29
return False
30
else:
31
i += 1
32
33
if key[i] != hashlib.sha256(username_trial).hexdigest()[6]:
34
return False
35
else:
36
i += 1
37
38
if key[i] != hashlib.sha256(username_trial).hexdigest()[2]:
39
return False
40
else:
41
i += 1
42
43
if key[i] != hashlib.sha256(username_trial).hexdigest()[7]:
44
return False
45
else:
46
i += 1
47
48
if key[i] != hashlib.sha256(username_trial).hexdigest()[1]:
49
return False
50
else:
51
i += 1
52
53
if key[i] != hashlib.sha256(username_trial).hexdigest()[8]:
54
return False
55
56
57
58
return True
Copied!

Analysis

According to the global variables declared at the beginning of the source code, the flag is picoCTF{1n_7h3_|<3y_of_xxxxxxxx} where x stands for a "dynamic" character. Our objective is to reverse engineer the check_key function and pass the check.
Note that check_key is not fully implemented and there are eight if statements checking if a certain character is valid. We could simply write a script and recover each character.

Implementation

1
#!/usr/bin/env python3
2
import hashlib
3
4
username_trial = b"PRITCHARD"
5
digest = hashlib.sha256(username_trial).hexdigest()
6
7
print(f"index 4: {digest[4]}")
8
print(f"index 5: {digest[5]}")
9
print(f"index 3: {digest[3]}")
10
print(f"index 6: {digest[6]}")
11
print(f"index 2: {digest[2]}")
12
print(f"index 7: {digest[7]}")
13
print(f"index 1: {digest[1]}")
14
print(f"index 8: {digest[8]}")
15
16
flag_part_1 = "picoCTF{1n_7h3_|<3y_of_"
17
flag_part_2 = ""
18
flag_part_2 += digest[4] + digest[5]
19
flag_part_2 += digest[3] + digest[6]
20
flag_part_2 += digest[2] + digest[7]
21
flag_part_2 += digest[1] + digest[8]
22
flag_part_3 = "}"
23
24
print(f"flag: {flag_part_1 + flag_part_2 + flag_part_3}")
Copied!

Flag

1
picoCTF{1n_7h3_|<3y_of_54ef6292}
Copied!

crackme-py

Solved by: ret2basic

Challenge

Source Code

1
# Hiding this really important number in an obscure piece of code is brilliant!
2
# AND it's encrypted!
3
# We want our biggest client to know his information is safe with us.
4
bezos_cc_secret = "A:[email protected]%uL`M-^M0c0AbcM-MFE055a4ce`eN"
5
6
# Reference alphabet
7
alphabet = "!\"#$%&'()*+,-./0123456789:;<=>[email protected]"+ \
8
"[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
9
10
11
12
def decode_secret(secret):
13
"""ROT47 decode
14
15
NOTE: encode and decode are the same operation in the ROT cipher family.
16
"""
17
18
# Encryption key
19
rotate_const = 47
20
21
# Storage for decoded secret
22
decoded = ""
23
24
# decode loop
25
for c in secret:
26
index = alphabet.find(c)
27
original_index = (index + rotate_const) % len(alphabet)
28
decoded = decoded + alphabet[original_index]
29
30
print(decoded)
31
32
33
34
def choose_greatest():
35
"""Echo the largest of the two numbers given by the user to the program
36
37
Warning: this function was written quickly and needs proper error handling
38
"""
39
40
user_value_1 = input("What's your first number? ")
41
user_value_2 = input("What's your second number? ")
42
greatest_value = user_value_1 # need a value to return if 1 & 2 are equal
43
44
if user_value_1 > user_value_2:
45
greatest_value = user_value_1
46
elif user_value_1 < user_value_2:
47
greatest_value = user_value_2
48
49
print( "The number with largest positive magnitude is "
50
+ str(greatest_value) )
51
52
53
54
choose_greatest()
Copied!

Analysis

Modify the source code to call the decode_secret function.

Implementation

1
# choose_greatest()
2
print(decode_secret(bezos_cc_secret))
Copied!

Flag

1
picoCTF{1|\/|_4_p34|\|ut_dd2c4616}
Copied!

ARMssembly 0

Solved by: ret2basic

Challenge

What integer does this program print with arguments 1765227561 and 1830628817? File: chall.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})

Assembly with Comments

1
.arch armv8-a
2
.file "chall.c"
3
.text
4
.align 2
5
.global func1
6
.type func1, %function
7
func1:
8
sub sp, sp, #16 @ allocate 16 bytes on the stack
9
str w0, [sp, 12] @ store w0 into [sp+12]
10
str w1, [sp, 8] @ store w1 into [sp+8]
11
ldr w1, [sp, 12] @ load [sp+12] into w1
12
ldr w0, [sp, 8] @ load [sp+8] into w0
13
cmp w1, w0 @ compare w1 and w0 => compare [sp+12] and [sp+8]
14
bls .L2 @ branch to .L2 if ls
15
ldr w0, [sp, 12] @ load [sp+12] into w0
16
b .L3 @ branch to .L3
17
.L2:
18
ldr w0, [sp, 8]
19
.L3:
20
add sp, sp, 16
21
ret
22
.size func1, .-func1
23
.section .rodata
24
.align 3
25
.LC0:
26
.string "Result: %ld\n"
27
.text
28
.align 2
29
.global main
30
.type main, %function
31
main:
32
stp x29, x30, [sp, -48]!
33
add x29, sp, 0
34
str x19, [sp, 16]
35
str w0, [x29, 44]
36
str x1, [x29, 32]
37
ldr x0, [x29, 32]
38
add x0, x0, 8
39
ldr x0, [x0]
40
bl atoi
41
mov w19, w0
42
ldr x0, [x29, 32]
43
add x0, x0, 16
44
ldr x0, [x0]
45
bl atoi
46
mov w1, w0
47
mov w0, w19
48
bl func1
49
mov w1, w0
50
adrp x0, .LC0
51
add x0, x0, :lo12:.LC0
52
bl printf
53
mov w0, 0
54
ldr x19, [sp, 16]
55
ldp x29, x30, [sp], 48
56
ret
57
.size main, .-main
58
.ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
59
.section .note.GNU-stack,"",@progbits
Copied!

Solution

bls: Branch on Lower than or Same.
The main function calls atoi twice to convert the arguments to integers and then calls func1 to compare those two integers. Since
176522756118306288171765227561 \leq 1830628817
, the control flow goes to .L2. Now w0 = [sp+8] = 1830628817 = x0.
Eventually, when printf is called, the value stored in x0 will be printed (calling convention). Hence this program prints 1830628817, which is 0x6d1d2dd1 in hex.

Flag

1
picoCTF{6d1d2dd1}
Copied!

speeds and feeds

Solved by: ret2basic

Challenge

There is something on my shop network running at mercury.picoctf.net:53740, but I can't tell what it is. Can you?

Analysis

Save the G-code to a file:
1
$ nc mercury.picoctf.net 53740 > G-code.txt
Copied!
Use NC Viewer to plot the flag.

Flag

1
picoCTF{num3r1cal_c0ntr0l_775375c7}
Copied!

Shop

Solved by: ret2basic

Challenge

Best Stuff - Cheap Stuff, Buy Buy Buy... Store Instance: source. The shop is open for business at nc mercury.picoctf.net 34938.

Analysis

Buy -10 "Quiet Quiches" and then buy 1 flag. Convert ASCII numbers to text.

Implementation

1
#!/usr/bin/env python3
2
3
characters = [112, 105, 99, 111, 67, 84, 70, 123, 98, 52, 100, 95, 98, 114, 111, 103, 114, 97, 109, 109, 101, 114, 95, 98, 97, 54, 98, 56, 99, 100, 102, 125]
4
5
flag = ""
6
for character in characters:
7
flag += chr(character)
8
9
print(flag)
Copied!

Flag

1
picoCTF{b4d_brogrammer_ba6b8cdf}
Copied!

ARMssembly 1

Solved by: ret2basic

Challenge

For what argument does this program print win with variables 85, 6 and 3? File: chall_1.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})

Assembly with Comments

1
.arch armv8-a
2
.file "chall_1.c"
3
.text
4
.align 2
5
.global func
6
.type func, %function
7
func:
8
sub sp, sp, #32 @ allocate 32 bytes on the stack
9
str w0, [sp, 12] @ [sp+12] = w0 = [x29+44] = arg
10
mov w0, 85 @ w0 = 85
11
str w0, [sp, 16] @ [sp+16] = w0 = 85
12
mov w0, 6 @ w0 = 6
13
str w0, [sp, 20] @ [sp+20] = w0 = 6
14
mov w0, 3 @ w0 = 3
15
str w0, [sp, 24] @ [sp+24] = w0 = 3
16
ldr w0, [sp, 20] @ w0 = [sp+20] = 6
17
ldr w1, [sp, 16] @ w1 = [sp+16] = 85
18
lsl w0, w1, w0 @ w0 = w1 * (2**w0) = 85 * (2**6) = 85 * 64 = 5440
19
str w0, [sp, 28] @ [sp+28] = w0 = 5440
20
ldr w1, [sp, 28] @ w1 = [sp+28] = 5440
21
ldr w0, [sp, 24] @ w0 = [sp+24] = 3
22
sdiv w0, w1, w0 @ w0 = w1 // w2 = 5440 // 3 = 1813
23
str w0, [sp, 28] @ [sp+28] = w0 = 1813
24
ldr w1, [sp, 28] @ w1 = [sp+28] = 1813
25
ldr w0, [sp, 12] @ w0 = [sp+12] = arg
26
sub w0, w1, w0 @ w0 = w1 - w0 = 1813 - arg
27
str w0, [sp, 28] @ [sp+28] = w0 = 1813 - arg
28
ldr w0, [sp, 28] @ w0 = [sp+28] = 1813 - arg
29
add sp, sp, 32
30
ret
31
.size func, .-func
32
.section .rodata
33
.align 3
34
.LC0:
35
.string "You win!"
36
.align 3
37
.LC1:
38
.string "You Lose :("
39
.text
40
.align 2
41
.global main
42
.type main, %function
43
main:
44
stp x29, x30, [sp, -48]!
45
add x29, sp, 0
46
str w0, [x29, 28]
47
str x1, [x29, 16]
48
ldr x0, [x29, 16]
49
add x0, x0, 8
50
ldr x0, [x0]
51
bl atoi
52
str w0, [x29, 44]
53
ldr w0, [x29, 44]
54
bl func
55
cmp w0, 0
56
bne .L4
57
adrp x0, .LC0
58
add x0, x0, :lo12:.LC0
59
bl puts
60
b .L6
61
.L4:
62
adrp x0, .LC1
63
add x0, x0, :lo12:.LC1
64
bl puts
65
.L6:
66
nop
67
ldp x29, x30, [sp], 48
68
ret
69
.size main, .-main
70
.ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
71
.section .note.GNU-stack,"",@progbits
Copied!

Solution

lsl: Logical Shift Left. It provides the value of a register multiplied by a power of two, inserting zeros into the vacated bit positions.
sdiv: Signed Divide.
Note that the x29 register is the frame pointer in ARM64. It is equivalent to the RBP register in Intel x86-64. The function func is just doing math:
85263=arg\frac{85 \cdot 2^6}{3} = arg
Hence arg = 1813, which is 0x715 in hex.

Flag

1
picoCTF{00000715}
Copied!

ARMssembly 2

Solved by: ret2basic

Challenge

What integer does this program print with argument 3848786505? File: chall_2.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})

Solution

b: Branch. This is the uncoditional branch.
bcc: Branch on Carry Clear. This is the conditional branch.
Note that the wzr register is equivalent to 0. The instruction str wzr, [sp, 24] zeros out the content of [sp+24].
Here [sp+24] is the result and [sp+28] is the counter. The loop keeps increment [sp+24] by 3 and compares the counter [sp+28] with 3848786505. In the end, the result [sp+24] is printed out. In other word, the program computes 3848786505 * 3 = 11546359515, which is 0x2b03776db in hex. Since the flag requires 32-bit hex, this hex number is truncated as 0xb03776db.

Flag

1
picoCTF{b03776db}
Copied!

Hurry up! Wait!

Solved by: ret2basic

Challenge

Solution

Each function call prints out a character:
Pseudocode

Flag

1
picoCTF{d15a5m_ftw_dfbdc5d}
Copied!

gogo

Solved by:

Challenge

Hmmm this is a weird file... enter_password. There is a instance of the service running at mercury.picoctf.net:35862.

Solution

Flag

1
Copied!

ARMssembly 3

Solved by: ret2basic

Challenge

What integer does this program print with argument 3350728462? File: chall_3.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})

Assembly with Comments

1
.arch armv8-a
2
.file "chall_3.c"
3
.text
4
.align 2
5
.global func1
6
.type func1, %function
7
func1:
8
stp x29, x30, [sp, -48]! @ push x29 and x30 onto the stack
9
add x29, sp, 0 @ x29 = sp + 0 = sp
10
str w0, [x29, 28] @ [x29+28] = w0 = 3350728462
11
str wzr, [x29, 44] @ [x29+44] = wzr = 0
12
b .L2 @ branch to .L2 unconditionally
13
.L4:
14
ldr w0, [x29, 28] @ w0 = [x29+28]
15
and w0, w0, 1 @ w0 &= 1 => => w0 = 1 if all bits of w0 are 1, w0 = 0 otherwise
16
cmp w0, 0 @ compare w0 and 0
17
beq .L3 @ branch to .L3 if w0 == 0
18
ldr w0, [x29, 44] @ w0 = [x29+44]
19
bl func2 @ branch to func2
20
str w0, [x29, 44] @ [x29+44] = w0
21
.L3:
22
ldr w0, [x29, 28] @ w0 = [x29+28]
23
lsr w0, w0, 1 @ w0 >> 1
24
str w0, [x29, 28] @ [x29+28] = w0
25
.L2:
26
ldr w0, [x29, 28] @ w0 = [x29+28]
27
cmp w0, 0 @ compare w0 and 0 => compare [x29+28] and 0
28
bne .L4 @ if [x29+28] != 0, branch to .L4
29
ldr w0, [x29, 44] @ w0 = [x29+44]
30
ldp x29, x30, [sp], 48
31
ret
32
.size func1, .-func1
33
.align 2
34
.global func2
35
.type func2, %function
36
func2:
37
sub sp, sp, #16 @ allocate 16 bytes on the stack
38
str w0, [sp, 12] @ [sp+12] = w0
39
ldr w0, [sp, 12] @ w0 = [sp+12]
40
add w0, w0, 3 @ w0 += 3
41
add sp, sp, 16
42
ret
43
.size func2, .-func2
44
.section .rodata
45
.align 3
46
.LC0:
47
.string "Result: %ld\n"
48
.text
49
.align 2
50
.global main
51
.type main, %function
52
main:
53
stp x29, x30, [sp, -48]!
54
add x29, sp, 0
55
str w0, [x29, 28]
56
str x1, [x29, 16]
57
ldr x0, [x29, 16]
58
add x0, x0, 8
59
ldr x0, [x0]
60
bl atoi
61
bl func1
62
str w0, [x29, 44]
63
adrp x0, .LC0
64
add x0, x0, :lo12:.LC0
65
ldr w1, [x29, 44]
66
bl printf
67
nop
68
ldp x29, x30, [sp], 48
69
ret
70
.size main, .-main
71
.ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
72
.section .note.GNU-stack,"",@progbits
Copied!

Solution

stp: Store Pair.
bl: Branch with Link.
lsr: Logical Shift Right.
The program computes and w0, w0, 1, where w0 is the argument. If the w0 & 1 = 1, it increments the counter by 3. Otherwise, it does nothing and continues. After each round of testing, the program divides w0 by 2 and repeats this test until w0 = 0.

Implementation

1
#!/usr/bin/env python3
2
3
target = 3350728462
4
5
result = 0
6
while target != 0:
7
if target & 1 != 0:
8
result += 3
9
target >>= 1
10
11
print(hex(result))
Copied!

Flag

1
picoCTF{00000030}
Copied!

Let's get dynamic

Solved by: ret2basic

Challenge

Can you tell what this file is reading? chall.S

Solution

Compile the assembly code:
1
$ gcc -c chall.S -o chall.o
2
$ gcc chall.o -o chall
Copied!
Disassemble the main function:
1
pwndbg> disass main
Copied!
PIE
Since PIE is enabled, all the addresses here are just offsets. We need to run the program for the correct addresses to load:
1
pwndbg> r
2
...
3
pwndbg> disass main
Copied!
main
The memcmp function compares our input with the flag. Set a breakpoint on memcmp and run the program again:
1
pwndbg> b *0x00005555555552f6
2
pwndbg> r
Copied!
The flag is located in RSI at this moment:
flag

Flag

1
picoCTF{dyn4m1c_4n4ly1s_1s_5up3r_us3ful_56e35b54}
Copied!

Easy as GDB

Solved by: ret2basic

Challenge

The flag has got to be checked somewhere... File: brute

Solution

Take a look at the pseudocode:
strncpy()
Here unk_2008 is the encrypted flag:
Ecrypted flag
This is a nice use case for the angr template. What we have to do here is:
    1.
    Figure out the flag length
    2.
    Find the address of the "Correct!" state
    3.
    Find the address of the "Incorrect." state
The length of the encrypted flag is 30, so the flag in clear should be 30-byte long as well.
The call puts instruction for "Correct!":
Correct
The call puts instruction for "Incorrect.":
Incorrect

Implementation

1
#!/usr/bin/env python3
2
import angr
3
import claripy
4
5
FLAG_LEN = 30
6
STDIN_FD = 0
7
8
base_addr = 0x100000 # To match addresses to Ghidra
9
10
proj = angr.Project("brute", main_opts={'base_addr': base_addr})
11
12
flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(FLAG_LEN)]
13
flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) # Add \n for scanf() to accept the input
14
15
state = proj.factory.full_init_state(
16
args=['brute'],
17
add_options=angr.options.unicorn,
18
stdin=flag,
19
)
20
21
# Add constraints that all characters are printable
22
for k in flag_chars:
23
state.solver.add(k >= ord('!'))
24
state.solver.add(k <= ord('~'))
25
26
simgr = proj.factory.simulation_manager(state)
27
find_addr = 0x100a72 # the address of "call puts" for SUCCESS
28
avoid_addr = 0x100a86 # the address of "call puts" for FAILURE
29
simgr.explore(find=find_addr, avoid=avoid_addr)
30
31
if (len(simgr.found) > 0):
32
for found in simgr.found:
33
print(found.posix.dumps(STDIN_FD))
Copied!
Run this script in docker:
1
$ docker run -it angr/angr
Copied!
The script takes some time to finish. Be patient.

Flag

1
picoCTF{I_5D3_A11DA7_e5458cbf}
Copied!

ARMssembly 4

Solved by: ret2basic

Challenge

What integer does this program print with argument 3964545182? File: chall_4.S Flag format: picoCTF{XXXXXXXX} -> (hex, lowercase, no 0x, and 32 bits. ex. 5614267 would be picoCTF{0055aabb})

Assembly with Comments

1
.arch armv8-a
2
.file "chall_4.c"
3
.text
4
.align 2
5
.global func1
6
.type func1, %function
7
func1:
8
stp x29, x30, [sp, -32]!
9
add x29, sp, 0
10
str w0, [x29, 28]
11
ldr w0, [x29, 28]
12
cmp w0, 100
13
bls .L2 @ if w0 <= 100, branch to .L2
14
ldr w0, [x29, 28] @ w0 = [x29+28]
15
add w0, w0, 100 @ w0 += 100
16
bl func2 @ branch to fun2
17
b .L3 @ branch to .L3 unconditionally
18
.L2:
19
ldr w0, [x29, 28]
20
bl func3 @ branch to func3
21
.L3:
22
ldp x29, x30, [sp], 32
23
ret
24
.size func1, .-func1
25
.align 2
26
.global func2
27
.type func2, %function
28
func2:
29
stp x29, x30, [sp, -32]!
30
add x29, sp, 0
31
str w0, [x29, 28]
32
ldr w0, [x29, 28]
33
cmp w0, 499
34
bhi .L5 @ branch to .L5 if w0 > 499
35
ldr w0, [x29, 28]
36
sub w0, w0, #86
37
bl func4 @ branch to func4
38
b .L6 @ branch to .L6 unconditionally
39
.L5:
40
ldr w0, [x29, 28]
41
add w0, w0, 13 @ w0 += 13
42
bl func5 @ branch to func5
43
.L6:
44
ldp x29, x30, [sp], 32
45
ret
46
.size func2, .-func2
47
.align 2
48
.global func3
49
.type func3, %function
50
func3:
51
stp x29, x30, [sp, -32]!
52
add x29, sp, 0
53
str w0, [x29, 28]
54
ldr w0, [x29, 28]
55
bl func7 @ branch to func7
56
ldp x29, x30, [sp], 32
57
ret
58
.size func3, .-func3
59
.align 2
60
.global func4
61
.type func4, %function
62
func4:
63
stp x29, x30, [sp, -48]!
64
add x29, sp, 0
65
str w0, [x29, 28]
66
mov w0, 17 @ w0 = 17
67
str w0, [x29, 44]
68
ldr w0, [x29, 44]
69
bl func1 @ branch to func1
70
str w0, [x29, 44]
71
ldr w0, [x29, 28]
72
ldp x29, x30, [sp], 48
73
ret
74
.size func4, .-func4
75
.align 2
76
.global func5
77
.type func5, %function
78
func5:
79
stp x29, x30, [sp, -32]!
80
add x29, sp, 0
81
str w0, [x29, 28]
82
ldr w0, [x29, 28]
83
bl func8 @ branch to func8
84
str w0, [x29, 28]
85
ldr w0, [x29, 28]
86
ldp x29, x30, [sp], 32
87
ret
88
.size func5, .-func5
89
.align 2
90
.global func6
91
.type func6, %function
92
func6:
93
sub sp, sp, #32
94
str w0, [sp, 12]
95
mov w0, 314 @ w0 = 314
96
str w0, [sp, 24] @ [sp+24] = w0 = 314
97
mov w0, 1932 @ w0 = 1932
98
str w0, [sp, 28] @ [sp+28] = w0
99
str wzr, [sp, 20] @ [sp+20] = 0
100
str wzr, [sp, 20]
101
b .L14 @ branch to .L14
102
.L15:
103
ldr w1, [sp, 28] @ w1 = [sp+28]
104
mov w0, 800 @ w0 = 800
105
mul w0, w1, w0 @ w0 *= w1
106
ldr w1, [sp, 24] @ w1 = [sp+24]
107
udiv w2, w0, w1 @ w2 = w0 // w1
108
ldr w1, [sp, 24] @ w1 = [sp+24]
109
mul w1, w2, w1 @ w1 *= w2
110
sub w0, w0, w1 @ w0 -= w1
111
str w0, [sp, 12] @ [sp+12] = w0
112
ldr w0, [sp, 20] @ w0 = [sp+20]
113
add w0, w0, 1 @ w0 += 1
114
str w0, [sp, 20] @ [sp+20] = w0
115
.L14:
116
ldr w0, [sp, 20]
117
cmp w0, 899
118
bls .L15 @ branch to .L15 if w0 <= 899
119
ldr w0, [sp, 12]
120
add sp, sp, 32
121
ret
122
.size func6, .-func6
123
.align 2
124
.global func7
125
.type func7, %function
126
func7:
127
sub sp, sp, #16
128
str w0, [sp, 12]
129
ldr w0, [sp, 12]
130
cmp w0, 100
131
bls .L18 @ branch to .L18 if w0 <= 100
132
ldr w0, [sp, 12]
133
b .L19 @ branch to .L19 unconditionally
134
.L18:
135
mov w0, 7 @ w0 = 7
136
.L19:
137
add sp, sp, 16
138
ret
139
.size func7, .-func7
140
.align 2
141
.global func8
142
.type func8, %function
143
func8:
144
sub sp, sp, #16
145
str w0, [sp, 12]
146
ldr w0, [sp, 12]
147
add w0, w0, 2 @ w0 += 2
148
add sp, sp, 16
149
ret
150
.size func8, .-func8
151
.section .rodata
152
.align 3
153
.LC0:
154
.string "Result: %ld\n"
155
.text
156
.align 2
157
.global main
158
.type main, %function
159
main:
160
stp x29, x30, [sp, -48]!
161
add x29, sp, 0
162
str w0, [x29, 28]
163
str x1, [x29, 16]
164
ldr x0, [x29, 16]
165
add x0, x0, 8
166
ldr x0, [x0]
167
bl atoi
168
str w0, [x29, 44]
169
ldr w0, [x29, 44]
170
bl func1
171
mov w1, w0
172
adrp x0, .LC0
173
add x0, x0, :lo12:.LC0
174
bl printf
175
nop
176
ldp x29, x30, [sp], 48
177
ret
178
.size main, .-main
179
.ident "GCC: (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0"
180
.section .note.GNU-stack,"",@progbits
Copied!

Solution

bhi: Branch on Higher than.
Here is my note:
1
arg = 3964545182
2
3
1. func1: 3964545182 + 100 = 3964545282
4
2. func2: 3964545282 + 13 = 3964545295
5
3. func5: do nothing
6
4. func8: 3964545295 + 2 = 3964545297
7
5. func1: do nothing
8
6. func3: do nothing
9
7. func7: do nothing
10
11
result = 3964545297 = 0xec4e2911
Copied!

Flag

1
picoCTF{ec4e2911}
Copied!

Powershelly

Solved by:

Challenge

It's not a bad idea to learn to read Powershell. We give you the output, but do you think you can find the input? rev_PS.ps1 output.txt

Solution

Todo!

Flag

1
Copied!

Rolling My Own

Solved by:

Challenge

I don't trust password checkers made by other people, so I wrote my own. It doesn't even need to store the password! If you can crack it I'll give you a flag. remote nc mercury.picoctf.net 17615

Solution

Todo!

Flag

1
Copied!

Checkpass

Solved by:

Challenge

What is the password? File: checkpass Flag format: picoCTF{...}

Solution

Todo!

Flag

1
Copied!
Last modified 6mo ago