Rewire
Description
This firmware is responsible for managing the CCTV system.
Maybe we can modify it?
Provided Files
- rewire.zip
Writeup
Starting off I inspected the binary.
$ file rewire
rewire: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=0401ed547bd67737e380e6b2ce29d3b944a5b002, for GNU/Linux 3.2.0, not stripped
$ strings rewire
/lib64/ld-linux-x86-64.so.2
__cxa_finalize
__libc_start_main
stdout
puts
fflush
sleep
putchar
__stack_chk_fail
printf
libc.so.6
GLIBC_2.4
GLIBC_2.34
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
=TxeNt
&fHW{H
Q#:'%<H
5JT+
GLOBAL key is invalid
Disabling CCTV feed...
Running CCTV feed...
NexTek Vision Pro
CCTV Solution
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Scrt1.o
__abi_tag
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux
completed.0
__do_global_dtors_aux_fini_array_entry
frame_dummy
__frame_dummy_init_array_entry
chall.c
__FRAME_END__
_DYNAMIC
__GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
putchar@GLIBC_2.2.5
__libc_start_main@GLIBC_2.34
_ITM_deregisterTMCloneTable
stdout@GLIBC_2.2.5
puts@GLIBC_2.2.5
_edata
_fini
__stack_chk_fail@GLIBC_2.4
printf@GLIBC_2.2.5
disable_cctv
__data_start
__gmon_start__
__dso_handle
_IO_stdin_used
enable_cctv
fflush@GLIBC_2.2.5
_end
__bss_start
main
__TMC_END__
_ITM_registerTMCloneTable
sleep@GLIBC_2.2.5
__cxa_finalize@GLIBC_2.2.5
_init
.symtab
.strtab
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment
Nothing too interesting, so I decompiled the binary using ghidra
.
int main(void) {
puts("NexTek Vision Pro");
puts("CCTV Solution");
enable_cctv();
return 0;
}
void enable_cctv(void) {
puts("\nRunning CCTV feed...");
do {
putchar(0x2e);
fflush(stdout);
sleep(1);
} while( true );
}
void disable_cctv(void) {
long in_FS_OFFSET;
ulong local_58;
undefined8 local_48;
undefined8 local_40;
undefined8 local_38;
undefined8 local_30;
undefined8 local_28;
undefined8 local_20;
undefined4 local_18;
undefined local_14;
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
if (key != 0x4e657854) {
puts("GLOBAL key is invalid");
}
puts("\nDisabling CCTV feed...");
local_48 = 0x7b57486626061930;
local_40 = 0x3c25273a23511c2f;
local_38 = 0x110427217e1c2767;
local_30 = 0x7e010a313e154926;
local_28 = 0x7a0d0f0b3c0a2737;
local_20 = 0x2b034f62115a5920;
local_18 = 0x2b544a35;
local_14 = 0x29;
for (local_58 = 0; local_58 < 0x35; local_58 = local_58 + 1) {
*(byte *)((long)&local_48 + local_58) =
*(byte *)((long)&local_48 + local_58) ^ (byte)(key >> (sbyte)(((uint)local_58 & 3) << 3));
}
printf("%s",&local_48);
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
The main
function seems to call the enable_cctv
function which doesn’t do anything apart from printing some uninteresting stuff.
The disable_cctv
function which contains actual content doesn’t get called at all.
Knowing this I patched the memory address
of the called function enable_cctv
to that of disable_cctv
.
Using radare2
for binary-patching:
$ r2 -w ./rewire
[0x00001100]> afl
0x000010a0 1 11 sym.imp.putchar
0x000010b0 1 11 sym.imp.puts
0x000010c0 1 11 sym.imp.__stack_chk_fail
0x000010d0 1 11 sym.imp.printf
0x000010e0 1 11 sym.imp.fflush
0x000010f0 1 11 sym.imp.sleep
0x00001100 1 37 entry0
0x00001130 4 34 sym.deregister_tm_clones
0x00001160 4 51 sym.register_tm_clones
0x000011a0 5 54 entry.fini0
0x00001090 1 11 fcn.00001090
0x000011e0 1 9 entry.init0
0x0000138c 1 13 sym._fini
0x000011e9 8 301 sym.disable_cctv
0x00001316 2 60 sym.enable_cctv
0x00001352 1 55 main
0x00001000 3 27 sym._init
[0x00001100]> pdf @ main
; DATA XREF from entry0 @ 0x1118(r)
┌ 55: int main (int argc, char **argv, char **envp);
│ 0x00001352 f30f1efa endbr64
│ 0x00001356 55 push rbp
│ 0x00001357 4889e5 mov rbp, rsp
│ 0x0000135a 488d05ea0c.. lea rax, str.NexTek_Vision_Pro ; 0x204b ; "NexTek Vision Pro"
│ 0x00001361 4889c7 mov rdi, rax
│ 0x00001364 e847fdffff call sym.imp.puts ; int puts(const char *s)
│ 0x00001369 488d05ed0c.. lea rax, str.CCTV_Solution ; 0x205d ; "CCTV Solution"
│ 0x00001370 4889c7 mov rdi, rax
│ 0x00001373 e838fdffff call sym.imp.puts ; int puts(const char *s)
│ 0x00001378 b800000000 mov eax, 0
│ 0x0000137d e894ffffff call sym.enable_cctv
│ 0x00001382 b800000000 mov eax, 0
│ 0x00001387 5d pop rbp
└ 0x00001388 c3 ret
[0x00001100]> s 0x137d
[0x0000137d]> wx e8 67 fe ff ff
[0x0000137d]> pdf @ main
; DATA XREF from entry0 @ 0x1118(r)
┌ 55: int main (int argc, char **argv, char **envp);
│ 0x00001352 f30f1efa endbr64
│ 0x00001356 55 push rbp
│ 0x00001357 4889e5 mov rbp, rsp
│ 0x0000135a 488d05ea0c.. lea rax, str.NexTek_Vision_Pro ; 0x204b ; "NexTek Vision Pro"
│ 0x00001361 4889c7 mov rdi, rax
│ 0x00001364 e847fdffff call sym.imp.puts ; int puts(const char *s)
│ 0x00001369 488d05ed0c.. lea rax, str.CCTV_Solution ; 0x205d ; "CCTV Solution"
│ 0x00001370 4889c7 mov rdi, rax
│ 0x00001373 e838fdffff call sym.imp.puts ; int puts(const char *s)
│ 0x00001378 b800000000 mov eax, 0
│ 0x0000137d e867feffff call sym.disable_cctv
│ 0x00001382 b800000000 mov eax, 0
│ 0x00001387 5d pop rbp
└ 0x00001388 c3 ret
Executing the binary now enters the disable_cctv
function.
$ ./rewire
ion Pro
CCTV Solution
GLOBAL key is invalid
Disabling CCTV feed...
ߧ����������ՙ�∙��Ι��������ؙ��䱠����ύ�������r
Looking at the disassembled code we can see a required key.
if (key != 0x4e657854) {
puts("GLOBAL key is invalid");
}
[0x00001100]> afl
0x000010a0 1 11 sym.imp.putchar
0x000010b0 1 11 sym.imp.puts
0x000010c0 1 11 sym.imp.__stack_chk_fail
0x000010d0 1 11 sym.imp.printf
0x000010e0 1 11 sym.imp.fflush
0x000010f0 1 11 sym.imp.sleep
0x00001100 1 37 entry0
0x00001130 4 34 sym.deregister_tm_clones
0x00001160 4 51 sym.register_tm_clones
0x000011a0 5 54 entry.fini0
0x00001090 1 11 fcn.00001090
0x000011e0 1 9 entry.init0
0x0000138c 1 13 sym._fini
0x000011e9 8 301 sym.disable_cctv
0x00001316 2 60 sym.enable_cctv
0x00001352 1 55 main
0x00001000 3 27 sym._init
[0x00001100]> pdf @ sym.disable_cctv
; CALL XREF from main @ 0x137d(x)
┌ 301: sym.disable_cctv ();
│ afv: vars(11:sp[0x10..0x58])
│ 0x000011e9 f30f1efa endbr64
│ 0x000011ed 55 push rbp
│ 0x000011ee 4889e5 mov rbp, rsp
│ 0x000011f1 4883ec50 sub rsp, 0x50
│ 0x000011f5 64488b0425.. mov rax, qword fs:[0x28]
│ 0x000011fe 488945f8 mov qword [var_8h], rax
│ 0x00001202 31c0 xor eax, eax
│ 0x00001204 8b05062e0000 mov eax, dword [obj.key] ; hit1_0
│ ; [0x4010:4]=0xdeadbeef
│ 0x0000120a 3d5478654e cmp eax, 0x4e657854 ; 'TxeN'
│ ┌─< 0x0000120f 740f je 0x1220
│ │ 0x00001211 488d05ec0d.. lea rax, str.GLOBAL_key_is_invalid ; 0x2004 ; "GLOBAL key is invalid"
│ │ 0x00001218 4889c7 mov rdi, rax
│ │ 0x0000121b e890feffff call sym.imp.puts ; int puts(const char *s)
│ └─> 0x00001220 488d05f30d.. lea rax, str._nDisabling_CCTV_feed... ; 0x201a ; "\nDisabling CCTV feed..."
│ 0x00001227 4889c7 mov rdi, rax
│ 0x0000122a e881feffff call sym.imp.puts ; int puts(const char *s)
│ 0x0000122f 48b8301906.. movabs rax, 0x7b57486626061930
│ 0x00001239 48ba2f1c51.. movabs rdx, 0x3c25273a23511c2f ; '/\x1cQ#:\'%<'
│ 0x00001243 488945c0 mov qword [var_40h], rax
│ 0x00001247 488955c8 mov qword [var_38h], rdx
│ 0x0000124b 48b867271c.. movabs rax, 0x110427217e1c2767
│ 0x00001255 48ba264915.. movabs rdx, 0x7e010a313e154926
│ 0x0000125f 488945d0 mov qword [var_30h], rax
│ 0x00001263 488955d8 mov qword [var_28h], rdx
│ 0x00001267 48b837270a.. movabs rax, 0x7a0d0f0b3c0a2737 ; '7\'\n<\v\x0f\rz'
│ 0x00001271 48ba20595a.. movabs rdx, 0x2b034f62115a5920
│ 0x0000127b 488945e0 mov qword [var_20h], rax
│ 0x0000127f 488955e8 mov qword [var_18h], rdx
│ 0x00001283 c745f0354a.. mov dword [var_10h], 0x2b544a35 ; '5JT+'
│ 0x0000128a c645f429 mov byte [var_ch], 0x29 ; ')'
│ 0x0000128e 48c745b835.. mov qword [var_48h], 0x35 ; '5'
│ 0x00001296 48c745b000.. mov qword [var_50h], 0
│ ┌─< 0x0000129e eb3a jmp 0x12da
│ ┌──> 0x000012a0 488d55c0 lea rdx, [var_40h]
│ ╎│ 0x000012a4 488b45b0 mov rax, qword [var_50h]
│ ╎│ 0x000012a8 4801d0 add rax, rdx
│ ╎│ 0x000012ab 0fb630 movzx esi, byte [rax]
│ ╎│ 0x000012ae 8b155c2d0000 mov edx, dword [obj.key] ; hit1_0
│ ╎│ ; [0x4010:4]=0xdeadbeef
│ ╎│ 0x000012b4 488b45b0 mov rax, qword [var_50h]
│ ╎│ 0x000012b8 83e003 and eax, 3
│ ╎│ 0x000012bb c1e003 shl eax, 3
│ ╎│ 0x000012be 89c1 mov ecx, eax
│ ╎│ 0x000012c0 d3fa sar edx, cl
│ ╎│ 0x000012c2 89d0 mov eax, edx
│ ╎│ 0x000012c4 31c6 xor esi, eax
│ ╎│ 0x000012c6 89f2 mov edx, esi
│ ╎│ 0x000012c8 488d4dc0 lea rcx, [var_40h]
│ ╎│ 0x000012cc 488b45b0 mov rax, qword [var_50h]
│ ╎│ 0x000012d0 4801c8 add rax, rcx
│ ╎│ 0x000012d3 8810 mov byte [rax], dl
│ ╎│ 0x000012d5 488345b001 add qword [var_50h], 1
│ ╎│ ; CODE XREF from sym.disable_cctv @ 0x129e(x)
│ ╎└─> 0x000012da 488b45b0 mov rax, qword [var_50h]
│ ╎ 0x000012de 483b45b8 cmp rax, qword [var_48h]
│ └──< 0x000012e2 72bc jb 0x12a0
│ 0x000012e4 488d45c0 lea rax, [var_40h]
│ 0x000012e8 4889c6 mov rsi, rax
│ 0x000012eb 488d05400d.. lea rax, [0x00002032] ; "%s"
│ 0x000012f2 4889c7 mov rdi, rax
│ 0x000012f5 b800000000 mov eax, 0
│ 0x000012fa e8d1fdffff call sym.imp.printf ; int printf(const char *format)
│ 0x000012ff 90 nop
│ 0x00001300 488b45f8 mov rax, qword [var_8h]
│ 0x00001304 64482b0425.. sub rax, qword fs:[0x28]
│ ┌─< 0x0000130d 7405 je 0x1314
│ │ 0x0000130f e8acfdffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
│ └─> 0x00001314 c9 leave
└ 0x00001315 c3 ret
When I disassambled the function I found that the key is set to =0xdeadbeef
per default.
Knowing this I swtiched the deadbeef
with the actual required key
.
[0x00001100]> /x ef be ad de
0x00004010 hit5_0 efbeadde
[0x00001100]> s 0x00004010
[0x00004010]> wx 54 78 65 4e
After patching the binary, updating the global-var key
and executing it again, I got the flag which concludes this challenge.
./rewire
NexTek Vision Pro
CCTV Solution
Disabling CCTV feed...
dach2025{d4mn_@r3_y0u_a_r1pperd0c_or_wh4t!?_67fea21e}