---
# System prepended metadata

title: HW3 Writeup
tags: [NTU]

---

###### tags: `NTU`

<style>
        .markdown-body {
            font-family: 'Arial', -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
/*             font-size: 14px; */
            line-height: 1.6;
        } !important;
</style>

# HW3 Writeup

## fifo

fifo is a feature of Linux called named pipes. This program will span another process by calling `fork`, and it also calls a lot of syscalls. Therefore, after decompiling fifo, I tried `strace` to trace all the syscalls that fifo called.

![](https://i.imgur.com/LwH1ctD.png)

If I remove the file under /tmp directory and run `strace` on fifo, then I can see the arguments passed to the syscalls. And luckily the flag is in one of the arguments.

```
❯ strace -f ./fifo
execve("./fifo", ["./fifo"], 0x7fff26fba018 /* 26 vars */) = 0
...
openat(AT_FDCWD, "/tmp/khodsmeogemgoe", O_WRONLY|O_CREAT|O_TRUNC, 0744) = 3
write(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 \21\0\0\0\0\0\0"..., 14464) = 14464
close(3)                                = 0
clone(strace: Process 3641 attached
child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd96be34810) = 3641
[pid  3640] stat("/tmp/bnpkevsekfpk3",  <unfinished ...>
[pid  3641] setsid( <unfinished ...>
[pid  3640] <... stat resumed> {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0
[pid  3641] <... setsid resumed> )      = 3641
[pid  3640] mknod("/tmp/bnpkevsekfpk3/aw3movsdirnqw", S_IFIFO|0600 <unfinished ...>
[pid  3641] execve("/tmp/khodsmeogemgoe", ["/tmp/khodsmeogemgoe"], NULL <unfinished ...>
[pid  3640] <... mknod resumed> )       = -1 EEXIST (File exists)
[pid  3640] openat(AT_FDCWD, "/tmp/bnpkevsekfpk3/aw3movsdirnqw", O_WRONLY <unfinished ...>
[pid  3641] <... execve resumed> )      = 0
[pid  3641] brk(NULL)                   = 0x558a4c692000
[pid  3641] arch_prctl(0x3001 /* ARCH_??? */, 0x7ffcea6d6350) = -1 EINVAL (Invalid argument)
[pid  3641] access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
[pid  3641] openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
[pid  3641] fstat(3, {st_mode=S_IFREG|0644, st_size=50099, ...}) = 0
[pid  3641] mmap(NULL, 50099, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa2369c8000
[pid  3641] close(3)                    = 0
[pid  3641] openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
[pid  3641] read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360q\2\0\0\0\0\0"..., 832) = 832
[pid  3641] pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
[pid  3641] pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
[pid  3641] pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
[pid  3641] fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0
[pid  3641] mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa2369c6000
[pid  3641] pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
[pid  3641] pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32
[pid  3641] pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68
[pid  3641] mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fa2367d4000
[pid  3641] mprotect(0x7fa2367f9000, 1847296, PROT_NONE) = 0
[pid  3641] mmap(0x7fa2367f9000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fa2367f9000
[pid  3641] mmap(0x7fa236971000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7fa236971000
[pid  3641] mmap(0x7fa2369bc000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fa2369bc000
[pid  3641] mmap(0x7fa2369c2000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa2369c2000
[pid  3641] close(3)                    = 0
[pid  3641] arch_prctl(ARCH_SET_FS, 0x7fa2369c7540) = 0
[pid  3641] mprotect(0x7fa2369bc000, 12288, PROT_READ) = 0
[pid  3641] mprotect(0x558a4b08e000, 4096, PROT_READ) = 0
[pid  3641] mprotect(0x7fa236a02000, 4096, PROT_READ) = 0
[pid  3641] munmap(0x7fa2369c8000, 50099) = 0
[pid  3641] openat(AT_FDCWD, "/tmp/bnpkevsekfpk3/aw3movsdirnqw", O_RDONLY <unfinished ...>
[pid  3640] <... openat resumed> )      = 3
[pid  3641] <... openat resumed> )      = 3
[pid  3640] write(3, "H\211\345\270)\0\0\0\277\2\0\0\0\276\2\0\0\0\272\21\0\0\0\17\5\211E\370H\211\307\270"..., 216 <unfinished ...>
[pid  3641] read(3,  <unfinished ...>
[pid  3640] <... write resumed> )       = 216
[pid  3641] <... read resumed> "H\211\345\270)\0\0\0\277\2\0\0\0\276\2\0\0\0\272\21\0\0\0\17\5\211E\370H\211\307\270"..., 216) = 216
[pid  3640] close(3 <unfinished ...>
[pid  3641] close(3 <unfinished ...>
[pid  3640] <... close resumed> )       = 0
[pid  3641] <... close resumed> )       = 0
[pid  3640] exit_group(0 <unfinished ...>
[pid  3641] unlink("/tmp/bnpkevsekfpk3/aw3movsdirnqw" <unfinished ...>
[pid  3640] <... exit_group resumed>)   = ?
[pid  3641] <... unlink resumed> )      = 0
[pid  3641] socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
[pid  3640] +++ exited with 0 +++
setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
sendto(3, "FLAG{FIFO_1s_D1sGVsTln9}", 24, 0, {sa_family=AF_INET, sin_port=htons(8877), sin_addr=inet_addr("192.168.130.1")}, 16) = 24
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0}, NULL) = 0
sendto(3, "FLAG{FIFO_1s_D1sGVsTln9}", 24, 0, {sa_family=AF_INET, sin_port=htons(8877), sin_addr=inet_addr("192.168.130.1")}, 16) = 24
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0}, NULL) = 0
```

## giveUflag

This problem is much easier than I thought to be. After decompiling the executable, I guessed that we need to run to the line that prints out the content of `Buffer`, shown in the figure below.

![](https://i.imgur.com/oAxWMgG.png)

However, it stuck whenever I want to reach the line. So I used x64dbg and found out the function pointer `v5` and `v4` pointed to `kernel32.sleep`, each called with a very large number resulted in unresponsiveness of the program. To circumvent it, I changed the value of the register `rcx` which stored the large number to 1, so it will only sleep for a short period. And then I can finally get the flag.
![](https://i.imgur.com/w0F9z0x.png)


## nani

This problem has two checks for the environment, one for the presence of a debugger and one for VM. It is easy to circumvent debugger, just install ScyllaHide and simply turn all the flags on. And for the VM, I replace the original instruction `cpuid` with `nop`s, so it won't match any of the predefined VM names in the program.

The next step is to trace the exception handler. First, I tried to use PE bear to trace the address of the handler. But it didn't lead me to the place I want to trace.

![](https://i.imgur.com/MiRtRwO.png)


In the end, I traced with x64dbg directly by stepping into where the program called RaiseException.

So we will have unwinding process below.

```
User -> System -> User
```

The final `User` code is the exception handler. Stop it right before its exit, and we can finally get the flag.

![](https://i.imgur.com/2kTkF1M.png)

