8 minutes
redpwn 2020 | RE Writeups
ropes 128pts
Description:
It's not just a string, it's a rope!
File:
ropes
Author:
NotDeGhost
on this challenge we were given Mach-O binary file ropes.
❯ file ropes
ropes: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>
to solve the first challenge is not too difficult, we can use the strings
command to find interesting strings that we might be able to see the flag.
❯ strings ropes
...
/usr/lib/libSystem.B.dylib
Give me a magic number:
First part is: flag{r0pes_ar3_
Second part is: just_l0ng_str1ngs}
@dyld_stub_binder
@_printf
...
FLAG : flag{r0pes_ar3_just_l0ng_str1ngs}
bubbly 395pts
Description:
It never ends
nc 2020.redpwnc.tf 31039
File:
bubbly
Author:
dns
At the challenge we are given binary files bubbly
❯ file bubbly
bubbly: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=edb56d2d9355bcee01909f171d8a272a3e82d053, with debug_info, not stripped
The following is a pseudocode snippet from the bubbly program, as we see there are variable array nums
and there are repeats, which are intended to move each element position to array nums
and there is a check()
function, this function is useful for checking each element on Array nums
whether the element in the array nums
is sorted, if the element array nums
is already passed the check ()
function returns the value 0 == True
if it does not return the value 1 == False
.
...
.data:0000000000004060 nums dd 1, 10, 3, 2, 5, 9, 8, 7, 4, 6
...
puts("I hate my data structures class! Why can't I just sort by hand?");
for ( pass = 0; ; pass = check() )
{
unused = __isoc99_scanf("%d", &i);
if ( i > 8 )
break;
nums[i] ^= nums[i + 1];
nums[i + 1] ^= nums[i];
nums[i] ^= nums[i + 1];
}
...
BOOL8 __fastcall check()
{
uint32_t i; // [rsp+0h] [rbp-8h]
bool pass; // [rsp+7h] [rbp-1h]
pass = 1;
for ( i = 0; i <= 8; ++i )
{
if ( nums[i] > nums[i + 1] )
return 0;
}
return pass;
}
To solve this challenge I use hackerearth to make it easier to solve the challenge. After getting a value to sort the array of nums, enter a value greater than 8 to exit the loop.
❯ ./connect.sh
I hate my data structures class! Why can't I just sort by hand?
1
2
3
4
5
6
7
8
1
4
5
6
7
4
5
6
4
5
3
9
Well done!
flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}
FLAG : flag{4ft3r_y0u_put_u54c0_0n_y0ur_c011ege_4pp5_y0u_5t1ll_h4ve_t0_d0_th15_57uff}
SMarT-solver 475pts
Description:
Find the correct flag. :)
NOTE: All letters in the flag are lowercase
File:
SMarT-solver
Author:
MrSlick
In the following challenges we are given a binary file SMarT-solver.
❯ file SMarT-solver
SMarT-solver: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=27bf1ae8e39bad973a605ab44e3b36a64e2134c6, not stripped
If you are familiar with the challenge of reversing, maybe we will get to know what we should do next. If you don’t understand, let me explain briefly. If we pay attention i think they wants to try saying “SMT-solver”, so we need to prepare our z3 already installed to help us solve this challenge and we are also told that All letters in the flag are lowercase. Let’s look deeper to understand how the binary works.
...
90d: 48 8d 85 e0 fe ff ff lea rax,[rbp-0x120] <-----------+
914: 48 89 c7 mov rdi,rax |
917: e8 c4 fd ff ff call 6e0 <strlen@plt> |
91c: 48 83 f8 48 cmp rax,0x48 <---------------+---> compare input length with 0x48 / 72
920: 0f 86 9c b0 01 00 jbe 1b9c2 <main+0x1b168>
926: 0f b6 95 e0 fe ff ff movzx edx,BYTE PTR [rbp-0x120] <---+
92d: 0f b6 85 e1 fe ff ff movzx eax,BYTE PTR [rbp-0x11f] <---|
934: 38 c2 cmp dl,al <---------------|
936: 0f 83 8c b0 01 00 jae 1b9c8 <main+0x1b16e> |
93c: 0f b6 95 e0 fe ff ff movzx edx,BYTE PTR [rbp-0x120] <---|
943: 0f b6 85 e2 fe ff ff movzx eax,BYTE PTR [rbp-0x11e] <---|
94a: 38 c2 cmp dl,al <---------------+---> compare each character in our input
94c: 0f 86 7c b0 01 00 jbe 1b9ce <main+0x1b174> |
952: 0f b6 95 e0 fe ff ff movzx edx,BYTE PTR [rbp-0x120] <---|
959: 0f b6 85 e3 fe ff ff movzx eax,BYTE PTR [rbp-0x11d] <---|
960: 38 c2 cmp dl,al <---------------|
962: 0f 83 6c b0 01 00 jae 1b9d4 <main+0x1b17a> |
...
After a few minutes doing static analysis it can be concluded that the flag length is 72 characters and that each character is compared to each other. The next step is to take the assembly code and clean it to make the code look clearer. After that, let’s create a script to complete this challenge. Visit my github to see my solver code
❯ python solver.py
flag{thequickbrownfoxjumpedoverthelazydogandlearnedhowtoautomateanalysis}
❯ python solver.py | ./SMarT-solver
Welcome to SMarT solver!
The #1 solution for your flag checking needs.
Enter a flag:
Correct input!
FLAG : flag{thequickbrownfoxjumpedoverthelazydogandlearnedhowtoautomateanalysis}
a-round-mechanism 495pts
Description:
I found a respectable mainframe, can you help me get in? Flag is in flag.txt
nc 2020.redpwnc.tf 31359
File:
ARM
Author:
green beans
In this challenge we are given a 32-bit ARM stripped binary file
❯ file ARM
ARM: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=714b6b1a1949f1f0d3912e7e13fef4420e2d4efa, stripped
After spending several hours doing static analysis I found a way to solve this challenge. As you can see here is a program flow where the length of the input must be 0x16 / 22 characters, the next step is that each character will be xor with 0x12 / 18.
...
.data:00086064 LDR R2, =loc_86008 <-------- Our input is stored at loc_86008
.data:00086068 MOV R0, #0 <---------+
.data:0008606C MOV R1, #0x16 <---------+-- Prepare looping 22 times
.data:00086070 loc_86070 ; CODE XREF: .data:00086090↓j
.data:00086070 LDRB R3, [R2,R0] <-----------+
.data:00086074 MOV R4, R3 |
.data:00086078 EOR R4, R4, #0x12 <---------+-- Each character will be xor with 18
.data:0008607C STRB R4, [R2,R0]
.data:00086080 CMP R3, #0xA
.data:00086084 BLEQ loc_163BC
.data:00086088 ADD R0, R0, #1
.data:0008608C CMP R0, R1 <--------+
.data:00086090 BLE loc_86070 <------+-- Return to loc_86070 if R0 is still smaller than R1
...
Then the sub_860EC function will be called and the value 1 and our input as parameters. The essence of the sub_860EC function every two characters from our input will be shifted left and shifted right once. After that the two results will be added up then the result is shifted right 7 times and subtracted by 1. This will be repeated 22 times.
...
.data:00086094 LDR R0, =loc_86008 <-----+
.data:00086098 MOV R1, #1 |
.data:0008609C BL sub_860EC <----------+-- sub_860EC(R0, R1)
...
.data:000860EC sub_860EC ; CODE XREF: .data:0008609C↑p
.data:000860EC ; sub_860EC+70↓p
.data:000860EC PUSH {LR}
.data:000860F0 PUSH {R12}
.data:000860F4 PUSH {R0}
.data:000860F8 PUSH {R1}
.data:000860FC SUB SP, SP, #8
.data:00086100 MOV R12, SP
.data:00086104 ADDLT R1, R1, #1
.data:00086108 CMP R1, #0x16 <-----+
.data:0008610C BNE loc_86118 <-----+-- Jump to loc_86118 if R1 not Equal 0x16 / 22
.data:00086110 MOV R0, #1
.data:00086114 B loc_86160 <----- exit from function sub_860EC
.data:00086118 ; ---------------------------------------------------------------------------
.data:00086118
.data:00086118 loc_86118 ; CODE XREF: sub_860EC+20↑j
.data:00086118 MOV R6, R0 <--------------- Our input is moved to R6 from R0 in parameter 1
.data:0008611C MOV R8, R1 <----------+
.data:00086120 LDRB R9, [R6,R8] <------+ R9 = R6[R8] Take the next character from our input
.data:00086124 MOV R10, R9
.data:00086128 SUB R5, R8, #1 <--------+ R8 is subtracted 1 to retrieve the previous character
.data:0008612C LDRB R12, [R6,R5] <------+ R12 = R6[R5]
.data:00086130 MOV R5, R12
.data:00086134 MOV R5, R5,LSR#1 <------+ LSR (Logical Shift Right) R5 = (R5 >> 1)
.data:00086138 MOV R10, R10,LSL#1 <-----+ LSL (Logical Shift Left) R10 = (R10 << 1)
.data:0008613C ADD R7, R5, R10 <--------+ R7 = (R5 + R10)
.data:00086140 MOV R10, R7
.data:00086144 MOV R7, R7,LSR#7 <------+ R7 = (R7 >> 7)
.data:00086148 MOV R10, R10,LSR R7 |
.data:0008614C SUB R10, R10, #1 <-------+ R10 = (R7 >> (R10 >> R7)) - 1
.data:00086150 STRB R10, [R6,R8] <----------- R6[R8] = R10
.data:00086154 LDR R0, =loc_86008 <-----+
.data:00086158 MOV R1, R8 |
.data:0008615C BL sub_860EC <----------+-- sub_860EC(R0, R1)
.data:00086160
.data:00086160 loc_86160 ; CODE XREF: sub_860EC+28↑j
.data:00086160 ADD SP, SP, #8
.data:00086164 POP {R1}
.data:00086168 POP {R0}
.data:0008616C POP {R12}
.data:00086170 POP {PC}
...
Last but not least the results of our input will be compared with te@B}efFk~{^Ixv@}y\\BC4
Because this program is ‘little enddian’ it should look like this 4CB\\y}@vxI^{~kFfe}B@et
.
...
.data:000860A0 LDR R2, =loc_86008
.data:000860A4 LDR R3, =aTeBEffkIxvYBc4 ; "te@B}efFk~{^Ixv@}y\\BC4"
...
The following is the output of my solver. Visit my github to see my solver code.
❯ python3 solver.py
Know 1st char : 4
Restore 2nd char: C
- possibility : 7
- possibility : {
- possibility : |
-----------------------------------
Result - 7 : 473Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &%!_q3quNd_ws_fD_wu#DN
-----------------------------------
Result - { : 4{3Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &i!_q3quNd_ws_fD_wu#DN
-----------------------------------
Result - | : 4|3Mc!cg\vMeaMtVMeg1V\
Compare key : True
Key found : &n!_q3quNd_ws_fD_wu#DN
I tried all three keys which I found all worked well.
❯ ./connect.sh
I hear you've come to bargain for flags
I'm a reasonable machine, if you guess the password I can give you a flag
&%!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag: cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}
❯ ./connect.sh
I hear you've come to bargain for flags
I'm a reasonable machine, if you guess the password I can give you a flag
&i!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag: cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}
❯ ./connect.sh
I hear you've come to bargain for flags
I'm a reasonable machine, if you guess the password I can give you a flag
&n!_q3quNd_ws_fD_wu#DN
Nice, you did it! Have your flag: cat flag.txt
flag{4_r3gu14R_m0N5tr051Ty}
FLAG : flag{4_r3gu14R_m0N5tr051Ty}