Rotterdam
The 1st Part of Kernel
│ │ 0x0040117e 498b00 mov rax, qword [r8]
│ │ 0x00401181 4831c3 xor rbx, rax
│ │ 0x00401184 48b8569ad581. movabs rax, 0x4b227ff781d59a56
│ │ 0x0040118e 4839d8 cmp rax, rbx
│ │ 0x00401191 0f856b030000 jne loc._BadFlag
In rax is the first 8 bytes of kernel, the the expected result of xoring rax and rbx is 0x4b227ff781d59a56. So
Value in rbx is calculated in *_Step1*, it seems like a input-irralevant value. A simple way to get the value would be run in debugger, break at specific point and read the value.
│ │ 0x0040112d 4831db xor rbx, rbx
│ │ 0x00401130 b8c5000000 mov eax, 0xc5 ; 197
│ │ 0x00401135 e8a6060000 call loc._GetTData
│ │ 0x0040113a 4889c3 mov rbx, rax
│ │ 0x0040113d b8ab000000 mov eax, 0xab ; 171
│ │ 0x00401142 e899060000 call loc._GetTData
│ │ 0x00401147 4801c3 add rbx, rax
│ │ 0x0040114a b8ab030000 mov eax, 0x3ab ; 939
│ │ 0x0040114f e88c060000 call loc._GetTData
│ │ 0x00401154 4801c3 add rbx, rax
│ │ 0x00401157 b877020000 mov eax, 0x277 ; 631
│ │ 0x0040115c e87f060000 call loc._GetTData
│ │ 0x00401161 4801c3 add rbx, rax
│ │ 0x00401164 b801010000 mov eax, 0x101 ; 257
│ │ 0x00401169 e872060000 call loc._GetTData
│ │ 0x0040116e 4801c3 add rbx, rax
│ │ 0x00401171 b887000000 mov eax, 0x87 ; 135
│ │ 0x00401176 e865060000 call loc._GetTData
│ │ 0x0040117b 4801c3 add rbx, rax
rbx read is 0x2a460d92f5a1f504, so here is the first part, Rotterda.
s = hex(0x2a460d92f5a1f504^0x4b227ff781d59a56)[2:]
param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)]))))
print('part1:', param)
kernel.append(param)
The 2nd Part of Kernel
│ │ 0x004011d6 b9ffffffff mov ecx, 0xffffffff ; -1
│ │ 0x004011db 4821c8 and rax, rcx
│ │ 0x004011de 4831db xor rbx, rbx
│ │ 0x004011e1 418b5809 mov ebx, dword [r8 + 9]
│ │ 0x004011e5 4801d8 add rax, rbx
│ │ 0x004011e8 48b946ff6457. movabs rcx, 0x15764ff46
│ │ 0x004011f2 4839c8 cmp rax, rcx
│ │ 0x004011f5 0f8507030000 jne loc._BadFlag
In *_Step3* the second part is checked, it should satisfy condition
Same way to get value in rax, so the second part is P0rt.
v = data[343]
s = hex(0x15764ff46 - (v&0xffffffff))[2:]
param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)]))))
print('part2:', param)
kernel.append(param)
The 3rd Part of Kernel
The third part located in *_Step4a*, it needs to satisfy condition
│ │ 0x004012d7 498b400e mov rax, qword [r8 + 0xe]
│ │ 0x004012db 4889c1 mov rcx, rax
│ │ 0x004012de 48b8ffffffff. movabs rax, 0xffffffffff ; 1099511627775
│ │ 0x004012e8 4821c1 and rcx, rax
│ │ 0x004012eb 4821c3 and rbx, rax
│ │ 0x004012ee 4839d9 cmp rcx, rbx
│ │ 0x004012f1 0f820b020000 jb loc._BadFlag
│ │ 0x004012f7 4829d9 sub rcx, rbx
│ │ 0x004012fa 48b85335a5d4. movabs rax, 0x17d4a53553
│ │ 0x00401304 4839c1 cmp rcx, rax
│ │ 0x00401307 0f85f5010000 jne loc._BadFlag
rbx got from r2 is 0x4d998c32ff, so the part is Rh1ne.
s = hex(0x4d998c32ff+0x17d4a53553)[2:]
param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)]))))
print('part3:', param)
kernel.append(param)
The 4th Part of Kernel
│ │ 0x00401395 498b4014 mov rax, qword [r8 + 0x14]
│ │ 0x00401399 4889c1 mov rcx, rax
│ │ 0x0040139c 48b8ffffffff. movabs rax, 0xffffffffff ; 1099511627775
│ │ 0x004013a6 4821c1 and rcx, rax
│ │ 0x004013a9 4889c8 mov rax, rcx
│ │ 0x004013ac 4831d2 xor rdx, rdx
│ │ 0x004013af 48f7e3 mul rbx
│ │ 0x004013b2 4989c2 mov r10, rax
│ │ 0x004013b5 4989d3 mov r11, rdx
│ │ 0x004013b8 48b8beb9770a. movabs rax, 0x37f7d400a77b9be
│ │ 0x004013c2 4c39d0 cmp rax, r10
│ │ 0x004013c5 0f8537010000 jne loc._BadFlag
│ │ 0x004013cb 48b838495487. movabs rax, 0x6a87544938
│ │ 0x004013d5 4c39d8 cmp rax, r11
│ │ 0x004013d8 0f8524010000 jne loc._BadFlag
The 4th part is supposed to equal to 0x6a8754493837f7d400a / rbx
. rbx is 0xdeb4fa4d998c32ff, it makes the result a float-point number.
s = hex(0x6a8754493837f7d400a77b9be//0xdeb4fa4d998c32ff)[2:]
param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)]))))
Tried out different values at for the first character of word ?l1tz. - 4l1tz leads to r11 = 0x6a8754492b - 6l1tz leads to r11 = 0x6a8754492d
So if we want the result ends with 0x38, we need to make the first characterc chr(ord('6')+(0x38-(0x2d))) = 'A'
, but Alitz leads to r11 = 0x6a87544937, whilst B is working. So the 4th part is Bl1tz. param = ‘B’ + param print(‘part4:’, param) kernel.append(param)
### The 5th Part of Kernel
```asm
│ │ 0x00401480 4889d8 mov rax, rbx
│ │ 0x00401483 48f7f1 div rcx
│ │ 0x00401486 4989c2 mov r10, rax
│ │ 0x00401489 4989d3 mov r11, rdx
│ │ 0x0040148c 48b89da04000. movabs rax, loc.congrats ; 0x40a09d ; "Congrats!! You found the flag!!\n"
│ │ 0x00401496 b852534f00 mov eax, 0x4f5352 ; 'RSO'
│ │ 0x0040149b 4c39d0 cmp rax, r10
│ │ 0x0040149e 7562 jne loc._BadFlag
│ │ 0x004014a0 48b89da04000. movabs rax, loc.congrats ; 0x40a09d ; "Congrats!! You found the flag!!\n"
│ │ 0x004014aa 48b8bedb3059. movabs rax, 0x55930dbbe
│ │ 0x004014b4 4c39d8 cmp rax, r11
│ │ 0x004014b7 7549 jne loc._BadFlag
We need to find a divident makes
Value in rbx is 0x1f6ff5218c40de9c, so we have the last part W1tte.
s = hex((0x1f6ff5218c40de9c-0x55930dbbe)//0x4f5352)[2:]
param = ''.join(reversed(''.join(map(chr, [int(s[i:i+2],16) for i in range(0,len(s),2)]))))
print('part5:', param)
kernel.append(param)
The Splitter
The splitter check comes after each part, it needs to be *"_"*.
So, join all the parts we have the kernel