StackZero
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me
No Result
View All Result
StackZero
No Result
View All Result

PicoCTF asm3 challenge: Master the Art of Reverse Engineering

May 7, 2023
in Reverse Engineering
0 0
picoctf asm3 featured
0
SHARES
1.6k
VIEWS
Share on FacebookShare on Twitter

Welcome back to the exciting world of reverse engineering!
In this article, we will tackle the picoCTF asm3 challenge (here is our article on how to register there), a slightly more complex task than the previous ones (asm1, asm2). By analyzing this assembly code, we will uncover its secrets and discover the flag.

To start, head over to the picoCTF website and log in to your account. If you don’t have an account yet, follow the registration steps in our introductory article.
Once you’re logged in, navigate to the Practice section, select the Reverse Engineering category, and look for the asm3 challenge. Let’s begin our journey to master this exciting challenge together!

Table of Contents

Toggle
  • Registers Overview
  • The challenge Description
  • Behaviour Intuition of picoCTF asm3
  • Ghidra
    • Decompiler
  • Find the result of picoCTF asm3
  • Conclusion

Registers Overview

Before starting with the real challenge, let’s look at something you may find useful about registers.

In a 32-bit processor, there are 8 general-purpose registers: EAX, EBX, ECX, EDX, ESI, EDI, EBP, and ESP. Each of these 32-bit registers can be further divided into smaller components for working with smaller data sizes.

Let’s consider the EAX register as an example. EAX can be divided into three components:

  1. AX (16 bits): AX is the lower 16 bits of the EAX register. It allows for operations on 16-bit data.
  2. AH (8 bits): AH represents the upper 8 bits of the AX register, which are bits 8 to 15 of the EAX register. It’s used for 8-bit operations on the upper half of AX.
  3. AL (8 bits): AL stands for the lower 8 bits of the AX register, which are bits 0 to 7 of the EAX register. It’s used for 8-bit operations on the lower half of AX.

The same logic applies to other 32-bit registers as well (EBX, ECX, and EDX). They can be broken down into their 16-bit counterparts (BX, CX, and DX) and further into the 8-bit high and low byte registers (BH, BL; CH, CL; DH, DL).

These smaller registers offer flexibility when working with different data sizes, enabling programmers to optimize operations and memory usage.

The challenge Description

For this challenge, we will use Ghidra, a powerful reverse engineering tool, as it simplifies the analysis of complex assembly code.

Here’s the assembly code for the asm3 challenge:

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+0xe]
	<+15>:	add    ah,BYTE PTR [ebp+0xf]
	<+18>:	xor    ax,WORD PTR [ebp+0x12]
	<+22>:	nop
	<+23>:	pop    ebp
	<+24>:	ret  

Behaviour Intuition of picoCTF asm3

First, let’s understand the function’s behaviour:

  1. The function begins by setting up the stack frame with ‘push ebp’ and ‘mov ebp, esp’.
  2. It then initializes the EAX register to zero using the ‘xor eax, eax’ instruction.
  3. The code moves the byte at the address [ebp+0x9] into the AH register.
  4. It then shifts the AX register 16 bits to the left using ‘shl ax, 0x10’.
  5. The byte at the address [ebp+0xe] is subtracted from the AL register.
  6. Next, the byte at the address [ebp+0xf] is added to the AH register.
  7. The code proceeds to xor the AX register with the word at the address [ebp+0x12].
  8. The function ends with a ‘nop’ (no operation) instruction, followed by ‘pop ebp’ and ‘ret’ instructions.

We can attempt the computation ourselves, but a good reverse engineer uses powerful tools. Ghidra is a helpful tool for this purpose, as it provides a visual representation of the algorithm or a version on a higher-level language (decompiler), making it easier to replicate.

To use Ghidra, we need to install it on our Kali Linux machine. Unfortunately, it doesn’t come pre-installed. However, the installation process is quite simple.

Follow these two easy steps in the terminal:

  1. Update the repository first.
sudo apt update

Then install Ghidra:

sudo apt install ghidra

Now we can run it by typing this

ghidra

Ghidra

With the new tool open, let’s import the script and see what it looks like!

1. Create a new project.

Ghidra new project

2. Follow the instructions, name the project, and click on the code browser.

Ghidra code browser

