These are hands-on challenges presented at the end of each module to reinforce newly learned concepts. These tasks require learners to immediately apply techniques discussed in the lesson, ensuring they understand how the theory translates into real-world offensive or defensive operations. By engaging directly with simulated environments, users build muscle memory, identify gaps in understanding, and develop confidence in executing the skills before moving on.
ASSEMBLY LANGUAGE
In the below 'Hello World' example, which Assembly instruction will '00001111 00000101' execute?
Download the attached file, and find the hex value in 'rax' when we reach the instruction at <_start+16>?
DATA MOVEMENT
Add an instruction at the end of the attached code to move the value in "rsp" to "rax". What is the hex value of "rax" at the end of program execution?
ARITHMETIC INSTRUCTIONS
Add an instruction to the end of the attached code to "xor" "rbx" with "15". What is the hex value of 'rbx' at the end?
LOOPS
Edit the attached assembly code to loop the "loop" label 5 times. What is the hex value of "rax" by the end?
UNCONDITIONAL BRANCHING
Try to jump to "func" before "loop loop". What is the hex value of "rbx" at the end?
CONDITIONAL BRANCHING
The attached assembly code loops forever. Try to modify (mov rax, 5) to make it not loop. What hex value prevents the loop?
USING THE STACK
Debug the attached binary to find the flag being pushed to the stack
SYSCALLS
What is the syscall number of "execve"?How many arguments does "execve" take?
PROCEDURES
Try assembling and debugging the above code, and note how "call" and "ret" store and retrieve "rip" on the stack. What is the address at the top of the stack after entering "Exit"? (6-digit hex 0xaddress, without zeroes)
FUNCTIONS
Try to fix the Stack Alignment in "print", so it does not crash, and prints "Its Aligned!". How much boundary was needed to be added? "write a number"
LIBC FUNCTIONS
The current string format we are using only allows numbers up to 2 billion. What format can we use to allow up to 3 billion? "Check length modifiers in the 'printf' man page"
SHELLCODES
Run the "Exercise Shellcode" to get the flag.
SHELLCODING TOOLS
The above server simulates an exploitable server you can execute shellcodes on. Use one of the tools to generate a shellcode that prints the content of '/flag.txt', then connect to the server with "nc SERVER_IP PORT" to send the shellcode.
//DEBUGGING
root@htb:~$ gdb -q ./gdb
Reading symbols from ./gdb...
(No debugging symbols found in ./gdb)
(gdb) All defined functions:
Non-debugging symbols:
0x0000000000401000 _start
0x0000000000402000 __bss_start
0x0000000000402000 _edata
0x0000000000402000 _end
(gdb) info variables
All defined variables:
(gdb) break *_start
Breakpoint 1 at 0x401000
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000401000 <_start>
breakpoint already hit 1 time
(gdb) run
Starting program: /home/htb-ac-53539/gdb
(gdb) disassemble _start
Dump of assembler code for function _start:
=> 0x0000000000401000 <+0>: movabs $0x21796d6564616341,%rax
0x000000000040100a <+10>: xor $0x21449,%rax
0x0000000000401010 <+16>: xor %rax,%rax
(gdb) break *0000000000401010
Breakpoint 5 at 0x20208
(gdb) si
0x000000000040100a in _start ()
(gdb) disas
Dump of assembler code for function _start:
0x0000000000401000 <+0>: movabs $0x21796d6564616341,%rax
=> 0x000000000040100a <+10>: xor $0x21449,%rax
0x0000000000401010 <+16>: xor %rax,%rax
End of assembler dump.
(gdb) si
0x0000000000401010 in _start ()
(gdb) disas
Dump of assembler code for function _start:
0x0000000000401000 <+0>: movabs $0x21796d6564616341,%rax
0x000000000040100a <+10>: xor $0x21449,%rax
=> 0x0000000000401010 <+16>: xor %rax,%rax
(gdb) x/wx 0x0000000000401010
0x401010 <_start+16>: 0x00c03148
* x (1st x) examines memory
* /wx controls how the memory is displayed:
- w refers to word (in x86-64, a word here means 4 bytes).
- x (2nd x) refers hexadecimal format.
(gdb) info registers rax
rax 0x21796d6564637708 2412079357676975880
* this shows the contents of RAX before the xor %rax,%rax executes.
- when xor %rax,%rax executes RAX = 0x0 as any value XOR’d with
itself becomes 0
root@htb:~$ nasm -f elf64 mov.s -o mov.o
root@htb:~$ ld mov.o -o mov
root@htb:~$ gdb ./mov
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded and 5 functions added for GDB 13.1 in 0.00ms using Python engine 3.11
Reading symbols from ./mov...
(No debugging symbols found in ./mov)
gef> info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _start
0x0000000000402000 __bss_start
0x0000000000402000 _edata
0x0000000000402000 _end
gef> break *_start
Breakpoint 1 at 0x401000
gef> info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000401000 <_start>
gef> run
0x400ffa add BYTE PTR [rax], al
0x400ffc add BYTE PTR [rax], al
0x400ffe add BYTE PTR [rax], al
●→ 0x401000 <_start+0000> mov eax, 0x400
0x401005 <_start+0005> mov ebx, 0x800
0x40100a <_start+000a> xchg rbx, rax
0x40100c <_start+000c> push rbx
0x40100d <_start+000d> mov rax, QWORD PTR [rsp]
0x401011 add BYTE PTR [rax], al
gef> si 4
→ 0x40100d <_start+000d> mov rax, QWORD PTR [rsp]
0x401011 add BYTE PTR [rax], al
0x401013 add BYTE PTR [rax], al
0x401015 add BYTE PTR [rax], al
0x401017 add BYTE PTR [rax], al
0x401019 add BYTE PTR [rax], al
* In GDB/GEF, the arrow → points to the next instruction that will be executed.
- To execute that instruction and step forward, use the "si" (step instruction) command.
gef> info registers
rax 0x800 0x800
rbx 0x400 0x400
gef> si
$rax : 0x400
$rbx : 0x400
gef> info registers rax
rax 0x400 0x400
root@htb:~$ nano unconditional.s
...
_start:
mov rbx, 2
mov rcx, 5
loop:
imul rbx, rbx
jmp func ;jmp placed here per instruction
loop loop
func:
mov rax, 60
mov rdi, 0
syscall
root@htb:~$ nasm -f elf64 unconditional.s -o unconditional.o
root@htb:~$ ld unconditional.o -o unconditional
root@htb:~$ gdb -q ./unconditional
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded and 5 functions added for GDB 13.1 in 0.00ms using Python engine 3.11
Reading symbols from ./unconditional...
(No debugging symbols found in ./unconditional)
gef> info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _start
0x000000000040100c loop
0x0000000000401012 func
gef> break *_start
Breakpoint 1 at 0x401000
gef> break *func
Breakpoint 2 at 0x401012
gef> info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000401000 <_start>
2 breakpoint keep y 0x0000000000401012 <func>
gef> run
gef> si 3
0x400fff add BYTE PTR [rbx+0x2], bh
0x401005 <_start+0005> mov ecx, 0x5
0x40100a <loop+0000> imul rbx, rbx
→ 0x40100e <loop+0004> jmp 0x401012 <func>
0x401010 <loop+0006> loop 0x40100a <loop>
● 0x401012 <func+0000> mov eax, 0x3c
0x401017 <func+0005> mov edi, 0x0
0x40101c <func+000a> syscall
0x40101e add BYTE PTR [rax], al
gef> si
0x40100e <loop+0004> jmp 0x401012 <func>
0x401010 <loop+0006> loop 0x40100a <loop>
● 0x401012 <func+0000> mov eax, 0x3c
→ 0x401017 <func+0005> mov edi, 0x0
0x40101c <func+000a> syscall
0x40101e add BYTE PTR [rax], al
0x401020 add BYTE PTR [rax], al
0x401022 add BYTE PTR [rax], al
0x401024 add BYTE PTR [rax], al
gef> p /x $rbx
$2 = 0x4
gef> info registers rbx
rbx 0x4 0x4
root@htb:~$ curl -O https://academy.hackthebox.com/storage/modules/85/conditional.zip
root@htb:~$ unzip conditional.zip
root@htb:~$ cat conditional.s
section .text
global _start
_start:
mov rax, 5 ; change here
imul rax, 5 ; rax = 5 * 5 (25)
;rax == 10 Zero Flag is set No (loop exits)
;rax != 10 Zero Flag is clear Yes (loop continues)
; cmp rax, 10 must set ZF = 1 (i.e., rax == 10) to prevent the loop (jnz not taken)
loop:
; if (rax == 10) then ZF = 1 → do not loop
; if (rax != 10) then ZF = 0 → jump to loop
cmp rax, 10 ; rax = 25 - 10 (15)
; subtract 10 from RAX (without storing the result),
; then set flags accordingly (especially Zero Flag).
jnz loop ; Jump back to loop if the result of the comparison doesn't set ZF to 1 (true) (i.e., RAX != 10)
* imul performs signed multiplication, meaning it treats the operands as
signed integers (can be negative or positive) when calculating the result.
root@htb:~$ nano conditional.s
section .text
global _start
_start:
;mov rax, 5 ; change here - must change rax to equal 10
mov rax, 2
imul rax, 5 ; rax = 2 * 5 (10)
; cmp rax, 10 must set ZF = 1 (i.e., rax == 10) to prevent the loop (jnz not taken)
loop:
; if (rax == 10) then ZF = 1 → do not loop
; if (rax != 10) then ZF = 0 → jump to loop
cmp rax, 10 ; rax = 10 - 10 (0) - this must be = 0 to prevent the loop
jnz loop ; think of jnz as (a != b)
* imul performs signed multiplication, meaning it treats the operands as
signed integers (can be negative or positive) when calculating the result.
root@htb:~$ nasm -f elf64 conditional.s -o conditional.o
root@htb:~$ ld conditional.o -o conditional
root@htb:~$ gdb -q ./conditional
gef> info func
All defined functions:
Non-debugging symbols:
0x0000000000401000 _start
0x0000000000401009 loop
gef> break *_start
Breakpoint 1 at 0x401000
gef> break *loop
Breakpoint 2 at 0x401009
gef> info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000401000 <_start>
2 breakpoint keep y 0x0000000000401009 <loop>
gef> run
0x400ffa add BYTE PTR [rax], al
0x400ffc add BYTE PTR [rax], al
0x400ffe add BYTE PTR [rax], al
●→ 0x401000 <_start+0000> mov eax, 0x2
0x401005 <_start+0005> imul rax, rax, 0x5
0x401009 <loop+0000> cmp rax, 0xa
0x40100d <loop+0004> jne 0x401009 <loop>
0x40100f add BYTE PTR [rax], al
0x401011 add BYTE PTR [rax], al
gef> si 2
0x400ffe add BYTE PTR [rax], al
● 0x401000 <_start+0000> mov eax, 0x2
0x401005 <_start+0005> imul rax, rax, 0x5
→ 0x401009 <loop+0000> cmp rax, 0xa
0x40100d <loop+0004> jne 0x401009 <loop>
0x40100f add BYTE PTR [rax], al
0x401011 add BYTE PTR [rax], al
0x401013 add BYTE PTR [rax], al
0x401015 add BYTE PTR [rax], al
gef> si
● 0x401000 <_start+0000> mov eax, 0x2
0x401005 <_start+0005> imul rax, rax, 0x5
0x401009 <loop+0000> cmp rax, 0xa
→ 0x40100d <loop+0004> jne 0x401009 <loop> NOT taken [Reason: !(!Z)]
0x40100f add BYTE PTR [rax], al
0x401011 add BYTE PTR [rax], al
0x401013 add BYTE PTR [rax], al
0x401015 add BYTE PTR [rax], al
0x401017 add BYTE PTR [rax], al
* → 0x40100d <loop+0004> jne 0x401009 <loop> NOT taken [Reason: !(!Z)]
- 0x2 prevents the loop
root@htb:~$ nano procedure.asm
section .data
message db "Fibonacci Sequence:", 0x0a
section .text
global _start
_start:
call printMessage ; print intro message
call initFib ; set initial Fib values
call loopFib ; calculate Fib numbers
call Exit ; Exit the program
printMessage:
mov rax, 1 ; rax: syscall number 1
mov rdi, 1 ; rdi: fd 1 for stdout
mov rsi,message ; rsi: pointer to message
mov rdx, 20 ; rdx: print length of 20 bytes
syscall ; call write syscall to the intro message
ret
initFib:
xor rax, rax ; initialize rax to 0
xor rbx, rbx ; initialize rbx to 0
inc rbx ; increment rbx to 1
ret
loopFib:
add rax, rbx ; get the next number
xchg rax, rbx ; swap values
cmp rbx, 10 ; do rbx - 10
js loopFib ; jump if result is <0
ret
Exit:
mov rax, 60
mov rdi, 0
syscall
root@htb:~$ nasm -f elf64 procedure.asm -o procedure.o
...
root@htb:~$ ld procedure.o -o procedure
...
root@htb:~$ gdb -q ./procedure
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded and 5 functions added for GDB 13.1 in 0.00ms using Python engine 3.11
Reading symbols from ./procedure...
(No debugging symbols found in ./procedure)
gef> info functions
All defined functions:
Non-debugging symbols:
0x0000000000401000 _start
0x0000000000401014 printMessage
0x0000000000401030 initFib
0x000000000040103a loopFib
0x0000000000401046 Exit
gef> disas _start
Dump of assembler code for function _start:
0x0000000000401000 <+0>: call 0x401014 <printMessage>
0x0000000000401005 <+5>: call 0x401030 <initFib>
0x000000000040100a <+10>: call 0x40103a <loopFib>
0x000000000040100f <+15>: call 0x401046 <Exit>
End of assembler dump.
gef> disas printMessage
Dump of assembler code for function printMessage:
0x0000000000401014 <+0>: mov eax,0x1
0x0000000000401019 <+5>: mov edi,0x1
0x000000000040101e <+10>: movabs rsi,0x402000
0x0000000000401028 <+20>: mov edx,0x14
0x000000000040102d <+25>: syscall
0x000000000040102f <+27>: ret
End of assembler dump.
gef> break *_start
Breakpoint 1 at 0x401000
gef> run
...
gef> ni
* run ni (aka next instruction) several times to get to the exit
● 0x401000 <_start+0000> call 0x401014 <printMessage>
0x401005 <_start+0005> call 0x401030 <initFib>
0x40100a <_start+000a> call 0x40103a <loopFib>
→ 0x40100f <_start+000f> call 0x401046 <Exit>
↳ 0x401046 <Exit+0000> mov eax, 0x3c
0x40104b <Exit+0005> mov edi, 0x0
0x401050 <Exit+000a> syscall
0x401052 add BYTE PTR [rax], al
0x401054 add BYTE PTR [rax], al
0x401056 add BYTE PTR [rax], al
gef> si
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdf18│+0x0000: 0x0000000000401014 → <printMessage+0000> mov eax, 0x1 ← $rsp
0x00007fffffffdf20│+0x0008: 0x0000000000000001
0x00007fffffffdf28│+0x0010: 0x00007fffffffe24e → "/home/htb-ac-53539/procedure"
0x00007fffffffdf30│+0x0018: 0x0000000000000000
0x00007fffffffdf38│+0x0020: 0x00007fffffffe26b → "SHELL=/bin/bash"
0x00007fffffffdf40│+0x0028: 0x00007fffffffe27b → "SESSION_MANAGER=local/htb-t3hsvuao25:@/tmp/.ICE-un[...]"
0x00007fffffffdf48│+0x0030: 0x00007fffffffe2dd → "WINDOWID=50331654"
0x00007fffffffdf50│+0x0038: 0x00007fffffffe2ef → "QT_ACCESSIBILITY=1"
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x40103f <loopFib+0005> cmp rbx, 0xa
0x401043 <loopFib+0009> js 0x40103a <loopFib>
0x401045 <loopFib+000b> ret
→ 0x401046 <Exit+0000> mov eax, 0x3c
0x40104b <Exit+0005> mov edi, 0x0
0x401050 <Exit+000a> syscall
0x401052 add BYTE PTR [rax], al
0x401054 add BYTE PTR [rax], al
0x401056 add BYTE PTR [rax], al
* 0x401014
root@htb:~$ curl -O https://academy.hackthebox.com/storage/modules/85/functions.zip
...
root@htb:~$ unzip functions.zip
...
root@htb:~$ cat functions.s
global _start
extern printf
section .data
outFormat db "It's %s", 0x0a, 0x00
message db "Aligned!", 0x0a
section .text
_start:
call print ; print string
call Exit ; Exit the program
print:
mov rdi, outFormat ; set 1st argument (Print Format)
mov rsi, message ; set 2nd argument (message)
call printf ; printf(outFormat, message)
ret
Exit:
mov rax, 60
mov rdi, 0
syscall
//triage
root@htb:~$ nasm -f elf64 functions.s -o functions.o
root@htb:~$ ld functions.o -o functions -lc --dynamic-linker /lib64/ld-linux-x86-64.so.2
root@htb:~$ ./functions
Segmentation fault
//code review
root@htb:~$ cat functions.s
global _start
extern printf
section .data
outFormat db "It's %s", 0x0a, 0x00
message db "Aligned!", 0x0a
section .text
_start:
call print ; print string - calls a procedure not function
call Exit ; Exit the program - calls a procedure not function
print:
mov rdi, outFormat ; set 1st argument (Print Format)
mov rsi, message ; set 2nd argument (message)
call printf ; printf(outFormat, message) - calls external function
ret
Exit:
mov rax, 60
mov rdi, 0
syscall
//debugg
root@htb:~$ gdb -q ./functions
GEF for linux ready, type `gef' to start, `gef config' to configure
93 commands loaded and 5 functions added for GDB 13.1 in 0.00ms using Python engine 3.11
Reading symbols from ./functions...
(No debugging symbols found in ./functions)
gef> info functions
All defined functions:
Non-debugging symbols:
0x0000000000401010 printf@plt
0x0000000000401020 _start
0x000000000040102a print
0x0000000000401044 Exit
gef> break *_start
Breakpoint 1 at 0x401020
gef> run
...
gef> si...
0x00007fffffffdb40│+0x0000: 0x0000000000000038 ("8"?) ← $rsp
0x00007fffffffdb48│+0x0008: 0x00007fffffffdf38 → 0x00007fffffffe26b → "SHELL=/bin/bash"
0x00007fffffffdb50│+0x0010: 0x00000003f7ffe2e0
0x00007fffffffdb58│+0x0018: 0x00007ffff7fde6e0 → <_dl_unload_cache+0030> mov QWORD PTR [rip+0x1fb1d], 0x0 # 0x7ffff7ffe208 <cache>
0x00007fffffffdb60│+0x0020: 0x000006eb1754d2d0
0x00007fffffffdb68│+0x0028: 0x00007ffff7fe8dd5 → <dl_main+1f35> lea rsp, [rbp-0x28]
0x00007fffffffdb70│+0x0030: 0x0000000000000000
0x00007fffffffdb78│+0x0038: 0x0000000000000001
//fix
root@htb:~$ nano functions.s
global _start
extern printf
section .data
outFormat db "It's %s", 0x0a, 0x00
message db "Aligned!", 0x0a
section .text
_start:
; Each procedure call pushes an 8-byte return address onto the stack.
; Each 'push' instruction also subtracts 8 from rsp (stack grows down).
; This is why we adjust rsp here — to keep 16-byte alignment before calls.
sub rsp, 8 ; keep stack 16-byte aligned (calls push 8-byte return addr)
call print ; print string - calls a procedure not function
call Exit ; Exit the program - calls a procedure not function
print:
mov rdi, outFormat ; set 1st argument (Print Format)
mov rsi, message ; set 2nd argument (message)
call printf ; printf(outFormat, message) - calls external function
ret
Exit:
add rsp, 8 ; restore stack (optional cleanup)
mov rax, 60
mov rdi, 0
syscall
* four main things to consider before calling a function:
- Save Registers on the stack (Caller Saved)
- Pass Function Arguments (like syscalls)
- Fix Stack Alignment
- Ensure rsp is 16-byte aligned before external function
calls (e.g., printf), otherwise you risk segfaults.
- Get Function's Return Value (in rax)
* Before calling a C function, the System V AMD64 ABI requires the stack to
be 16-byte aligned at the call instruction. Currently, after _start, the
stack alignment is off because rsp isn't adjusted
root@htb:~$ man -s 3 printf
...
Length modifier
Here, "integer conversion" stands for d, i, o, u, x, or X conversion.
hh A following integer conversion corresponds to a signed char or
unsigned char argument, or a following n conversion corresponds to a
pointer to a signed char argument.
h A following integer conversion corresponds to a short or unsigned
short argument, or a following n conversion corresponds to a pointer
to a short argument.
l (ell) A following integer conversion corresponds to a long or unsigned
long argument, or a following n conversion corresponds to a pointer to
a long argument, or a following c conversion corresponds to a wint_t
argument, or a following s conversion corresponds to a pointer to
wchar_t argument. On a following a, A, e, E, f, F, g, or G conversion,
this length modifier is ignored (C99; not in SUSv2).
ll (ell-ell). A following integer conversion corresponds to a long long
or unsigned long long argument, or a following n conversion corresponds
to a pointer to a long long argument.
q A synonym for ll. This is a nonstandard extension, derived from BSD;
avoid its use in new code.
L A following a, A, e, E, f, F, g, or G conversion corresponds to a long
double argument. (C99 allows %LF, but SUSv2 does not.)
j A following integer conversion corresponds to an intmax_t or uintmax_t
argument, or a following n conversion corresponds to a pointer to an
intmax_t argument.
z A following integer conversion corresponds to a size_t or ssize_t
argument, or a following n conversion corresponds to a pointer to
a size_t argument.
Z A nonstandard synonym for z that predates the appearance of z. Do not
use in new code.
t A following integer conversion corresponds to a ptrdiff_t argument, or
a following n conversion corresponds to a pointer to a ptrdiff_t
argument.
SUSv3 specifies all of the above, except for those modifiers explicitly
noted as being nonstandard extensions. SUSv2 specified only the length
modifiers h (in hd, hi, ho, hx, hX, hn) and l (in ld, li, lo, lx, lX, ln,
lc, ls) and L (in Le, LE, Lf, Lg, LG).
As a nonstandard extension, the GNU implementations treats ll and L as
synonyms, so that one can, for example, write llg (as a synonym for the
standards-compliant Lg) and Ld (as a synonym for the standards compliant
lld). Such usage is nonportable.
* %lld
root@htb:~$ sudo pipx install pwntools
...
installed package pwntools 4.14.1, installed using Python 3.11.2
These apps are now globally available
- asm
- checksec
- common
- constgrep
- cyclic
- debug
- disablenx
- disasm
- elfdiff
- elfpatch
- errno
- hex
- libcdb
- main
- phd
- pwn
- pwnstrip
- scramble
- shellcraft
- template
- unhex
- update
- version
done! ✨ 🌟 ✨
root@htb:~$ python3
>>> from pwn import *
>>> context(os="linux", arch="amd64", log_level="error")
>>> run_shellcode(unhex('4831db536a0a48b86d336d307279217d5048b833645f316e37305f5048b84854427b6c303464504889e64831c0b0014831ff40b7014831d2b2190f054831c0043c4030ff0f05')).interactive()
HTB{l04d3d_1n70_m3m0ry!}
root@htb:~$ sudo pipx install pwntools
installing pwntools
...
//identify the path for cat
root@htb:~$ which cat
/usr/bin/cat
//research & craft payload - assuming target is Linux
root@htb:~$ python3
>>> from pwn import *
>>> context(os="linux", arch="amd64", log_level="error")
//list payloads and find execve syscall
>>> dir(shellcraft)
[...SNIP... 'execve', 'exit', 'exit_group', ... SNIP...]
//syscall and arguments
>>> syscall = shellcraft.execve(path='/bin/cat', argv=['/bin/cat', '/flag.txt'])
>>> asm(syscall).hex()
'6a01fe0c2448b82f62696e2f636174504889e768797501018134240101010148b801010101010101015048b8012e676d60662f754831042448b82f62696e2f6361745031f6566a115e4801e6566a105e4801e6564889e631d26a3b580f05'
//test shellcode locally
root@htb:~$ nano payloadLoader.py
#!/usr/bin/python3
import sys
from pwn import *
context(os="linux", arch="amd64", log_level="error")
run_shellcode(unhex(sys.argv[1])).interactive()
root@htb:~$ python3 payloadLoader.py '6a01fe0c2448b82f62696e2f636174504889e768797501018134240101010148b801010101010101015048b8012e676d60662f754831042448b82f62696e2f6361745031f6566a115e4801e6566a105e4801e6564889e631d26a3b580f05'
/bin/cat: /flag.txt: No such file or directory