Historical Intros #
Trondol begins #
Its start from curiousity about “What the peak level of this machine?”, and then landed into tinkering how to make this TV-Box becoming a Linux server.
Trondol
After becoming a Linux server, I named it "Trondol". Then I've thought "how to make this TV-Box (Trondol) are able to work with other TV-Box?".
Trondol Cluster
Then this things evolved, I call it "Trondol Cluster", after its work together in Cluster system. What if work together but in security areas?.
Infosec Trondol
Its evolved for 2nd times, The OG "Infosec Trondol". Aren't done yet, After this things are able to work in security areas.
Pwnadol
What if get some low level workspace? like binary layer? Then it's evolved, proudly present, the peak level of TV-Box. Pwnadol Homelabs, with no cluster.
What is Pwnadol #
Pwnadol is a low cost and highly efficient exploit development homelabs that I built with formerly Android TV-Box device.
Why dont we just use pi’s? what make Pwnadol difference from any kind of pi’s? It’s ARM64 right?
Yes its ARM64 device, but a TV-Box are much more cheaper than comparable any pi’s. Just it, lets build our homelabs, btw here is the CPU details.
[ root@labs: ~ ]># lscpu | head -n10
Architecture: aarch64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Vendor ID: ARM
Model name: Cortex-A53
Model: 4
Thread(s) per core: 1
Core(s) per cluster: 4
[ root@labs: ~ ]>#What is Radare2 #
Free Reversing Toolkit
“A free/libre toolchain for easing several low level tasks like forensics, software reverse engineering, exploiting, debugging, …
It is composed by a bunch of libraries (which are extended with plugins) and programs that can be automated with almost any programming language.”
~ rada.re
Radare2 Installation #
First thing todo, you need to install some development dependency to build Radare2 binary from source.
sudo apt install git build-essentialAccording to radare2 installation, you just need todo a simple paste command on the terminal.
git clone https://github.com/radareorg/radare2
cd radare2 ; sys/install.shIf you face some build issue then try this command, if not just skip this.
sudo make purge
rm -rf shlr/capstone
git clean -xdf
git reset --hard @~50
sys/install.sh[ root@labs: radare2 ]># radare2 -v
radare2 6.1.9 +36803 abi:127 @ linux-arm_64
birth: git.6.1.8-342-g9104dd7ff4 2026-07-24__21:57:49
commit: 9104dd7ff4311780fe268a529524c394b4147b9f
options: gpl -O? cs:5 cl:2 makeIf we were done, lets go to walkthrough. Maybe I will demonstrate for bit for radare2 usecase.
Walkthrough #
lets we create a simple C-lang hello-world.c code.
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
[ root@labs: walkthrough ]># gcc hello-world.c -o hello
[ root@labs: walkthrough ]># ./hello
Hello, World!
[ root@labs: walkthrough ]># file hello
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=1666d7a861d5c78f6a7f2bc982042241fd013c40, for GNU/Linux 3.7.0, not stripped
[ root@labs: walkthrough ]># uname -m
aarch64As you can see, from the execution up there. We have some information about the binary itself.
Its print Hello, World! ofcourse and the binary are compiled by using ARM aarch64 architecture GCC compiler.
Because this TV-Box is ARM based CPU.
[ root@labs: walkthrough ]># file `which gcc`
/usr/bin/gcc: symbolic link to gcc-14
[ root@labs: walkthrough ]># file `which gcc-14`
/usr/bin/gcc-14: symbolic link to aarch64-linux-gnu-gcc-14
[ root@labs: walkthrough ]># file `which aarch64-linux-gnu-gcc-14`
/usr/bin/aarch64-linux-gnu-gcc-14: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=99ea0b90dea6c913445097ead845ec23d4fb4499, for GNU/Linux 3.7.0, strippedAnd then let’s try our Reversing toolkit framework (Radare2).
[ root@labs: walkthrough ]># file hello
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=1666d7a861d5c78f6a7f2bc982042241fd013c40, for GNU/Linux 3.7.0, not stripped
[ root@labs: walkthrough ]># r2 hello
-- Control the height of the terminal on serial consoles with e scr.height
[0x00000680]>After we type r2 hello or radare2 hello, it will pops up a new shell environment with set of weird number.
[0x00000680]>Lets talk about this number in another section, lets being objective first.
After we pops a new shell, we need to do a recon or find what we looking for inside of the hello binary file.
[0x00000680]> i
fd 3
file hello
size 0x11390
humansz 68.9K
mode r-x
format elf64
iorw true
block 0x100
type DYN (Shared object file)
arch arm
baddr 0x0
binsz 68620
bintype elf
bits 64
canary false
injprot false
class ELF64
compiler GCC: (Debian 14.2.0-19) 14.2.0
crypto false
endian little
havecode true
intrp /lib/ld-linux-aarch64.so.1
laddr 0x0
lang c
linenum false
lsyms true
machine ARM aarch64
nx true
os linux
pic true
relocs true
relro partial
rpath NONE
sanitize false
static false
stripped false
uncaps true
subsys linux
va true
[0x00000680]>By typing i inside of shell, we got lot of information to better understanding what this file binary is.
Those info much better than file command that we use previously.
And then lets start to looking for what we want. Let trying to patch this binary without re-compiled the binary.
[0x00000680]> aaa
INFO: Analyze all flags starting with sym. and entry0 (aa)
INFO: Analyze imports (af@@@i)
INFO: Analyze entrypoint (af@ entry0)
INFO: Analyze symbols (af@@@s)
INFO: Running plugin pre-analysis hooks
INFO: Analyze all functions arguments/locals (afva@@F)
INFO: Analyze function calls (aac)
INFO: Analyze len bytes of instructions for references (aar)
INFO: Finding and parsing C++ vtables (avrr)
INFO: Analyzing methods (af @@ method.*)
INFO: Finding function preludes (aap)
INFO: Emulate functions to find computed references (aaef)
INFO: Recovering local variables (afva@@@F)
INFO: Type matching analysis for all functions (aaft)
INFO: Propagate noreturn information (aanr)
INFO: Use -AA or aaaa to perform additional experimental analysis
INFO: Finding xrefs in noncode sections (e anal.in=io.maps.x; aav)
WARN: Skipping aav because base address is zero. Use -B 0x800000 or aav0
[0x00000680]>By typing aaa on the shell, it suppose to analysing whole hello binary.
We will try to seek Hello, World! string,
and then patch them in disassembly language, then re-run the binary and see the result.
[0x00000680]> iz
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x000007e8 0x000007e8 13 14 .rodata ascii Hello, World!
[0x00000680]>By typing iz radare2 will seeking the strings type inside whole binary,
and print the offset or the address of string are in placed.
Then, what next? After we find the address of Hello, World! string,
We need to seek into the offset of string which in case 0x000007e8 are the correspond for Hello, World!.
[0x00000680]> s 0x000007e8
[0x000007e8]>Here you can see, can you spot the different? Yes, the weird number is called with “offset”.
The offset is change or switch from 0x00000680 into 0x000007e8. By typing s <OFFSET>
you will change the address, from current into another place.
Then what next? After we move into another offset, we need to show the disassembly code.
How to show the disassembly code of the offset string Hello, World!?
By typing pd command inside the shell, you will facing front gate of hell. pd command
are correspond for print the disassembly code.
[0x000007e8]> pd
;-- str.Hello__World_:
;-- hit10_0:
; STRN XREF from main @ 0x7b4(r)
0x000007e8 .string "Hello, World!" ; len=14
0x000007f6 0000 unaligned
;-- section..eh_frame_hdr:
;-- segment.GNU_EH_FRAME:
;-- __GNU_EH_FRAME_HDR:
0x000007f8 011b033b invalid ; [15] -r-- section size 60 named .eh_frame_hdr
; ---SNIP---
0x00000834 00000000 invalid
;-- section..eh_frame:
0x00000838 10000000 invalid ; [16] -r-- section size 180 named .eh_frame
; ---SNIP---
0x0000089c 0e209d04 invalid
0x000008a0 9e034293 sbfiz x30, x28, 0x3e, 1
; ---SNIP---
0x000008d4 20000000 invalid
0x000008d8 00410e10 adr x0, 0x1d0f8
0x000008dc 9d029e01 invalid
0x000008e0 46dedd0e invalid
0x000008e4 00000000 invalid
;-- __FRAME_END__:
0x000008e8 00000000 invalid
;-- section..note.ABI_tag:
;-- segment.NOTE_1:
;-- __abi_tag:
0x000008ec 04000000 invalid ; [17] -r-- section size 32 named .note.ABI-tag
[0x000007e8]> pSee? Its HELL, I can’t read my brain goes Dyslexic, but I’ve high-lighting the Hello, World! section.
The comment it said, “; STRN XREF from main @ 0x7b4(r)”, its a XREF or cross reference into main.
What these mean? Its mean the Hello, World! string are came from main function.
Lets find main function, how to find main function? to find main function you need to
type afl which stand for “Analysing Function List” maybe, or whatever.
[0x000007e8]> afl
0x00000610 1 16 sym.imp.__libc_start_main
0x00000620 1 32 sym.imp.__cxa_finalize
0x00000640 1 16 sym.imp.abort
0x00000650 1 20 sym.imp.puts
0x00000680 1 48 entry0
0x000006b4 3 20 sym.call_weak_fn
0x000006e0 4 48 sym.deregister_tm_clones
0x00000710 4 60 sym.register_tm_clones
0x0000074c 5 80 entry.fini0
0x000007a0 1 8 entry.init0
0x000007c8 1 24 sym._fini
0x000007a8 1 32 main
0x000005d0 1 28 sym._init
0x000005f0 1 32 fcn.000005f0
[0x000007e8]>After command afl radare spit out bunch of list, those list is a functions,
as you can see part of those list the main function are included.
What next? We need to change the address offset into main function, then show the disassembly code again.
[0x000007e8]> s 0x000007a8
[0x000007a8]>Spot the different? Yes, e turn into a. Its hard to spot,
and the next step is do with command pd to show disassembly code again,
but instead of pd we gonna make the code more clean by typing pdf.
[0x000007a8]> pdf
;-- pc:
; DATA XREF from entry0 @ 0x6a0(r)
┌ 32: int main (int argc, char **argv, char **envp);
│ afv: vars(2:sp[0x8..0x10])
│ 0x000007a8 fd7bbfa9 stp x29, x30, [var_10h]!
│ 0x000007ac fd030091 mov x29, sp
│ 0x000007b0 00000090 adrp x0, 0
│ 0x000007b4 00a01f91 add x0, x0, str.Hello__World_ ; 0x7e8 ; "Hello, World!" ; const char *s
│ 0x000007b8 a6ffff97 bl sym.imp.puts ; int puts(const char *s)
│ 0x000007bc 00008052 mov w0, 0
│ 0x000007c0 fd7bc1a8 ldp x29, x30, [sp], 0x10
└ 0x000007c4 c0035fd6 ret
[0x000007a8]>Lets try to analysing the highlighted code, cuz I just understanding these single piece of line.
- After we go from
0x000007e8offset. - We landed into
0x000007a8which is themainfunction. - In the
mainfunction, at the offset0x000007b4it said;
add x0, x0, str.Hello__World_ ; 0x7e8 ; "Hello, World!" ; const char *sAdd the string str.Hello__World_ into x0, which previously the str.Hello__World_ came from 0x7e8 or 0x000007e8.
Radare2 automatically set the comment with ; "Hello, World!" to represent this add x0, x0, str.Hello__World_ disassembly instruction, maybe.
Or to able have a better view we can have a pseudo Decompiled code by typing pdc.
[0x000007a8]> pdc
// callconv: x0 arm64 (x0, x1, x2, x3, x4, x5, x6, x7, stack);
int main (int argc, char **argv, char **envp) {
// DATA XREF from entry0 @ 0x6a0(r)
[var_10h]! = (x29, 2)
x29 = sp
x0 = 0
x0 += str.Hello__World_ // 0x7e8 // "Hello, World!" // const char *s // hit10_0
sym.imp.puts () // int puts("Hello, World!")
w0 = 0
(x29, 2) = 3
}
[0x000007a8]>Also you can compare the decompiled code, with its offset side by side using pdco command.
[0x000007a8]> pdco
0x000007a8 | | // callconv: x0 arm64 (x0, x1, x2, x3, x4, x5, x6, x7, stack);
0x000007a8 | | int main (int argc, char **argv, char **envp) {
0x000007a8 | // DATA XREF from entry0 @ 0x6a0(r)
0x000007a8 | [var_10h]! = (x29, 2)
0x000007ac | x29 = sp
0x000007b0 | x0 = 0
0x000007b4 | x0 += str.Hello__World_ // 0x7e8 // "Hello, World!" // const char *s // hit10_0
0x000007b8 | sym.imp.puts () // int puts("Hello, World!")
0x000007bc | w0 = 0
0x000007c0 | (x29, 2) = 3
0x000007c0 | }
[0x000007a8]>Or even with the disassembly code side by side with set of instruction and the offset by pdca command.
[0x000007a8]> pdca
0x000007a8 | | // callconv: x0 arm64 (x0, x1, x2, x3, x4, x5, x6, x7, stack);
0x000007a8 | | int main (int argc, char **argv, char **envp) {
0x000007a8 | stp x29, x30, [var_10h]! | // DATA XREF from entry0 @ 0x6a0(r)
0x000007a8 | stp x29, x30, [var_10h]! | [var_10h]! = (x29, 2)
0x000007ac | mov x29, sp | x29 = sp
0x000007b0 | adrp x0, 0 | x0 = 0
0x000007b4 | add x0, x0, str.Hello__World_ | x0 += str.Hello__World_ // 0x7e8 // "Hello, World!" // const char *s // hit10_0
0x000007b8 | bl sym.imp.puts | sym.imp.puts () // int puts("Hello, World!")
0x000007bc | mov w0, 0 | w0 = 0
0x000007c0 | ldp x29, x30, [sp], 0x10 | (x29, 2) = 3
0x000007a8 | | }
[0x000007a8]>Lets move forward, how to patch the binary without re-compile it?
First we need to reopen the binary file with write access mode, by typing oo+ radare2 will automatically
reopen the binary file with writable access.
[0x000007a8]> oo+
[0x000007a8]> pdf
;-- pc:
; DATA XREF from entry0 @ 0x6a0(r)
┌ 32: int main (int argc, char **argv, char **envp);
│ afv: vars(2:sp[0x8..0x10])
│ 0x000007a8 fd7bbfa9 stp x29, x30, [var_10h]!
│ 0x000007ac fd030091 mov x29, sp
│ 0x000007b0 00000090 adrp x0, 0
│ 0x000007b4 00a01f91 add x0, x0, str.Hello__World_ ; 0x7e8 ; "Hello, World!" ; const char *s
│ 0x000007b8 a6ffff97 bl sym.imp.puts ; int puts(const char *s)
│ 0x000007bc 00008052 mov w0, 0
│ 0x000007c0 fd7bc1a8 ldp x29, x30, [sp], 0x10
└ 0x000007c4 c0035fd6 ret
[0x000007a8]>If there is no output after oo+, this mean radare2 was in writable mode. You can verify with o command.
[0x000007a8]> o
3 * r-x 0x00011390 hello
4 - rw- 0x00000008 null://8
[0x000007a8]> oo+
[0x000007a8]> o
3 * rwx 0x00011390 hello
4 - rw- 0x00000008 null://8
[0x000007a8]>As you can see it was rwx, which mean read-write-exec permission access (full access).
After we have a write access, lets rewrite Hello, World! value with Hello, Pwnadol!. How?
First we need to find where is the Hello, World! offset really are. By the main references comment it said 0x000007e8.
Let seeking into it, within s 0x000007e8 command.
[0x000007a8]> pdf
;-- pc:
; DATA XREF from entry0 @ 0x6a0(r)
┌ 32: int main (int argc, char **argv, char **envp);
│ afv: vars(2:sp[0x8..0x10])
│ 0x000007a8 fd7bbfa9 stp x29, x30, [var_10h]!
│ 0x000007ac fd030091 mov x29, sp
│ 0x000007b0 00000090 adrp x0, 0
│ ; NULL XREF from main @ 0x7a8(r)
│ 0x000007b4 00a01f91 add x0, x0, str.Hello__World_ ; 0x7e8 ; "Hello, World!" ; const char *s
│ 0x000007b8 a6ffff97 bl sym.imp.puts ; int puts(const char *s)
│ 0x000007bc 00008052 mov w0, 0
│ 0x000007c0 fd7bc1a8 ldp x29, x30, [sp], 0x10
└ 0x000007c4 c0035fd6 ret
[0x000007a8]> s 0x000007e8
[0x000007e8]>And then type pd to show content of the offset, instead of pd lets add pd <Nunmber>,
for example pd 1. This mean the pd command will show the disassembly code by just one line on top.
[0x000007e8]> pd 1
;-- str.Hello__World_:
;-- hit8_0:
; STRN XREF from main @ 0x7b4(r)
0x000007e8 .string "Hello, World!" ; len=14
[0x000007e8]>Then verified with ps command.
[0x000007e8]> pd 1
;-- str.Hello__World_:
;-- hit8_0:
; STRN XREF from main @ 0x7b4(r)
0x000007e8 .string "Hello, World!" ; len=14
[0x000007e8]> ps
Hello, World!
[0x000007e8]>Then replace Hello, World! with Hello, Pwnadol!, by typing wz <String>
for example wz Hello, Pwnadol!. Then just q for quit, that will automatically save.
Note: If the radare2 option is
bin.cache=truethe patch code will goes into RAM instead, rather goes into Disk. So, make sure to make itbin.cache=false, iftruethe patch that you make will not applied.
[0x000007e8]> ps
Hello, World!
[0x000007e8]> wz Hello, Pwnadol!
[0x000007e8]> ps
Hello, Pwnadol!
[0x000007e8]> qAfter we quit, lets rerun the hello binary again, and see the output.
[ root@labs: walkthrough ]># ./hello
Hello, Pwnadol!We Pwnadol it.
But, what if set instruction are x86(-64)? we just have ARM64 machine, how we do x86(-64) executable in ARM64? it can’t, need Proof of Concept? here it is.
[ root@labs: walkthrough ]># x86_64-linux-gnu-gcc hello-world.c -o hello-x86_64
[ root@labs: walkthrough ]># ./hello-x86_64
-bash: ./hello-x86_64: cannot execute binary file: Exec format error
[ root@labs: walkthrough ]># file hello-x86_64 hello
hello-x86_64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c03c4d533ef0a7dc698fa0f64c6c1dae611e94f9, for GNU/Linux 3.2.0, not stripped
hello: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=1666d7a861d5c78f6a7f2bc982042241fd013c40, for GNU/Linux 3.7.0, not stripped
[ root@labs: walkthrough ]>#There is so many antidot out there. But I’ve find the most simple, fast and efficient way to make it worth, with low overhead resource.
What is FEX-Emu #
FEX: Emulation x86 Programs on ARM64
“FEX allows you to run x86 applications on ARM64 Linux devices, similar to qemu-user and box64. It offers broad compatibility with both 32-bit and 64-bit binaries, and it can be used alongside Wine/Proton to play Windows games.”
~ FEX-Emu
FEX-Emu Installation #
There is QT Graphical dependency are required by FEX-Emu to make it run smooth like butter.
sudo apt install qtbase5-dev qtdeclarative5-dev qttools5-dev-tools libqt5svg5-dev fuse3Below is the most important part of installation for FEX-Emu dependencies, to make FEX-Emu not screaming and yelling at you about minimum prerequisite dependency. Install those all.
apt install -y \
git \
cmake \
ninja-build \
pkgconf \
ccache \
clang \
llvm \
lld \
binfmt-support \
libssl-dev \
python3-setuptools \
g++-x86-64-linux-gnu \
libgcc-14-dev-i386-cross \
libgcc-14-dev-amd64-cross \
nasm \
python3-clang \
libstdc++-14-dev-i386-cross \
libstdc++-14-dev-amd64-cross \
libstdc++-14-dev-arm64-cross \
squashfs-tools \
squashfuse \
libc-bin \
libc6-dev-i386-amd64-cross \
lib32stdc++-14-dev-amd64-cross Then build or compile the binary from FEX-Emu git repository source, with this FEX-Emu installation reference.
git clone --recurse-submodules https://github.com/FEX-Emu/FEX.git
cd FEX
mkdir Build
cd Build
CC=clang CXX=clang++ cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DUSE_LINKER=lld -DENABLE_LTO=True -DBUILD_TESTING=False -DENABLE_ASSERTIONS=False -G Ninja ..
ninjaAfter the compilation is done, lets run the FEX-Emu with FEXBash, that will make a new pops up shell.
Which will “for every x86-64 binary inside of new environment, are able to run with ARM64 set instruction”.
[ root@labs: walkthrough ]># uname -m
aarch64
[ root@labs: walkthrough ]># FEXBash
FEXBash root@labs:~/.development/walkthrough> uname -m
x86_64
FEXBash root@labs:~/.development/walkthrough> file hello-x86_64
hello-x86_64: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c03c4d533ef0a7dc698fa0f64c6c1dae611e94f9, for GNU/Linux 3.2.0, not stripped
FEXBash root@labs:~/.development/walkthrough> ./hello-x86_64
Hello, World!
FEXBash root@labs:~/.development/walkthrough>Then we made it, Let try to Pwnadol it too, with ARM64 radare2 executable binary.
[ root@labs: walkthrough ]># r2 -w hello-x86_64
WARN: Relocs has not been applied. Please use `-e bin.relocs.apply=true` or `-e bin.cache=true` next time
-- Use rarun2 to launch your programs with a predefined environment.
[0x00001050]> o
3 * rwx 0x00003ea8 hello-x86_64
4 - rw- 0x00000008 null://8
[0x00001050]> i
fd 3
file hello-x86_64
size 0x3ea8
humansz 15.7K
mode rwx
format elf64
iorw true
block 0x100
type DYN (Shared object file)
arch x86
baddr 0x0
binsz 13985
bintype elf
bits 64
canary false
injprot false
class ELF64
compiler GCC: (Debian 14.2.0-19) 14.2.0
crypto false
endian little
havecode true
intrp /lib64/ld-linux-x86-64.so.2
laddr 0x0
lang c
linenum false
lsyms true
machine AMD x86-64 architecture
nx true
os linux
pic true
relocs true
relro partial
rpath NONE
sanitize false
static false
stripped false
uncaps true
subsys linux
va true
[0x00001050]>See the highlighted, those is a proof for binary data that was x86-64 bit set instruction code.
Lets rewrite the Hello, World! like before.
[0x00001050]> aaa
INFO: Analyze all flags starting with sym. and entry0 (aa)
INFO: Analyze imports (af@@@i)
INFO: Analyze entrypoint (af@ entry0)
INFO: Analyze symbols (af@@@s)
INFO: Running plugin pre-analysis hooks
INFO: Analyze all functions arguments/locals (afva@@F)
INFO: Analyze function calls (aac)
INFO: Analyze len bytes of instructions for references (aar)
INFO: Finding and parsing C++ vtables (avrr)
INFO: Analyzing methods (af @@ method.*)
INFO: Recovering local variables (afva@@@F)
INFO: Type matching analysis for all functions (aaft)
INFO: Propagate noreturn information (aanr)
INFO: Use -AA or aaaa to perform additional experimental analysis
[0x00001050]> iz
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x00002004 0x00002004 13 14 .rodata ascii Hello, World!
[0x00001050]> s 0x00002004
[0x00002004]> ps
Hello, World!
[0x00002004]> wz Hello, Pwnadol!
[0x00002004]> ps
Hello, Pwnadol!
[0x00002004]>qLet me extends the history line, still merge into prev history line.
[0x00001050]> iz
nth paddr vaddr len size section type string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0 0x00002004 0x00002004 13 14 .rodata ascii Hello, World!
[0x00001050]> s 0x00002004
[0x00002004]> ps
Hello, World!
[0x00002004]> wz Hello, Pwnadol!
[0x00002004]> ps
Hello, Pwnadol!
[0x00002004]> q
[ root@labs: walkthrough ]># FEXBash
FEXBash root@labs:~/.development/walkthrough> ./hello-x86_64
Hello, Pwnadol!
FEXBash root@labs:~/.development/walkthrough>DAMMMNNNN! We just succesfully built extensible Pwnadol Exploit Development Homelabs, by just using a $10 TV-Box with Radare2 and FEX-Emu.