To analyze the asm3 file (test.S), we need to clean it by removing line numbers and then compile it using GCC. Our code will look like this:

.intel_syntax noprefix
.globl asm3

asm3:
	push   ebp
	mov    ebp,esp
	xor    eax,eax
	mov    ah,BYTE PTR [ebp+0x9]
	shl    ax,0x10
	sub    al,BYTE PTR [ebp+0xe]
	add    ah,BYTE PTR [ebp+0xf]
	xor    ax,WORD PTR [ebp+0x12]
	nop
	pop    ebp
	ret  

To compile, type this command in the terminal: gcc -masm=intel -m32 -c test.S -o test.o

  • The .intel_syntax noprefix directive switches to Intel syntax from the default AT&T syntax.
  • The noprefix option stops the assembler from adding an underscore prefix to global symbols, common in Intel syntax.
  • The .globl directive makes the asm3 symbol visible globally, allowing access by other object files or linking with other functions.

Now, drag and drop the test file into Ghidra! We could run it with given inputs, but our aim is to understand, so we’ll do static analysis instead!

Decompiler

To better understand the code, we are going to use Ghidra’s decompiler. But what is a decompiler?

It’s a tool that takes machine code and converts it back into a more human-readable programming language. This helps people understand how a program works, making it easier to analyze and modify the code.

At the project’s opening, Ghidra will ask you if you want to analyze it, so confirm, keep the default settings and go ahead.

Now you will have the compiler on your right, just click on the text section in the left side view and you will see this screen:

picoctf asm3 decompiled

Ghidra has converted the assembly code into a more readable function.

ushort asm3(undefined4 param_1,undefined4 param_2,undefined4 param_3)

{
  return CONCAT11(param_2._3_1_,-param_2._2_1_) ^ param_3._2_2_;
}

takes three input parameters: param_1, param_2, and param_3. All these parameters are 4-byte values (undefined4).

The function returns a 2-byte unsigned short value (ushort) as the result. To calculate the result, it performs the following operations:

  1. Extracts the third byte from param_2 (param_2.3_1) and makes it the most significant byte of the result.
  2. Extracts the second byte from param_2 (param_2.2_1), negates it and makes it the least significant byte of the result.
  3. Concatenates these two bytes to form a 2-byte value (CONCAT11 is the way for Ghidra to say that it concatenates two elements of size 1).
  4. Extracts a 2-byte value from param_3, starting at the second byte (param_3.2_2).
  5. Performs a bitwise exclusive OR (XOR) operation between the concatenated 2-byte value and the 2-byte value from param_3.

Finally, the function returns the result of this XOR operation.

Find the result of picoCTF asm3

Now that we have a clear understanding of the assembly code, let’s find out what asm3(0xd2c26416, 0xe6cf51f0, 0xe54409d5) returns.

We can do the computation manually or we can write an equivalent script and check the result. I would opt for the second one using Python:

def asm3(param_1, param_2, param_3):
    return ((param_2 >> 24) << 8 | (-(param_2 >> 16) & 0xFF)) ^ (param_3 >> 16)

def main():
    # Test input values
    param1 = 0xd2c26416
    param2 = 0xe6cf51f0
    param3 = 0xe54409d5

    # Call asm3 function with the test inputs
    result = asm3(input1, input2, input3)

    # Print the result
    print(f"The result of asm3 function is: 0x{result:04x}")

if __name__ == "__main__":
    main()

I just want to delve into some important aspects of the code, in particular, the bitwise operations:

  1. param_2 >> 24: Shift the bits of param_2 24 positions to the right. This isolates the most significant byte of param_2.
  2. ((param_2 >> 24) << 8): Shift the result from step 1 eight positions to the left. This moves the most significant byte of param_2 to the position of the second-most significant byte.
  3. param_2 >> 16: Shift the bits of param_2 16 positions to the right. This isolates the second-most significant byte of param_2.
  4. -(param_2 >> 16): Compute the negative value of the result from step 3.
  5. (-(param_2 >> 16) & 0xFF): Perform a bitwise AND operation between the result from step 4 and 0xFF (255). This masks the result to keep only the least significant byte, effectively making sure the result is an 8-bit value.
  6. ((param_2 >> 24) << 8) | (-(param_2 >> 16) & 0xFF): Perform a bitwise OR operation between the results from step 2 and step 5. This combines the two 8-bit values into a 16-bit value, where the most significant byte is from step 2 and the least significant byte is from step 5.
  7. param_3 >> 16: Shift the bits of param_3 16 positions to the right. This isolates the two most significant bytes of param_3 as a 16-bit value.
  8. ((param_2 >> 24) << 8 | (-(param_2 >> 16) & 0xFF)) ^ (param_3 >> 16): Perform a bitwise XOR operation between the results from step 6 and step 7. This computes the final 16-bit result of the asm3 function.

