Reverse Engineering Writeup
Table of Contents
- vault-door-training - Points: 50
- Your mission is to enter Dr. Evil's laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault's computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java
import java.util.*;
class VaultDoorTraining {
public static void main(String args[]) {
VaultDoorTraining vaultDoor = new VaultDoorTraining();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
}
else {
System.out.println("Access denied!");
}
}
}
// The password is below. Is it safe to put the password in the source code?
// What if somebody stole our source code? Then they would know what our
// password is. Hmm... I will think of some ways to improve the security
// on the other doors.
//
// -Minion #9567
public boolean checkPassword(String password) {
return password.equals("w4rm1ng_Up_w1tH_jAv4_3b500738c12");
}
}
Hint: The password is revealed in the program's source code.
$ cat VaultDoorTraining.java
picoCTF{w4rm1ng_Up_w1tH_jAv4_3b500738c12}
- vault-door-1 - Points: 100
- This vault uses some complicated arrays! I hope you can make sense of it, special agent. The source code for this vault is here: VaultDoor1.java
import java.util.*;
class VaultDoor1 {
public static void main(String args[]) {
VaultDoor1 vaultDoor = new VaultDoor1();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
}
// I came up with a more secure way to check the password without putting
// the password itself in the source code. I think this is going to be
// UNHACKABLE!! I hope Dr. Evil agrees...
//
// -Minion #8728
public boolean checkPassword(String password) {
return password.length() == 32 &&
password.charAt(0) == 'd' &&
password.charAt(29) == 'f' &&
password.charAt(4) == 'r' &&
password.charAt(2) == '5' &&
password.charAt(23) == 'r' &&
password.charAt(3) == 'c' &&
password.charAt(17) == '4' &&
password.charAt(1) == '3' &&
password.charAt(7) == 'b' &&
password.charAt(10) == '_' &&
password.charAt(5) == '4' &&
password.charAt(9) == '3' &&
password.charAt(11) == 't' &&
password.charAt(15) == 'c' &&
password.charAt(8) == 'l' &&
password.charAt(12) == 'H' &&
password.charAt(20) == 'c' &&
password.charAt(14) == '_' &&
password.charAt(6) == 'm' &&
password.charAt(24) == '5' &&
password.charAt(18) == 'r' &&
password.charAt(13) == '3' &&
password.charAt(19) == '4' &&
password.charAt(21) == 'T' &&
password.charAt(16) == 'H' &&
password.charAt(27) == '3' &&
password.charAt(30) == '3' &&
password.charAt(25) == '_' &&
password.charAt(22) == '3' &&
password.charAt(28) == 'e' &&
password.charAt(26) == '6' &&
password.charAt(31) == 'a';
}
}
Hint: Look up the charAt() method online.
- Below a python script that solve the challenge
myPass = [None] * 32
myPass[0] = 'd'
myPass[29] = 'f'
myPass[4] = 'r'
myPass[2] = '5'
myPass[23] = 'r'
myPass[3] = 'c'
myPass[17] = '4'
myPass[1] = '3'
myPass[7] = 'b'
myPass[10] = '_'
myPass[5] = '4'
myPass[9] = '3'
myPass[11] = 't'
myPass[15] = 'c'
myPass[8] = 'l'
myPass[12] = 'H'
myPass[20] = 'c'
myPass[14] = '_'
myPass[6] = 'm'
myPass[24] = '5'
myPass[18] = 'r'
myPass[13] = '3'
myPass[19] = '4'
myPass[21] = 'T'
myPass[16] = 'H'
myPass[27] = '3'
myPass[30] = '3'
myPass[25] = '_'
myPass[22] = '3'
myPass[28] = 'e'
myPass[26] = '6'
myPass[31] = 'a'
print("picoCTF{{{}}}".format(''.join(myPass)))
picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_63ef3a}
- vault-door-3 - Points: 200
- This vault uses for-loops and byte arrays. The source code for this vault is here: VaultDoor3.java
import java.util.*;
class VaultDoor3 {
public static void main(String args[]) {
VaultDoor3 vaultDoor = new VaultDoor3();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
}
// Our security monitoring team has noticed some intrusions on some of the
// less secure doors. Dr. Evil has asked me specifically to build a stronger
// vault door to protect his Doomsday plans. I just *know* this door will
// keep all of those nosy agents out of our business. Mwa ha!
//
// -Minion #2671
public boolean checkPassword(String password) {
if (password.length() != 32) {
return false;
}
char[] buffer = new char[32];
int i;
for (i=0; i<8; i++) {
buffer[i] = password.charAt(i);
}
for (; i<16; i++) {
buffer[i] = password.charAt(23-i);
}
for (; i<32; i+=2) {
buffer[i] = password.charAt(46-i);
}
for (i=31; i>=17; i-=2) {
buffer[i] = password.charAt(i);
}
String s = new String(buffer);
return s.equals("jU5t_a_sna_3lpm1dg347_u_4_mfr54b");
}
}
Hint: Make a table that contains each value of the loop variables and the corresponding buffer index that it writes to.
- Below a python script that solve the challenge
buffer = [None] * 32
password = 'jU5t_a_sna_3lpm1dg347_u_4_mfr54b'
for i in range(0,8):
buffer[i] = password[i]
for i in range(8,16):
buffer[i] = password[23-i]
for i in range(16,32,2):
buffer[i] = password[46-i]
for i in range(31,16,-2):
buffer[i] = password[i]
print("picoCTF{{{}}}".format(''.join(buffer)))
picoCTF{jU5t_a_s1mpl3_an4gr4m_4_u_7f35db}
- vault-door-4 - Points: 250
- This vault uses ASCII encoding for the password. The source code for this vault is here: VaultDoor4.java
import java.util.*;
class VaultDoor4 {
public static void main(String args[]) {
VaultDoor4 vaultDoor = new VaultDoor4();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
}
// I made myself dizzy converting all of these numbers into different bases,
// so I just *know* that this vault will be impenetrable. This will make Dr.
// Evil like me better than all of the other minions--especially Minion
// #5620--I just know it!
//
// .:::. .:::.
// :::::::.:::::::
// :::::::::::::::
// ':::::::::::::'
// ':::::::::'
// ':::::'
// ':'
// -Minion #7781
public boolean checkPassword(String password) {
byte[] passBytes = password.getBytes();
byte[] myBytes = {
106 , 85 , 53 , 116 , 95 , 52 , 95 , 98 ,
0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
0142, 0131, 0164, 063 , 0163, 0137, 070 , 060 ,
'f' , '8' , 'e' , '1' , 'e' , '0' , '4' , '7' ,
};
for (int i=0; i<32; i++) {
if (passBytes[i] != myBytes[i]) {
return false;
}
}
return true;
}
}
Hint: Use a search engine to find an "ASCII table"
Hint: You will also need to know the difference between octal, decimal, and hexademical numbers
- Below a python script that solve the challenge
passBytes = [None] * 32
myBytes = [
106 , 85 , 53 , 116 , 95 , 52 , 95 , 98 ,
'0x55', '0x6e', '0x43', '0x68', '0x5f', '0x30', '0x66', '0x5f',
'0o142', '0o131', '0o164', '0o63' , '0o163', '0o137', '0o70' , '0o60' ,
'f' , '8' , 'e' , '1' , 'e' , '0' , '4' , '7' ,
]
# base10
for i in range(0,8):
passBytes[i] = chr(myBytes[i])
# base16
for i in range(8,16):
#passBytes[i] = bytearray.fromhex(myBytes[i].replace('0x', '')).decode()
passBytes[i] = chr(int(myBytes[i], 16))
# base8
for i in range(16,24):
passBytes[i] = chr(int(myBytes[i], 8))
for i in range(24,32):
passBytes[i] = myBytes[i]
print("picoCTF{{{}}}".format(''.join(passBytes)))
picoCTF{jU5t_4_bUnCh_0f_bYt3s_80f8e1e047}
- vault-door-5 - Points: 300
- In the last challenge, you mastered octal (base 8), decimal (base 10), and hexadecimal (base 16) numbers, but this vault door uses a different change of base as well as URL encoding! The source code for this vault is here: VaultDoor5.java
import java.net.URLDecoder;
import java.util.*;
class VaultDoor5 {
public static void main(String args[]) {
VaultDoor5 vaultDoor = new VaultDoor5();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
// Minion #7781 used base 8 and base 16, but this is base 64, which is
// like... eight times stronger, right? Riiigghtt? Well that's what my twin
// brother Minion #2415 says, anyway.
//
// -Minion #2414
public String base64Encode(byte[] input) {
return Base64.getEncoder().encodeToString(input);
}
// URL encoding is meant for web pages, so any double agent spies who steal
// our source code will think this is a web site or something, defintely not
// vault door! Oh wait, should I have not said that in a source code
// comment?
//
// -Minion #2415
public String urlEncode(byte[] input) {
StringBuffer buf = new StringBuffer();
for (int i=0; i<input.length; i++) {
buf.append(String.format("%%%2x", input[i]));
}
return buf.toString();
}
public boolean checkPassword(String password) {
String urlEncoded = urlEncode(password.getBytes());
String base64Encoded = base64Encode(urlEncoded.getBytes());
String expected = "JTYzJTMwJTZlJTc2JTMzJTcyJTc0JTMxJTZlJTY3JTVm"
+ "JTY2JTcyJTMwJTZkJTVmJTYyJTYxJTM1JTY1JTVmJTM2"
+ "JTM0JTVmJTYzJTMxJTM0JTYzJTYzJTY1JTMxJTMx";
return base64Encoded.equals(expected);
}
}
Hint: You may find an encoder/decoder tool helpful, such as https://encoding.tools/
Hint: Read the wikipedia articles on URL encoding and base 64 encoding to understand how they work and what the results look like.
- Below a python script that solve the challenge
import base64
encoded = 'JTYzJTMwJTZlJTc2JTMzJTcyJTc0JTMxJTZlJTY3JTVmJTY2JTcyJTMwJTZkJTVmJTYyJTYxJTM1JTY1JTVmJTM2JTM0JTVmJTYzJTMxJTM0JTYzJTYzJTY1JTMxJTMx'
data = base64.b64decode(encoded).decode('utf-8')
print(data)
data = data.replace('%', ' 0x')
print(data)
ch = data.split(" ")
print(ch)
print('picoCTF{', end = '')
for c in ch:
if(c != ''):
print(chr(int(c, 16)), end = '')
print('}\n', end = '')
picoCTF{c0nv3rt1ng_fr0m_ba5e_64_c14cce11}
- vault-door-6 - Points: 350
- This vault uses an XOR encryption scheme. The source code for this vault is here: VaultDoor6.java
import java.util.*;
class VaultDoor6 {
public static void main(String args[]) {
VaultDoor6 vaultDoor = new VaultDoor6();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
// Dr. Evil gave me a book called Applied Cryptography by Bruce Schneier,
// and I learned this really cool encryption system. This will be the
// strongest vault door in Dr. Evil's entire evil volcano compound for sure!
// Well, I didn't exactly read the *whole* book, but I'm sure there's
// nothing important in the last 750 pages.
//
// -Minion #3091
public boolean checkPassword(String password) {
if (password.length() != 32) {
return false;
}
byte[] passBytes = password.getBytes();
byte[] myBytes = {
0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d,
0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa ,
0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27,
0xa , 0x31, 0x30, 0x30, 0x30, 0x64, 0x61, 0x33,
};
for (int i=0; i<32; i++) {
if (((passBytes[i] ^ 0x55) - myBytes[i]) != 0) {
return false;
}
}
return true;
}
}
Hint: If X ^ Y = Z, then Z ^ Y = X. Write a program that decrypts the flag based on this fact.
- Below a python script that solve the challenge
passBytes = [None] * 32
myBytes = [
0x3b, 0x65, 0x21, 0xa , 0x38, 0x0 , 0x36, 0x1d,
0xa , 0x3d, 0x61, 0x27, 0x11, 0x66, 0x27, 0xa ,
0x21, 0x1d, 0x61, 0x3b, 0xa , 0x2d, 0x65, 0x27,
0xa , 0x31, 0x30, 0x30, 0x30, 0x64, 0x61, 0x33,
]
for i in range(32):
passBytes[i] = chr(myBytes[i] ^ 0x55)
print("picoCTF{{{}}}".format(''.join(passBytes)))
picoCTF{n0t_mUcH_h4rD3r_tH4n_x0r_deee14f}
- vault-door-7 - Points: 400
- This vault uses bit shifts to convert a password string into an array of integers. Hurry, agent, we are running out of time to stop Dr. Evil's nefarious plans! The source code for this vault is here: VaultDoor7.java
import java.util.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
class VaultDoor7 {
public static void main(String args[]) {
VaultDoor7 vaultDoor = new VaultDoor7();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
// Each character can be represented as a byte value using its
// ASCII encoding. Each byte contains 8 bits, and an int contains
// 32 bits, so we can "pack" 4 bytes into a single int. Here's an
// example: if the hex string is "01ab", then those can be
// represented as the bytes {0x30, 0x31, 0x61, 0x62}. When those
// bytes are represented as binary, they are:
//
// 0x30: 00110000
// 0x31: 00110001
// 0x61: 01100001
// 0x62: 01100010
//
// If we put those 4 binary numbers end to end, we end up with 32
// bits that can be interpreted as an int.
//
// 00110000 00110001 01100001 01100010 -> 808542562
//
// Since 4 chars can be represented as 1 int, the 32 character password can
// be represented as an array of 8 ints.
//
// - Minion #7816
public int[] passwordToIntArray(String hex) {
int[] x = new int[8];
byte[] hexBytes = hex.getBytes();
for (int i=0; i<8; i++) {
x[i] = hexBytes[i*4] << 24
| hexBytes[i*4+1] << 16
| hexBytes[i*4+2] << 8
| hexBytes[i*4+3];
}
return x;
}
public boolean checkPassword(String password) {
if (password.length() != 32) {
return false;
}
int[] x = passwordToIntArray(password);
return x[0] == 1096770097
&& x[1] == 1952395366
&& x[2] == 1600270708
&& x[3] == 1601398833
&& x[4] == 1716808014
&& x[5] == 1734293603
&& x[6] == 959591523
&& x[7] == 842097204;
}
}
Hint: Use a decimal/hexademical converter such as this one: https://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
Hint: You will also need to consult an ASCII table such as this one: https://www.asciitable.com/
- Below a python script that solve the challenge
x =[0] * 8
x[0] = 1096770097
x[1] = 1952395366
x[2] = 1600270708
x[3] = 1601398833
x[4] = 1716808014
x[5] = 1734293603
x[6] = 959591523
x[7] = 842097204
ch = [None] * 4
buffer = ""
for i in range(0,8):
tmp = str(bin(x[i])[2:].zfill(32))
ch[0] = chr(int(hex(int(tmp[:8], 2)), 16))
ch[1] = chr(int(hex(int(tmp[8:16], 2)), 16))
ch[2] = chr(int(hex(int(tmp[16:24], 2)), 16))
ch[3] = chr(int(hex(int(tmp[24:32], 2)), 16))
buffer += ch[0] + ch[1] + ch[2] + ch[3]
print("picoCTF{{{}}}".format(buffer))
picoCTF{A_b1t_0f_b1t_sh1fTiNg_8c924c21b4}
- asm1 - Points: 200
- What does asm1(0x610) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm1_1_95494d904d73b330976420bc1cd763ec.
Hint: assembly conditions (https://www.tutorialspoint.com/assembly_programming/assembly_conditions.htm)
asm1:
<+0>: push ebp
<+1>: mov ebp,esp
<+3>: cmp DWORD PTR [ebp+0x8],0x3b9 ; 953
<+10>: jg 0x50f <asm1+34> ; jump greater
<+12>: cmp DWORD PTR [ebp+0x8],0x1 ; 1
<+16>: jne 0x507 <asm1+26> ; jump not equal
<+18>: mov eax,DWORD PTR [ebp+0x8]
<+21>: add eax,0x11
<+24>: jmp 0x526 <asm1+57>
<+26>: mov eax,DWORD PTR [ebp+0x8] ;
<+29>: sub eax,0x11 ; 17 -> 1569
<+32>: jmp 0x526 <asm1+57> ; jump
<+34>: cmp DWORD PTR [ebp+0x8],0x477
<+41>: jne 0x520 <asm1+51>
<+43>: mov eax,DWORD PTR [ebp+0x8]
<+46>: sub eax,0x11
<+49>: jmp 0x526 <asm1+57>
<+51>: mov eax,DWORD PTR [ebp+0x8]
<+54>: add eax,0x11
<+57>: pop ebp
<+58>: ret ; 1569 -> 0x621
// input 0x610 -> 1552
picoCTF{0x621}
- asm2 - Points: 250
- What does asm2(0x10,0x18) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm2_0_a50f0b17a6f50b50a53305ebd71af535.
Hint: assembly conditions (https://www.tutorialspoint.com/assembly_programming/assembly_conditions.htm)
asm2:
<+0>: push ebp
<+1>: mov ebp,esp ; ebp = esp
<+3>: sub esp,0x10 ; esp - 16
<+6>: mov eax,DWORD PTR [ebp+0xc] ; eax = ebp + 12
<+9>: mov DWORD PTR [ebp-0x4],eax ; [ebp - 4] = eax
<+12>: mov eax,DWORD PTR [ebp+0x8] ; eax = ebp + 8
<+15>: mov DWORD PTR [ebp-0x8],eax ; [ebp - 8] = eax
<+18>: jmp 0x50c <asm2+31>
<+20>: add DWORD PTR [ebp-0x4],0x1 ; [ebp - 4] + 1
<+24>: add DWORD PTR [ebp-0x8],0xcb ; [ebp - 8] + 203
<+31>: cmp DWORD PTR [ebp-0x8],0xb693 ; 46739
<+38>: jle 0x501 <asm2+20> ; jump less equal
<+40>: mov eax,DWORD PTR [ebp-0x4] ; eax = [ebp - 4]
<+43>: leave ; eax = 231+24 = 255 -> 0xff
<+44>: ret
input: 0x10,0x18 -> 16,24
- Otherwise you can use the assembly function as function of a C program in the following way
.intel_syntax noprefix
.global asm2
asm2:
push ebp
mov ebp,esp
sub esp,0x10
mov eax,DWORD PTR [ebp+0xc]
mov DWORD PTR [ebp-0x4],eax
mov eax,DWORD PTR [ebp+0x8]
mov DWORD PTR [ebp-0x8],eax
jmp asm2+31
add DWORD PTR [ebp-0x4],0x1
add DWORD PTR [ebp-0x8],0xcb
cmp DWORD PTR [ebp-0x8],0xb693
jle asm2+20
mov eax,DWORD PTR [ebp-0x4]
leave
ret
#include <stdio.h>
int main() {
printf("Flag: 0x%x\n", asm2(0x10,0x18));
}
all:
gcc -m32 -c asm2.s -o asm2.o -fno-stack-protector -no-pie
gcc -m32 -c solve.c -o solve.o -fno-stack-protector -no-pie
gcc -m32 -o a.out solve.o asm2.o -fno-stack-protector -no-pie
./a.out
clean:
rm a.out *.o
picoCTF{0xff}
- asm3 - Points: 300
- What does asm3(0xc264bd5c,0xb5a06caa,0xad761175) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm3_1_b71abaa5cc92e3f7061f23957206b434.
Hint: more(?) registers (https://wiki.skullsecurity.org/index.php?title=Registers)
asm3:
<+0>: push ebp
<+1>: mov ebp,esp
<+3>: xor eax,eax
<+5>: mov ah,BYTE PTR [ebp+0x9]
<+8>: shl ax,0x10
<+12>: sub al,BYTE PTR [ebp+0xd]
<+15>: add ah,BYTE PTR [ebp+0xf]
<+18>: xor ax,WORD PTR [ebp+0x10]
<+22>: nop
<+23>: pop ebp
<+24>: ret
- As before it's possible to use the assembly function as function of a C program in the following way
.intel_syntax noprefix
.global asm2
asm3:
push ebp
mov ebp,esp
xor eax,eax
mov ah,BYTE PTR [ebp+0x9]
shl ax,0x10
sub al,BYTE PTR [ebp+0xd]
add ah,BYTE PTR [ebp+0xf]
xor ax,WORD PTR [ebp+0x10]
nop
pop ebp
ret
#include <stdio.h>
int main() {
printf("Flag: 0x%x\n", asm3(0xc264bd5c,0xb5a06caa,0xad761175));
}
all:
gcc -m32 -c asm3.s -o asm3.o -fno-stack-protector -no-pie
gcc -m32 -c solve.c -o solve.o -fno-stack-protector -no-pie
gcc -m32 -o a.out solve.o asm3.o -fno-stack-protector -no-pie
./a.out
clean:
rm a.out *.o
picoCTF{0xa4e1}
- asm4 - Points: 400
- What will asm4("picoCTF_c1373") return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/asm4_5_ca12dca0134f6b54a52c905ffc1e5b35.
Hint: Treat the Array argument as a pointer
<+0>: push ebp
<+1>: mov ebp,esp
<+3>: push ebx
<+4>: sub esp,0x10
<+7>: mov DWORD PTR [ebp-0x10],0x247
<+14>: mov DWORD PTR [ebp-0xc],0x0
<+21>: jmp 0x518 <asm4+27>
<+23>: add DWORD PTR [ebp-0xc],0x1
<+27>: mov edx,DWORD PTR [ebp-0xc]
<+30>: mov eax,DWORD PTR [ebp+0x8]
<+33>: add eax,edx
<+35>: movzx eax,BYTE PTR [eax]
<+38>: test al,al
<+40>: jne 0x514 <asm4+23>
<+42>: mov DWORD PTR [ebp-0x8],0x1
<+49>: jmp 0x587 <asm4+138>
<+51>: mov edx,DWORD PTR [ebp-0x8]
<+54>: mov eax,DWORD PTR [ebp+0x8]
<+57>: add eax,edx
<+59>: movzx eax,BYTE PTR [eax]
<+62>: movsx edx,al
<+65>: mov eax,DWORD PTR [ebp-0x8]
<+68>: lea ecx,[eax-0x1]
<+71>: mov eax,DWORD PTR [ebp+0x8]
<+74>: add eax,ecx
<+76>: movzx eax,BYTE PTR [eax]
<+79>: movsx eax,al
<+82>: sub edx,eax
<+84>: mov eax,edx
<+86>: mov edx,eax
<+88>: mov eax,DWORD PTR [ebp-0x10]
<+91>: lea ebx,[edx+eax*1]
<+94>: mov eax,DWORD PTR [ebp-0x8]
<+97>: lea edx,[eax+0x1]
<+100>: mov eax,DWORD PTR [ebp+0x8]
<+103>: add eax,edx
<+105>: movzx eax,BYTE PTR [eax]
<+108>: movsx edx,al
<+111>: mov ecx,DWORD PTR [ebp-0x8]
<+114>: mov eax,DWORD PTR [ebp+0x8]
<+117>: add eax,ecx
<+119>: movzx eax,BYTE PTR [eax]
<+122>: movsx eax,al
<+125>: sub edx,eax
<+127>: mov eax,edx
<+129>: add eax,ebx
<+131>: mov DWORD PTR [ebp-0x10],eax
<+134>: add DWORD PTR [ebp-0x8],0x1
<+138>: mov eax,DWORD PTR [ebp-0xc]
<+141>: sub eax,0x1
<+144>: cmp DWORD PTR [ebp-0x8],eax
<+147>: jl 0x530 <asm4+51>
<+149>: mov eax,DWORD PTR [ebp-0x10]
<+152>: add esp,0x10
<+155>: pop ebx
<+156>: pop ebp
<+157>: ret
- As before it's possible to use the assembly function as function of a C program in the following way
.intel_syntax noprefix
.global asm4
asm4:
push ebp
mov ebp,esp
push ebx
sub esp,0x10
mov DWORD PTR [ebp-0x10],0x247
mov DWORD PTR [ebp-0xc],0x0
jmp asm4+27
add DWORD PTR [ebp-0xc],0x1
mov edx,DWORD PTR [ebp-0xc]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
test al,al
jne asm4+23
mov DWORD PTR [ebp-0x8],0x1
jmp asm4+138
mov edx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov eax,DWORD PTR [ebp-0x8]
lea ecx,[eax-0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
mov edx,eax
mov eax,DWORD PTR [ebp-0x10]
lea ebx,[edx+eax*1]
mov eax,DWORD PTR [ebp-0x8]
lea edx,[eax+0x1]
mov eax,DWORD PTR [ebp+0x8]
add eax,edx
movzx eax,BYTE PTR [eax]
movsx edx,al
mov ecx,DWORD PTR [ebp-0x8]
mov eax,DWORD PTR [ebp+0x8]
add eax,ecx
movzx eax,BYTE PTR [eax]
movsx eax,al
sub edx,eax
mov eax,edx
add eax,ebx
mov DWORD PTR [ebp-0x10],eax
add DWORD PTR [ebp-0x8],0x1
mov eax,DWORD PTR [ebp-0xc]
sub eax,0x1
cmp DWORD PTR [ebp-0x8],eax
jl asm4+51
mov eax,DWORD PTR [ebp-0x10]
add esp,0x10
pop ebx
pop ebp
ret
#include <stdio.h>
int main() {
printf("Flag: 0x%x\n", asm4("picoCTFc1373"));
}
all:
gcc -m32 -c asm4.s -o asm4.o -fno-stack-protector -no-pie
gcc -m32 -c solve.c -o solve.o -fno-stack-protector -no-pie
gcc -m32 -o a.out solve.o asm4.o -fno-stack-protector -no-pie
./a.out
clean:
rm a.out *.o
picoCTF{0x1d8}