Now we can finally run the script by typing in our terminal:

python main.py

And it will print:

0x0375

And we are done, that’s our flag!

Now let’s insert 0x375 into the input in picoCTF and the challenge is complete!

Conclusion

In conclusion, our journey through the picoCTF asm3 challenge has been an exciting and enlightening adventure. We’ve delved into the world of bit manipulation, reverse engineering, and Python programming to decode this complex problem. This hands-on experience has not only expanded our understanding of low-level operations but also showcased the power of persistent curiosity and exploration.

If you’re as captivated by this challenge as we are, don’t miss out on more thrilling content related to cybersecurity, reverse engineering, and programming challenges. Follow the Stackzero blog, where we unravel the mysteries of the digital world and bring you cutting-edge insights to sharpen your skills and knowledge.

For real-time updates and engaging conversations with like-minded enthusiasts, be sure to connect with Stackzero on social media. Join our growing community, share your thoughts, and learn from the experiences of fellow tech aficionados. Together, we’ll continue to push the boundaries of learning and conquer new heights in the captivating realm of technology.

Don’t wait another moment! Follow Stackzero now and unlock a world of endless possibilities in the fascinating field of cybersecurity and beyond.

Tags: assemblerctfcybersecuritypico ctfpicoctfreverse engineering
Previous Post

A Beginner’s Guide to PicoCTF’s Reverse Engineering: Simple Writeups

Next Post

Master the Art of Linux Firewall: Practical Guide to Iptables

Next Post
Master the Art of Linux Firewall: Practical Guide to Iptables

Master the Art of Linux Firewall: Practical Guide to Iptables

You might also like

Cryptographic functions

Cryptographic Hash Functions in Python: Secure Your Data Easily

November 3, 2024
Malware Obfuscation Techniques: All That You Need To Know

Malware Obfuscation Techniques: All That You Need To Know

March 25, 2024
How To Do Process Enumeration: An Alternative Way

How To Do Process Enumeration: An Alternative Way

March 4, 2024
How To Do DLL Injection: An In-Depth Cybersecurity Example

How To Do DLL Injection: An In-Depth Cybersecurity Example

February 8, 2024
Process Injection By Example: The Complete Guide

Process Injection By Example: The Complete Guide

January 24, 2024
How To Build Your Own: Python String Analysis for Malware Insights

How To Build Your Own: Python String Analysis for Malware Insights

November 10, 2023

StackZero

StackZero is a specialized technical blog dedicated to the realm of cybersecurity. It primarily provides insightful articles and comprehensive tutorials designed to educate readers on developing security tools. The blog encompasses a broad spectrum of subjects, starting from the foundational principles of cryptography and extending to more sophisticated areas such as exploitation and reverse engineering. This makes StackZero an invaluable resource for both beginners and professionals in the field of cybersecurity.
The blog covers a wide range of topics, from the basics of cryptography to the more advanced topics of exploitation and reverse engineering.

Tags

application security blind sqli blind sql injection bruteforce c cesar cipher command injection cryptography ctf cybersecurity debugging dom-based xss dvwa ethical-hacking ethical hacking exploitation file inclusion gdb hacking injection javascript malware malware analysis malware evasion network-security pentesting lab picoctf pico ctf python reflected xss reverse engineering sql sqli sql injection static analysis stored xss substitution substitution cipher vulnerable application web application security web exploitation web security windows windows api xss
  • About Me
  • Contacts
  • HomePage
  • Opt-out preferences
  • Privacy Policy
  • Terms and Conditions

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
Manage Cookie Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
View preferences
{title} {title} {title}
No Result
View All Result
  • Homepage
  • Cryptography and Privacy
  • Ethical Hacking
  • Reverse Engineering
  • Contacts
  • About Me