-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
2376 lines (2376 loc) · 764 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>http://example.com</id>
<title>4n6 & k8s</title>
<link href="http://example.com" />
<updated>2023-08-06T18:00:00.000Z</updated>
<category term="kubernetes" />
<entry>
<id>http://example.com/2023/08/06/Writeups/quals2023/</id>
<title>Securinets Quals CTF 23 Forensics & Misc Challenges Writeup</title>
<link rel="alternate" href="http://example.com/2023/08/06/Writeups/quals2023/"/>
<content type="html"><h2 id="the-ctf"><a class="markdownIt-Anchor" href="#the-ctf">#</a> The CTF</h2>
<p>Securinets Quals CTF was this Securinets generation’s first CTF event on CTFTime where all the big teams have demonstrated therir skills to get to the finals in Tunisia this late-September.</p>
<p>We present four challenging tasks, two forensics involving Containerization and Kubernetes, Hiberfil.sys, Restore Point, and Crypto-currency Wallet, and two Misc involving Steganography and Reverse Engineering a set-top-box firmware and analyzing its memory dump.</p>
<p>Congratulations to SKSD, r3kapig, Hexagon for earning the top 3 spots in the CTF, and we deliver a special apperciation to the Securinets masterminds for their hard work and dedication to make this event a huge success, and we hope to see you all in the finals.</p>
<p>First, our new CTF weight:</p>
<p><img data-src="https://i.imgur.com/n9elp7B.png" alt=""></p>
<p>The scoreboard:</p>
<p><img data-src="https://i.imgur.com/eYBMvzh.jpg" alt=""></p>
<h2 id="the-betrayers"><a class="markdownIt-Anchor" href="#the-betrayers">#</a> The Betrayers</h2>
<p><img data-src="https://i.imgur.com/lAWQkqM.png" alt=""></p>
<h3 id="description"><a class="markdownIt-Anchor" href="#description">#</a> Description:</h3>
<p>An IT company provides a critical service to customers. One day, the service is attacked by DDoS. The Attack is originated from within the company’s internal network, and that each compromised host was sending a large number of requests to the server.</p>
<p>The attack occurred shortly after the company installed a new patch to one of its software programs. Every new version should be hosted by a special web server with DNS record in the private network but this time the new version is hosted by the Technical Director server!!!</p>
<p>The Technical Director is in trouble and he said that is not the attacker!</p>
<p>The strange thing is that the program is deleted directly after the blue team figure out the attack!</p>
<p>We need to get a release from that version and figure out how the attack occur!</p>
<blockquote>
<p>The binary expect to do DDoS attack on specifc IP. In this challenge we changed the IP and the rate of send requests</p>
</blockquote>
<p>Author: <strong>Raf²</strong></p>
<p>File: <span class="exturl" data-url="aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xUU5VbmQ0Q0VYWHJxQUM5Y252bFVFLUFXLWFlV0RzemQvdmlldz91c3A9c2hhcmluZw==">Download</span></p>
<h3 id="write-up"><a class="markdownIt-Anchor" href="#write-up">#</a> Write-up</h3>
<p>Ok Let’s figure out what is happen. We get the disk image of the Technical Director system. The system that host the new program patch. (It must not be this one)</p>
<p>Let’s start figure out what softwares are installed and check the history of the system.</p>
<p>Oh as expected there is a mail software. It’s thunderbird. We will check it later.<br>
<img data-src="https://i.imgur.com/y6i9bfK.png" alt=""></p>
<p>Let’s Check the browsing history of the system and check what is going on here! We found Edge only here!</p>
<p>Go to <code>C:\Users\Kong Office\AppData\Local\Edge\UserData\Default</code> and check the <code>History</code> database</p>
<p><img data-src="https://i.imgur.com/E1oNXEo.png" alt=""></p>
<p>After checking every single link and search. we found searchs about whatsapp desktop how to install it and official whatsapp download website is visited.</p>
<p><img data-src="https://i.imgur.com/geAQL42.png" alt=""></p>
<p>Thunderbird is installed for sure. But still no clue for whatsapp for now. Let’s see what we have on the inbox now! It’s time to check the mails! To check the inbox you can go to <code>C:\Users\Kong Office\AppData\Roaming\Thunderbird\Profiles\0ppw4tlt.default-release\ImapMail\imap.gmail.com</code> and investigate the <code>INBOX</code> file</p>
<p><img data-src="https://i.imgur.com/1J4A8Bx.png" alt=""></p>
<p>You can open the file using any text editor to check the mails but it’s the worst way. you’ll find the attachements encoded to base 64 and many trashy details</p>
<p>You’ll get an ugly view like this if you open it with vscode.<br>
<img data-src="https://i.imgur.com/bH5fHr5.png" alt=""></p>
<p>But you can choose any thunderbird inbox viewer available in the internet. I tried a random one and i got a better exeperience to understand what happen.</p>
<p><img data-src="https://i.imgur.com/6T7zVMC.png" alt=""></p>
<p>Let’s summerize what we found. One mail telling that the kubernetes cluster is updgraded successfully from the platform engineer, another one from a system adminstration telling the Technical Director about the security updates. Another one from <code>Securinets INSAT</code> asking for sponsorship to the National Cyber Security Congress! And the suspicision one is from a dummy mail <code>[email protected]</code> . In this mail we found a clue!<br>
A stranger tell the Technical Director about deploying a malicious binary and send a mega link! Ahhh Protected one</p>
<p><img data-src="https://i.imgur.com/zalrPXh.png" alt=""></p>
<p>The link lead you to a wordlist that have strong and secure passwords. The mail talks about subsystem!! What a subsystem? Is it a <code>WSL</code> ??</p>
<p><img data-src="https://i.imgur.com/1Sfnhxu.png" alt=""></p>
<p>and here we finished mail browser history and mail investigation. still the whatsapp thing! Where is whatsapp hide his data?? good question. Checking AppData don’t help us. We didn’t find any WhatsApp directory!</p>
<p>After googling we found that there is some whatsapp version can store his data inside <code>%AppData%\Local\Packages</code> . Let’s check that folder and Bingoo!! We found whatsapp directory! WhatsApp was installed here! Let’s see what we can do here!</p>
<p><img data-src="https://i.imgur.com/4x79Dni.png" alt=""></p>
<p>You can find some conversation inside <code>messages.db</code> file. It might be encrypted and it might be decrypted. Let’s try to open this database and see what we can find here!</p>
<p><img data-src="https://i.imgur.com/mfM1duI.png" alt=""></p>
<p>I am chocked!! Two employees were behind all this!!<br>
Two employees hate the director and they want to be in a trouble!</p>
<p>The attackers talks about encryption and subsystem password and they are shocked because the system is windows! and yes the mega decryption key is shared in this discussion. They send the mail to the director to make it in trouble!!</p>
<p><img data-src="https://i.imgur.com/8ATiHDP.png" alt=""></p>
<p>Let’s download that wordlist and check the powershell history commands! I am sure there is something there. Because I found Hyber-V directory in random place while investigating. The history is stored in <code>%userprofile%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history. txt</code></p>
<p><img data-src="https://i.imgur.com/GnecotB.png" alt=""></p>
<p>Yeah! Everything is cleared now! subsytem, subsystem! They are talking about WSL. WSL is installed here! and it used to host the malicious program! But what they does mean by encryption and the password. Mmmmm I guess we will face some cracking in the few next minutes!</p>
<p>Let’s check WSL now! Where is windows store the WSL? Just check <code>%userprofile%\AppData\Local\Packages</code></p>
<p><img data-src="https://i.imgur.com/wIfONXj.png" alt=""></p>
<p>Let’s mount this vhdx disk now in our Linux/WSL and check the files in this system. You can use <code>libguestfs-tools</code> to achieve this.</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ sudo apt-get install libguestfs-tools</span><br></pre></td></tr></table></figure>
<p>Then, you can mount now the wsl disk image:<br>
<img data-src="https://i.imgur.com/0QqjpLl.png" alt=""></p>
<p>We found a user named <code>Kong</code> and have a home directory. Let’s check his files and bash history!</p>
<p><img data-src="https://i.imgur.com/W7p1CnE.png" alt=""></p>
<p>Let’s start with <code>.bash_history</code> first. It’s my number one rule!<br>
<img data-src="https://i.imgur.com/7kXO7nj.png" alt=""></p>
<p>Wow! The attacker configure wsl.conf then install docker! Mmm He configure it to be boot with systemd!<br>
Then he installed something called kind, After that he download <code>kubectl</code> ! Kubectl??? Ah It’s <code>Kubernetes</code> time!</p>
<p>But what is kind? Searching on it. I found that kind is Kubernetes inside Docker. It’s a lightweight kubernetes cluster.</p>
<p>There is 3 yaml files. For sure there are worth to check! Let’s see what is inside these files!</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">### k-config.yaml content ####</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Cluster</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">kind.x-k8s.io/v1alpha4</span></span><br><span class="line"><span class="attr">networking:</span></span><br><span class="line"> <span class="attr">podSubnet:</span> <span class="string">&quot;10.244.0.0/16&quot;</span></span><br><span class="line"> <span class="attr">serviceSubnet:</span> <span class="string">&quot;10.96.0.0/12&quot;</span></span><br><span class="line"> <span class="comment"># the default CNI will not be installed</span></span><br><span class="line"> <span class="attr">disableDefaultCNI:</span> <span class="literal">false</span></span><br><span class="line"> </span><br><span class="line"><span class="attr">nodes:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">role:</span> <span class="string">control-plane</span></span><br><span class="line"> <span class="comment"># add a mount from /path/to/my/files on the host to /files on the node</span></span><br><span class="line"> <span class="attr">extraMounts:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">hostPath:</span> <span class="string">/etc/crio/crio.conf</span></span><br><span class="line"> <span class="attr">containerPath:</span> <span class="string">/etc/crio/crio.conf</span></span><br><span class="line"> <span class="comment"># optional: if set, the mount is read-only.</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">readOnly:</span> <span class="literal">true</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">selinuxRelabel:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">hostPath:</span> <span class="string">/etc/kubernetes</span></span><br><span class="line"> <span class="attr">containerPath:</span> <span class="string">/etc/kubernetes</span></span><br><span class="line"> <span class="comment"># optional: if set, the mount is read-only.</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">readOnly:</span> <span class="literal">false</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">selinuxRelabel:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">hostPath:</span> <span class="string">/var/lib/netcd</span></span><br><span class="line"> <span class="attr">containerPath:</span> <span class="string">/var/lib/etcd</span></span><br><span class="line"> <span class="comment"># optional: if set, the mount is read-only.</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">readOnly:</span> <span class="literal">false</span></span><br><span class="line"> <span class="comment"># default false</span></span><br><span class="line"> <span class="attr">selinuxRelabel:</span> <span class="literal">false</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">role:</span> <span class="string">worker</span></span><br><span class="line"> <span class="attr">kubeadmConfigPatches:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">|</span></span><br><span class="line"><span class="string"> kind: JoinConfiguration</span></span><br><span class="line"><span class="string"> nodeRegistration:</span></span><br><span class="line"><span class="string"> kubeletExtraArgs:</span></span><br><span class="line"><span class="string"> node-labels: &quot;app-type=web-app&quot;</span></span><br><span class="line"><span class="string"></span> <span class="attr">extraPortMappings:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">containerPort:</span> <span class="number">30999</span></span><br><span class="line"> <span class="attr">hostPort:</span> <span class="number">80</span></span><br><span class="line"> <span class="comment"># optional: set the bind address on the host</span></span><br><span class="line"> <span class="comment"># 0.0.0.0 is the current default</span></span><br><span class="line"> <span class="attr">listenAddress:</span> <span class="string">&quot;0.0.0.0&quot;</span></span><br><span class="line"> <span class="comment"># optional: set the protocol to one of TCP, UDP, SCTP.</span></span><br><span class="line"> <span class="comment"># TCP is the default</span></span><br><span class="line"> <span class="attr">protocol:</span> <span class="string">TCP</span></span><br></pre></td></tr></table></figure>
<p>It’s a kind cluster configuration file!! This fiel is used to declare the specification of your cluster! And as you see <code>/etc/kubernetes</code> and <code>/var/lib/etcd</code> are mounted. We have 2-node cluster and a <code>extraPortMappings</code> to expose a service. In addition there is node-labels on the worker-node</p>
<blockquote>
<p>This challenge requires some kubernetes knowledge. You must be familiar with the basics of the kubernetes. Like nodes, deployements, pods, services, etc…</p>
</blockquote>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">### content deploy.yaml ###</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">update-app</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">update-app</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">replicas:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">selector:</span></span><br><span class="line"> <span class="attr">matchLabels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">update-app</span></span><br><span class="line"> <span class="attr">strategy:</span> &#123;&#125;</span><br><span class="line"> <span class="attr">template:</span></span><br><span class="line"> <span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">update-app</span></span><br><span class="line"> <span class="attr">spec:</span></span><br><span class="line"> <span class="attr">imagePullSecrets:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">regcred</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">image:</span> <span class="string">medrafk8s/kubersex</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">update-app</span></span><br><span class="line"> <span class="attr">resources:</span></span><br><span class="line"> <span class="attr">requests:</span></span><br><span class="line"> <span class="attr">memory:</span> <span class="string">&quot;64Mi&quot;</span></span><br><span class="line"> <span class="attr">cpu:</span> <span class="string">&quot;250m&quot;</span></span><br><span class="line"> <span class="attr">limits:</span></span><br><span class="line"> <span class="attr">memory:</span> <span class="string">&quot;128Mi&quot;</span></span><br><span class="line"> <span class="attr">cpu:</span> <span class="string">&quot;500m&quot;</span></span><br><span class="line"> <span class="attr">affinity:</span></span><br><span class="line"> <span class="attr">nodeAffinity:</span></span><br><span class="line"> <span class="attr">requiredDuringSchedulingIgnoredDuringExecution:</span></span><br><span class="line"> <span class="attr">nodeSelectorTerms:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">matchExpressions:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">key:</span> <span class="string">app-type</span></span><br><span class="line"> <span class="attr">operator:</span> <span class="string">In</span></span><br><span class="line"> <span class="attr">values:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">web-app</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">front-end</span></span><br><span class="line"><span class="attr">status:</span> &#123;&#125;</span><br></pre></td></tr></table></figure>
<p>This is a deployment manifest that pull a private image <code>medrafk8s/kubersex</code> using the imagePullSecrets fields! The nodeAffinity is used for some scheduling specification. In this example the deployment will be deployed in node with labels <code>app-type=web-app</code></p>
<p>Let’s summerize now! The attacker installed Kind to deploy the web app that hosts the malicious inside a kubernetes cluster!</p>
<p>So our objective is to recover the webapp that contains the malicious binary! But how can we restore that container! It’s a private container! What we should to do?</p>
<p>To get the private container we need to get the pull secret. The credential that allow us to pull the container image! The credential are stored inside a <code>secret</code> (Kubernetes Object).</p>
<p>According to the bash history we have this commands:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">USER=XXXXXXXXXXXXXXXXXXXX</span><br><span class="line">PASSWORD=XXXXXXXXXXXXXXXXXXX</span><br><span class="line">SERVER=XXXXXXXXXXXXXXXXXX</span><br><span class="line">kubectl create secret docker-registry regcred --docker-server=<span class="variable">$SERVER</span> --docker-username=<span class="variable">$USER</span> --docker-password=<span class="variable">$PASSWORD</span></span><br><span class="line">kubectl get secrets</span><br></pre></td></tr></table></figure>
<blockquote>
<p>The attacker store the credential inside environement and create a pull secret using <code>kubectl</code> command</p>
</blockquote>
<p>The only way to get the credential is to extract the secret from the <code>etcd</code> . But We have a problem! The etcd is protected!</p>
<p>Let’s Back to the bash history you’ll find that the attacker edit a <code>kube-apiserver.yaml</code> and <code>enc.yaml</code> .</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">### enc.yaml ###</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">apiserver.config.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">EncryptionConfiguration</span></span><br><span class="line"><span class="attr">resources:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">resources:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">secrets</span></span><br><span class="line"> <span class="attr">providers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">identity:</span> &#123;&#125;</span><br><span class="line"> <span class="bullet">-</span> <span class="attr">secretbox:</span></span><br><span class="line"> <span class="attr">keys:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">key1</span></span><br><span class="line"> <span class="attr">secret:</span> <span class="string">&lt;BASE64</span> <span class="string">ENCODED&gt;</span></span><br></pre></td></tr></table></figure>
<p>Let’s talk a little about the <code>Encryption Configuration</code> in Kubernetes.</p>
<p><img data-src="./images/https://d33wubrfki0l68.cloudfront.net/2475489eaf20163ec0f54ddc1d92aa8d4c87c96b/e7c81/images/docs/components-of-kubernetes.svg" alt=""></p>
<p>As known. Etcd is a distributed key-value store that is used by Kubernetes to store and retrieve the configuration data for the cluster. The Kubernetes API server interacts with etcd to read and write configuration data, such as the current state of the cluster and the desired state. The etcd data store serves as the single source of truth for the Kubernetes cluster’s configuration data, and the API server ensures that this data is always up to date and consistent across the cluster.</p>
<p>The API server accepts an argument <code>--encryption-provider-config</code> that controls how API data is encrypted in etcd. In other words, API server can store the data inside etcd but not in plain text! It’s encrypted to secure the data inside the database! for more details check this <span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvdGFza3MvYWRtaW5pc3Rlci1jbHVzdGVyL2VuY3J5cHQtZGF0YS8=">link</span></p>
<p>So our mission now is to find the secret value of the <code>EncryptionConfiguration</code> to use it after restoring the etcd by setting up a new api server that can read the encrypted data from the <code>etcd</code> .</p>
<p><img data-src="https://i.imgur.com/XEB64Su.png" alt=""></p>
<p>Getting back to the whatsapp discussion. The attacker use the same password for the encryption key and subsystem password!</p>
<p>Bingo!! Crack time! We know that the encryption key must be 32 bytes. So this information will help us filtering the downloaded wordlist!</p>
<p>Linux stores user passwords hashes in <code>/etc/shadow</code> . Great, we have the hash and the wordlist! Let’s do it!</p>
<p><img data-src="https://i.imgur.com/SanopKU.png" alt=""></p>
<p>Let’s start filter out the passwords with 32 characters from the wordlist using grep and tail to pick from the bottom:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grep -E <span class="string">&#x27;^.&#123;32&#125;$&#x27;</span> passwords.txt | <span class="built_in">tail</span> -n 100000 &gt; pass.txt</span><br></pre></td></tr></table></figure>
<p>Now it’s time to extract the user information from <code>/etc/shadow</code> and <code>/etc/password</code></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">grep kong etc/passwd &gt; passwd.txt</span><br><span class="line">grep kong etc/shadow &gt; shadow.txt</span><br></pre></td></tr></table></figure>
<p>Before start cracking using <code>John The Ripper</code> . We need to combine the passwd and shadow into a format that john can read. <code>unshadow</code> can do this work!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unshadow passwd.txt shadow.txt &gt; crack-me.txt</span><br></pre></td></tr></table></figure>
<p>Now our hash is ready for crack. Let’s use john with <code>--format=crypt</code> to specify that we are trying to crack yescrypt hash</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">john --wordlist=pass.txt crack-me.txt --format=crypt</span><br></pre></td></tr></table></figure>
<p>After some minutes we got the password!! The password is : <code>@a*Hd~u32@q1Db/LUiOFxC*W2THm5p*V</code></p>
<p><img data-src="https://i.imgur.com/c1mV0ef.png" alt=""></p>
<p>Now it’s time to resotre the <code>etcd</code> . Restoring a Kubernetes cluster in case of a disaster can be accomplished using etcd snapshots. However, the process of restoring an etcd snapshot is not straightforward and requires expertise. Actually in kubernetes etcd can take snapshot automatically. So we will count on that.</p>
<p>In this case i will use Kind to generate a lightweight cluster. In case you will use your own cluster you must to know that restoring etcd can lead you to lost your cluster data. So be careful!</p>
<p>To keep it simple I’ll use the same configuration as <code>k-config.yaml</code> .</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">kind create cluster --config=k-config.yaml</span><br><span class="line">Creating cluster <span class="string">&quot;kind&quot;</span> ...</span><br><span class="line"> ✓ Ensuring node image (kindest/node:v1.25.3) 🖼</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line">kubectl cluster-info --context kind-kind</span><br><span class="line"></span><br><span class="line">Have a <span class="built_in">nice</span> day! 👋</span><br></pre></td></tr></table></figure>
<p>In Kind each node will be represented as a container</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ docker ps</span><br><span class="line">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS</span><br><span class="line"> NAMES</span><br><span class="line">eba4afe51855 kindest/node:v1.25.3 <span class="string">&quot;/usr/local/bin/entr…&quot;</span> 2 minutes ago Up 2 minutes 127.0.0.1:43323-&gt;6443/tcp kind-control-plane</span><br><span class="line">13d7b697ba1f kindest/node:v1.25.3 <span class="string">&quot;/usr/local/bin/entr…&quot;</span> 2 minutes ago Up 2 minutes 0.0.0.0:80-&gt;30999/tcp kind-worker</span><br></pre></td></tr></table></figure>
<p>After making sure that the api-server works correctly we need to add the <code>Encryption Configuration</code> to make sure that the api server can read the encrypted data after restoring etcd.</p>
<p>Go and put this file on <code>/etc/kubernetes/enc/enc.yaml</code></p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apiserver.config.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">EncryptionConfiguration</span></span><br><span class="line"><span class="attr">resources:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">resources:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">secrets</span></span><br><span class="line"> <span class="attr">providers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">identity:</span> &#123;&#125;</span><br><span class="line"> <span class="bullet">-</span> <span class="attr">secretbox:</span></span><br><span class="line"> <span class="attr">keys:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">key1</span></span><br><span class="line"> <span class="attr">secret:</span> <span class="string">QGEqSGR+dTMyQHExRGIvTFVpT0Z4QypXMlRIbTVwKlY=</span></span><br></pre></td></tr></table></figure>
<p>Then go to <code>/etc/kubernetes/manifests/api-server.yaml</code> to add these lines.</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Pod</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">annotations:</span></span><br><span class="line"> <span class="attr">kubeadm.kubernetes.io/kube-apiserver.advertise-address.endpoint:</span> <span class="number">172.18</span><span class="number">.0</span><span class="number">.2</span><span class="string">:6443</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">component:</span> <span class="string">kube-apiserver</span></span><br><span class="line"> <span class="attr">tier:</span> <span class="string">control-plane</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">kube-apiserver</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">kube-system</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">command:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">kube-apiserver</span></span><br><span class="line"> <span class="string">...</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">--encryption-provider-config=/etc/kubernetes/enc/enc.yaml</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">volumeMounts:</span></span><br><span class="line"> <span class="string">...</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">enc</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">mountPath:</span> <span class="string">/etc/kubernetes/enc</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">readonly:</span> <span class="literal">true</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="string">...</span></span><br><span class="line"> <span class="attr">volumes:</span></span><br><span class="line"> <span class="string">...</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">enc</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">hostPath:</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">path:</span> <span class="string">/etc/kubernetes/enc</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="attr">type:</span> <span class="string">DirectoryOrCreate</span> <span class="comment"># &lt;-- add this line</span></span><br><span class="line"> <span class="string">...</span></span><br></pre></td></tr></table></figure>
<p>After changing the manifest the api-server will be stopped and down. If you did it corretly, you need to wait a few seconds until the api-server works again!</p>
<p>After configuring the api-server correctly let’s take the content <code>/var/lib/netcd</code> and try to use the <code>db</code> as our snapshot that we want to restore it!</p>
<p><img data-src="https://i.imgur.com/fu0HEsS.png" alt=""></p>
<p>I suggest to copy <code>db</code> inside the control-plane node (in this case container). I will copy it to one of the extraMounts of kind.</p>
<p>Now let’s open a shell inside the control-plane container:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it kind-control-plane bash</span><br></pre></td></tr></table></figure>
<p>Now we need to use an utility called etcdctl that will help us to interact with the etcd server.</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">apt update </span><br><span class="line">apt install etcd-client</span><br></pre></td></tr></table></figure>
<p>After install it succesfully. An important thing it must be done. Don’t skip this step! you must export an env variable to make etcdctl behave as we need!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> ETCDTL_API=3</span><br></pre></td></tr></table></figure>
<p>now it’s time to use this utility! There is a resotre command in this utility that allow us to restore the backup or the snapshot</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">etcdctl --endpoints=https://[etcd-server] \</span><br><span class="line">--cacert=&lt;path-to-ca-certification&gt; \</span><br><span class="line">--cert=&lt;path-to-etcd-server-cert&gt; \</span><br><span class="line">--key=&lt;path-to-etcd-server-key&gt; \</span><br><span class="line">--data-dir &lt;path-to-restored-data&gt; \ </span><br><span class="line">snapshot restore &lt;path-to-snapshot&gt;</span><br></pre></td></tr></table></figure>
<p>You need to fill this arguments with your own. you can get theses information from <code>/etc/kubernetes/manifests/etcd.yaml</code></p>
<p>In my case the command it will be like this:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ETCDTL_API=3 etcdctl --endpoints=https://[127.0.0.1:2379] \</span><br><span class="line">--cacert=/etc/kubernetes/pki/etcd/ca.crt \</span><br><span class="line">--cert=/etc/kubernetes/pki/etcd/server.crt \</span><br><span class="line">--key=/etc/kubernetes/pki/etcd/server.key \</span><br><span class="line">--data-dir /var/lib/etcd-backup \</span><br><span class="line">snapshot restore ./db</span><br></pre></td></tr></table></figure>
<p>You migth get an error or warning about hash stuff after running this command. Skip it! Let’s check if <code>/var/lib/etcd-backup</code> directory is created and if it contains <code>member</code> directory!</p>
<p>If you got it! Then you are on the right way! Now it’s time to do the crazy thing! Let’s replace our new data placed in <code>/var/lib/etcd-backup/member/snap</code> to the original etcd database!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cp</span> /var/lib/etcd-backup/member/snap/db /var/lib/etcd/member/snap/</span><br></pre></td></tr></table></figure>
<p>Just wait few seconds! and try a kubectl command!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">kubectl get nodes</span><br><span class="line">NAME STATUS ROLES AGE VERSION</span><br><span class="line">kind-control-plane NotReady &lt;none&gt; 51m v1.25.3</span><br><span class="line">kind-worker NotReady &lt;none&gt; 51m v1.25.3</span><br><span class="line">quals-control-plane Ready control-plane 26h v1.25.3</span><br><span class="line">quals-worker Ready &lt;none&gt; 26h v1.25.3</span><br></pre></td></tr></table></figure>
<p>Bingo! It works fine! but as you see here we have nodes naming issues cause of the data of the etcd!</p>
<p>Let’s check if we have a secret object or not!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">kubectl get secrets</span><br><span class="line">NAME TYPE DATA AGE</span><br><span class="line">regcred kubernetes.io/dockerconfigjson 1 26h</span><br></pre></td></tr></table></figure>
<p>And Yes!!! We got our secret! Let’s now inspect the data inside it!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"> kubectl get secret regcred -o jsonpath=<span class="string">&#x27;&#123;.data.\.dockerconfigjson&#125;&#x27;</span> | <span class="built_in">base64</span> -d</span><br><span class="line">&#123;<span class="string">&quot;auths&quot;</span>:&#123;<span class="string">&quot;docker.io&quot;</span>:&#123;<span class="string">&quot;username&quot;</span>:<span class="string">&quot;medrafk8s&quot;</span>,<span class="string">&quot;password&quot;</span>:<span class="string">&quot;dckr_pat_MLkRjYtjdk7dwT80W_dx3VTuac8&quot;</span>,<span class="string">&quot;auth&quot;</span>:<span class="string">&quot;bWVkcmFmazhzOmRja3JfcGF0X01Ma1JqWXRqZGs3ZHdUODBXX2R4M1ZUdWFjOA==&quot;</span>&#125;&#125;&#125;</span><br></pre></td></tr></table></figure>
<p>And finally! The registry is <code>docker.io</code> , the username is <code>medrafk8s</code> and the password is <code>dckr_pat_MLkRjYtjdk7dwT80W_dx3VTuac8</code></p>
<p>With this creds we can pull the container that host the malicious binary and analyse his traffic! Let’s do it!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ docker login docker.io -u medrafk8s -p dckr_pat_MLkRjYtjdk7dwT80W_dx3VTuac8</span><br><span class="line">WARNING! Using --password via the CLI is insecure. Use --password-stdin.</span><br><span class="line">Login Succeeded</span><br></pre></td></tr></table></figure>
<p>Let’s pull this image now!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ docker pull medrafk8s/kubersex</span><br><span class="line">Using default tag: latest</span><br><span class="line">latest: Pulling from medrafk8s/kubersex</span><br><span class="line">c158987b0551: Pull complete</span><br><span class="line">1e35f6679fab: Pull complete</span><br><span class="line">cb9626c74200: Pull complete</span><br><span class="line">b6334b6ace34: Pull complete</span><br><span class="line">f1d1c9928c82: Pull complete</span><br><span class="line">9b6f639ec6ea: Pull complete</span><br><span class="line">ee68d3549ec8: Downloading [=======&gt; ] 1.813MB/11.49MB</span><br><span class="line">4caa31e6cbc5: Download complete</span><br><span class="line">a1434f597582: Waiting</span><br></pre></td></tr></table></figure>
<p>The 1st i used to do when I pull a container image in forensics challenges is to check the layers of the image!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ docker <span class="built_in">history</span> medrafk8s/kubersex</span><br><span class="line">IMAGE CREATED CREATED BY SIZE COMMENT</span><br><span class="line">77a3b3f4c35c 13 minutes ago /bin/sh -c <span class="comment">#(nop) CMD [&quot;nginx&quot; &quot;-g&quot; &quot;daemon… 0B</span></span><br><span class="line">0b383b70426b 13 minutes ago /bin/sh -c <span class="built_in">rm</span> Serial-Key.txt 0B</span><br><span class="line">b6ca15406c7d 13 minutes ago /bin/sh -c <span class="comment">#(nop) EXPOSE 80 0B</span></span><br><span class="line">64eaf6945cd1 13 minutes ago /bin/sh -c <span class="comment">#(nop) COPY file:ed75fc1a725ff91b… 20B</span></span><br><span class="line">748d1b219207 13 minutes ago /bin/sh -c <span class="comment">#(nop) COPY dir:48e5409ee398a470a… 5.4MB</span></span><br><span class="line">4937520ae206 6 weeks ago /bin/sh -c <span class="built_in">set</span> -x &amp;&amp; apkArch=<span class="string">&quot;<span class="subst">$(cat /etc… 29.6MB</span></span></span><br><span class="line"><span class="subst"><span class="string">&lt;missing&gt; 6 weeks ago /bin/sh -c #(nop)</span> ENV NJS_VERSION=0.7.12 0B</span></span><br><span class="line"><span class="string">&lt;missing&gt; 6 weeks ago /bin/sh -c #(nop) CMD [&quot;</span>nginx<span class="string">&quot; &quot;</span>-g<span class="string">&quot; &quot;</span>daemon… 0B</span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) STOPSIGNAL SIGQUIT 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) EXPOSE 80 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) ENTRYPOINT [&quot;/docker-entr… 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:e57eef017a414ca7… 4.62kB</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:36429cfeeb299f99… 3.01kB</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:d4375883ed5db364… 276B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:5c18272734349488… 2.12kB</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:7b307b62e82255f0… 1.62kB</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="built_in">set</span> -x &amp;&amp; addgroup -g 101 -S … 4.74MB</span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) ENV PKG_RELEASE=1 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) ENV NGINX_VERSION=1.25.1 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) LABEL maintainer=NGINX Do… 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) CMD [&quot;/bin/sh&quot;] 0B</span></span><br><span class="line">&lt;missing&gt; 6 weeks ago /bin/sh -c <span class="comment">#(nop) ADD file:828b07e74c184e7f2… 7.05MB</span></span><br></pre></td></tr></table></figure>
<p>This is a webserver! Something important is here. No one can ignore the <code>Serial-Key.txt</code> file<br>
We will get it later! Let’s run the web app now</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ sudo docker run --name kubersex -p 81:80 medrafk8s/kubersex</span><br><span class="line">/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration</span><br><span class="line">/docker-entrypoint.sh: Looking <span class="keyword">for</span> shell scripts <span class="keyword">in</span> /docker-entrypoint.d/</span><br><span class="line">/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh</span><br><span class="line">10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf</span><br><span class="line">10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 <span class="keyword">in</span> /etc/nginx/conf.d/default.conf</span><br><span class="line">/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh</span><br><span class="line">/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh</span><br><span class="line">/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh</span><br><span class="line">/docker-entrypoint.sh: Configuration complete; ready <span class="keyword">for</span> start up</span><br><span class="line">2023/08/02 17:37:52 [notice] 1<span class="comment">#1: using the &quot;epoll&quot; event method</span></span><br><span class="line">2023/08/02 17:37:52 [notice] 1<span class="comment">#1: nginx/1.25.1</span></span><br><span class="line">2023/08/02 17:37:52 [notice] 1<span class="comment">#1: built by gcc 12.2.1 20220924 (Alpine 12.2.1_git20220924-r4)</span></span><br></pre></td></tr></table></figure>
<p>Mmm there is a Download button! Press it and you will get a binary! Bingo! This is the malicious release!</p>
<p><img data-src="https://i.imgur.com/jDkGJef.png" alt="The web app"></p>
<p>After checking the binary and run it, we found that the binary requires a serial key! Let’s recover that file!</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s:~$ docker save medrafk8s/medraf &gt; image.tar </span><br><span class="line">raf@4n6nk8s:~$ tar -xf image.tar </span><br><span class="line">raf@4n6nk8s:~$ <span class="built_in">cd</span> aae4861ba6bde0fbe820ba547bbe794c7c7e9c8be14c8972a6691eaa584161bc</span><br><span class="line">raf@4n6nk8s:~$ tar -xf layer.tar &amp;&amp; <span class="built_in">ls</span></span><br><span class="line">Serial-Key.txt VERSION json layer.tar</span><br></pre></td></tr></table></figure>
<p>And this is the content of the file !</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">I will put the serial key in the container image in case you forget! YOU FOOOOL YOU USED TO FORGET IT! GO AND DESTROY THE SERVICE WITH THE BOSS HOST!</span><br><span class="line"></span><br><span class="line">KEY:</span><br><span class="line">KFTV-RCFL-VC5W-HX3X</span><br></pre></td></tr></table></figure>
<blockquote>
<p>At this point you can reverse the binary and get the flag! or patch the binary to change a IP server with your choice! In this step reversing is the main idea so i put a public IP of a reachable server to make the binary send packets when players decice to run it !</p>
</blockquote>
<p>Let’s continue:</p>
<p>Run the binary again and insert that key! It seems the binary works! I bet this is the responsible binary for the DDoS attack! So, I will check the behavior of this binary and open Wireshark while this one is running!</p>
<p><img data-src="https://i.imgur.com/Opesxe5.png" alt="Record Traffic with Wireshark"></p>
<p>Mmmm this is http flow! Let’s check the requests!</p>
<p><img data-src="https://i.imgur.com/tzWSbjW.png" alt="We got the flag!"></p>
<p>Binggo we got the flag! The flag is on the http header</p>
<p>FLAG: <code>Securinets&#123;c03cefb79791e431011d0f86de9dd83aee67aebcec946bfefad00cd4807fc9c3&#125;</code></p>
<h2 id="jackpot"><a class="markdownIt-Anchor" href="#jackpot">#</a> Jackpot</h2>
<p><img data-src="https://i.imgur.com/GONLlyG.png" alt=""></p>
<p>We were able to find a left-behind cranky old cartel laptop in hibernation state. We believe that this device can help us retrieve the cartel’s crypto-currency wallet and withdraw their future gains.</p>
<p>We know that the cartel uses an intranet to communicate their news within couple of blocks in the city undergrounds.</p>
<p>Provided this intellisense, can you win us the jackpot? Wrap your finding in Securinets as indicated below.</p>
<p drug-enforcement-administration-for-the-win-style="">Flag format: Securinets</p>
<p><span class="exturl" data-url="aHR0cHM6Ly90d2l0dGVyLmNvbS9hZG1pZGEwdWk=">adm &amp; mida0ui</span></p>
<h3 id="attachment"><a class="markdownIt-Anchor" href="#attachment">#</a> Attachment</h3>
<p>Given a disk image, <code>disk.img</code> . The disk image is a raw disk image, and can be investigated using FTK Imager.<br>
<span class="exturl" data-url="aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2ZpbGUvZC8xU3M0UVRRaTRYYlJYYlRmeTNGVTBuRGJxZVBGaHVSRkkvdmlldz91c3A9c2hhcmluZw==">https://drive.google.com/file/d/1Ss4QTQi4XbRXbTfy3FU0nDbqePFhuRFI/view?usp=sharing</span></p>
<h3 id="writeup"><a class="markdownIt-Anchor" href="#writeup">#</a> Writeup</h3>
<p>The disk image is a raw disk image, and can be investigated using FTK Imager. The disk image contains a single partition, which is a Windows XP installation.</p>
<p>Looking at the root of the disk image, we can see a few interesting files:</p>
<p><img data-src="https://i.imgur.com/Qx1z5zy.png" alt=""></p>
<ul>
<li><code>Documents and Settings</code> - Contains the user profiles of the system</li>
<li><code>Program Files</code> - Contains the installed programs</li>
<li><code>Windows</code> - Contains the Windows installation files</li>
<li><code>pagefile.sys</code> - The page file of the system, aka swap file, which holds the memory of the system when it is not in use or when it is not enough RAM to hold the memory of the system.</li>
<li><code>hiberfil.sys</code> - The hibernation file of the system, which contains the memory of the system when it is hibernated.</li>
<li><code>System Volume Information</code> - Contains the shadow copies of the system, which is a backup of the system files. It is used to restore the system in case of a system failure. It is also used by the Windows Backup utility to create a backup of the system. It is also used by the Windows Restore utility to restore the system to a previous state. This folder is present in all disk images, people are usually not interested in it. However, it is very interesting in this case, as it contains a folder named <code>_restore&#123;xxxxxx&#125;</code> . This folder contains a file named <code>RPx</code> , this cleary a restore point of the system. We will investigate it later as well.</li>
</ul>
<p>and the rest of the stuff that would really find in any Windows disk…</p>
<p>Let’s start with the fact that the laptop was in hibernation mode, we know for a fact that the hiberfil.sys stores the memory content at hibernation, maybe we can treat it as an actual memory and find the intranet chat!!?</p>
<p>Googling a bit, I found this (Superuser question)[<span class="exturl" data-url="aHR0cHM6Ly9zdXBlcnVzZXIuY29tL3F1ZXN0aW9ucy82NjA2NDkvaG93LXRvLXJlYWQtd2luZG93cy1oaWJlcm5hdGlvbi1maWxlLWhpYmVyZmlsLXN5cy10by1leHRyYWN0LWRhdGE=">https://superuser.com/questions/660649/how-to-read-windows-hibernation-file-hiberfil-sys-to-extract-data</span>] and it says that if we convert the hiberfile.sys file to a raw image, we can use Volatility to analyze it!</p>
<p>and this is the command to use, as indicated:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vol -f hiberfil.sys --profile WinXPSP3x86 imagecopy -O hiberfil.raw</span><br></pre></td></tr></table></figure>
<p><img data-src="https://i.imgur.com/AgJlPlG.png" alt=""></p>
<p>Cool, we hope now we can use Volatility to analyze the hiberfil.raw file. Let’s start by checking the processes and commands history.</p>
<p><img data-src="https://i.imgur.com/MGjHNpu.png" alt=""></p>
<p>Cmdscan now maybe!</p>
<p><img data-src="https://i.imgur.com/8KCPq36.png" alt=""></p>
<p>There we go, we can see what they meant by the legacy, old school chat. They were using <code>msg.exe</code> to communicate with each other. This is a very old program, and it is used to send messages to other users in the same network. It is very similar to the LAN messenger that we found earlier, but it is a command line program. <code>msg</code> can also be used to transmit files as well.</p>
<p>The chat goes with the description and indicates that our guy got some kind of password that was placed in a certain registry key and permanetly deleted it after.</p>
<p>Now, let’s further investigate the programs now to build an understanding around this situation</p>
<p><img data-src="https://i.imgur.com/NGRW8VU.png" alt=""></p>
<p>We only see Chrome to be the only interesting thing in this disk evidence.</p>
<p>We know the crypto-currency part might need some searching to know that Metamask the most famous crypto wallet is a browser extension!!</p>
<p>And yeah, Metamask is being used in Chrome. Metamask is a browser extension that allows you to use Ethereum, Binance Chain, and more. It is a very popular extension, and it is used by a lot of people. Metamask gives you a wallet address, and you can use it to send and receive cryptocurrencies whether in the Ethereum network, BSC network, or custom networks. But an address is only the public key you use to send and receive, we are looking further than that, we want the private one to be able to control the wallet completely.</p>
<p>Metamask Extension for Chrome</p>
<p><img data-src="https://i.imgur.com/wWzkTjZ.png" alt=""></p>
<p>Could there be an active wallet within Metamask? Let’s check it out.</p>
<p>Usually the extension data is stored within the ‘Local Extension Settings’ folder. And as expected, that folder contains some interesting files.</p>
<p><img data-src="https://i.imgur.com/t8T8lYY.png" alt=""></p>
<p>The <code>Local Extension Settings</code> folder contains a folder named <code>nkbihfbeogaeaoehlefnkodbefgpgknn</code> , which is the ID of the Metamask extension. This folder contains a file named 0000xx.ldb, which is a DB file. Let’s check it out.</p>
<p>According to this <span class="exturl" data-url="aHR0cHM6Ly9ldGhlcmV1bS5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvNTI2NTgvd2hlcmUtZG9lcy1tZXRhbWFzay1zdG9yZS10aGUtd2FsbGV0LXNlZWQtZmlsZS1wYXRo">Ethereum Stackexchange question</span>. We could be able to completely control the existing wallet if we have the password. Could the challenge be all about that? and how to get the wallet password?</p>
<p>Yes it is possible, and we will get back to it later, for now, finding password is the priority!! We know it is a registry key, that was deleted.</p>
<p>Let’s think how we can RESTORE it xD</p>
<p>Is it the time, to investigate the <code>_restore&#123;xxxxxx&#125;</code> folder? right?</p>
<p>We can make use of a VM, however (OP: says the disk must not be converted back to vmdk whether by using a different file format or breaking the boot files). This way we can’t use a VM to check the restore point. So, we have to do it manually. My idea is to spin my own Windows XP on VMware, you can get the ISO officially by Microsoft with serial number from the WayBackMachine SP3 and x86 of course. After that we create a dummy restore point and modify its files by copying the RP folders from <code>System Volume Information</code> and then we can proceed to perform a restore point to see what is inside. I hope you can understand what I mean here.</p>
<p>(OP Note: for order I guess I will accept any provided order or make the user follow the order as shown in the leaked chat.)</p>
<p>Let’s do it.</p>
<ul>
<li>Spinning a new Windows XP machine</li>
</ul>
<p><img data-src="https://i.imgur.com/gAJWn0m.png" alt=""></p>
<ul>
<li>Creating a dummy restore point or just get the disk UUID, anyways we need Windows to create a restore point folder for us, so let’s do it.</li>
</ul>
<p><img data-src="https://i.imgur.com/hoZj5DU.png" alt=""></p>
<ul>
<li>Copying the RP folders from the Disk image <code>System Volume Information</code> to the new VM’s <code>System Volume Information</code></li>
</ul>
<p>Export the restore folder from System Volume Information to your desktop or some folder.</p>
<p>Adjust these folder options on Windows XP VM</p>
<p><img data-src="https://i.imgur.com/LH8W47T.png" alt=""></p>
<p>Then use this command to gain access to the System Volume Information folder</p>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cacls <span class="string">&quot;C:\System Volume Information&quot;</span> /E /G Administrator:F</span><br></pre></td></tr></table></figure>
<p>It can be administrator, Everyone or your specific VM username.</p>
<p><img data-src="https://i.imgur.com/6JWtrGQ.png" alt=""></p>
<p>Then copy the restore folder contents to the System Volume Information folder</p>
<p>This is the current dummy restore point we made</p>
<p><img data-src="https://i.imgur.com/ReEeaE9.png" alt=""></p>
<p>We add the exported RP5 and RP6 folders from the disk image with them</p>
<p>In each of the folders there is a <code>drivetable.txt</code> file that contains the old disk UUID, we need to replace it with the new one.</p>
<ul>
<li>Modifying Disk UUID in the restore point</li>
</ul>
<p>You can also modify the <code>domain.txt</code> since it contains the old user-id but I believe the Restore point utility can very much detect the change.</p>
<ul>
<li>Restoring the system like if it was a real restore point we made.</li>
</ul>
<p><img data-src="https://i.imgur.com/NW9lTab.png" alt=""></p>
<p>We can see a new entry added called “restore_point”, so let’s proceed with it!</p>
<p>This is the domain thing, hit ‘OK’</p>
<p><img data-src="https://i.imgur.com/VMADEqo.png" alt=""></p>
<p>We wait for a quick restart.</p>
<p><img data-src="https://i.imgur.com/X1drpyr.png" alt=""></p>
<p>And that’s a success!</p>
<p>Let’s open the registry now, shall we?</p>
<p><img data-src="https://i.imgur.com/ynNyJqX.png" alt=""></p>
<p>And there we go, a key named password containing a string named deleteMe! Bingo!</p>
<p>At this point, there is only one thing left, let’s get the flag!</p>
<p>Remember that Ethereum stack exchange question I mentioned earlier? here is the link again, also bring the content of the ldb file’s vault which is near the word “keyring”, you can CTRL+F that in the ldb files and adjust the format if some letters are escaped or encoded because data is never lost, you can also upload the whole file to the <span class="exturl" data-url="aHR0cHM6Ly9tZXRhbWFzay5naXRodWIuaW8vdmF1bHQtZGVjcnlwdG9yLw==">tool</span></p>
<p><span class="exturl" data-url="aHR0cHM6Ly9ldGhlcmV1bS5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvNTI2NTgvd2hlcmUtZG9lcy1tZXRhbWFzay1zdG9yZS10aGUtd2FsbGV0LXNlZWQtZmlsZS1wYXRo">https://ethereum.stackexchange.com/questions/52658/where-does-metamask-store-the-wallet-seed-file-path</span>.</p>
<p><img data-src="https://i.imgur.com/FxNDjWP.png" alt=""></p>
<p><img data-src="https://i.imgur.com/Mhm1M63.png" alt=""></p>
<p>Let’s get our flag now</p>
<p><img data-src="https://i.imgur.com/3tK5T2J.png" alt=""></p>
<p>Done, we have some critical information here. The seed phrase! We wrap it in Securinets</p>
<p><code>Securinets&#123;female-fire-strong-accuse-spring-update-bird-exchange-home-embark-latin-mom&#125;</code></p>
<p>Thanks for reading, we hope you enjoyed it, and we will be happy to hear your feedback and suggestions.</p>
<p>GGs <strong>itunderground</strong> for solving this challenge</p>
<h3 id="idea-and-final-words"><a class="markdownIt-Anchor" href="#idea-and-final-words">#</a> Idea and Final Words</h3>
<p>Just wanted to use pagefile.sys, hiberfile.sys, the Metamask thing, and Restore points because nobody used them like this in a CTF. So don’t know if that’s a great thing or rather will make players frustrated. Yet, tried to make everything as clear as possible for the players to understand and enjoy the challenge as a whole.</p>
<h2 id="raf-hide"><a class="markdownIt-Anchor" href="#raf-hide">#</a> Raf Hide</h2>
<p><img data-src="https://i.imgur.com/QRKzGoO.png" alt=""></p>
<h3 id="description-2"><a class="markdownIt-Anchor" href="#description-2">#</a> Description:</h3>
<blockquote Secrect="">
<p>My friend write a tool that can hide data inside an image. He give me this tool with an anime video without any source code and challenge me to get the secret! . Can you help me extract the flag?<br>
Flag format: Securinets</p>
</blockquote>
<blockquote>
<p>In this Challenge you will get a go binary and a video! I will not explain how to reverse the binary. The main Idea is to understand what the binary do and extract the data from the video</p>
</blockquote>
<p>Author: <strong>Raf²</strong></p>
<p>Binary: <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tLzRuNm5rOHMvcXVhbHMtMjAyMy13cml0ZS11cHMvcmF3L21haW4vUmFmLUhpZGUvcmFmaGlkZQ==">Download</span></p>
<p>This is a python version of what the binary can do :</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"></span><br><span class="line"><span class="comment"># Create an ArgumentParser object</span></span><br><span class="line">parser = argparse.ArgumentParser(description=<span class="string">&#x27;Example program using options and arguments&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Add options and arguments</span></span><br><span class="line">parser.add_argument(<span class="string">&#x27;-i&#x27;</span>, <span class="string">&#x27;--input&#x27;</span>, <span class="built_in">help</span>=<span class="string">&#x27;select cover-image&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>)</span><br><span class="line">parser.add_argument(<span class="string">&#x27;-e&#x27;</span>, <span class="string">&#x27;--embedfile&#x27;</span>, <span class="built_in">help</span>=<span class="string">&#x27;select image to be embedded&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>)</span><br><span class="line">parser.add_argument(<span class="string">&#x27;-o&#x27;</span>, <span class="string">&#x27;--output&#x27;</span>, <span class="built_in">help</span>=<span class="string">&#x27;The output&#x27;</span>, <span class="built_in">type</span>=<span class="built_in">str</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Parse the arguments</span></span><br><span class="line">args = parser.parse_args()</span><br><span class="line"></span><br><span class="line"><span class="comment"># Check if the options and arguments are correct</span></span><br><span class="line"><span class="keyword">if</span> args.<span class="built_in">input</span> <span class="keyword">and</span> args.embedfile <span class="keyword">and</span> args.output:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">&#x27;Starting Hiding ...&#x27;</span>)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> <span class="comment"># Provide an usage message if the input is incorrect</span></span><br><span class="line"> parser.print_usage()</span><br><span class="line"> exit()</span><br><span class="line"></span><br><span class="line">image=Image.<span class="built_in">open</span>(args.<span class="built_in">input</span>)</span><br><span class="line">embed=Image.<span class="built_in">open</span>(args.embedfile).convert(<span class="string">&#x27;1&#x27;</span>)</span><br><span class="line"><span class="keyword">if</span> image.size != embed.size:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">&#x27;The Images are not in the same size!&#x27;</span>)</span><br><span class="line"> exit()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">embed_data=embed.load()</span><br><span class="line">image_data=image.load()</span><br><span class="line">index=<span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(image.height):</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(image.width):</span><br><span class="line"> flag_pix=<span class="built_in">int</span>(embed_data[i,j])</span><br><span class="line"> flag_pix &amp;=<span class="number">1</span></span><br><span class="line"> im_pix=<span class="built_in">list</span>(image_data[i,j])</span><br><span class="line"> data = ((flag_pix &lt;&lt; index%<span class="number">2</span>) | (<span class="number">254</span>-index%<span class="number">2</span>)) </span><br><span class="line"> <span class="keyword">if</span> flag_pix ==<span class="number">1</span> :</span><br><span class="line"> im_pix[index%<span class="number">3</span>]|= data &amp; (<span class="number">1</span>+index%<span class="number">2</span>)</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> im_pix[index%<span class="number">3</span>]&amp;= data</span><br><span class="line"> image_data[i,j]=<span class="built_in">tuple</span>(im_pix)</span><br><span class="line"> index+=<span class="number">1</span></span><br><span class="line">image.save(args.output)</span><br></pre></td></tr></table></figure>
<p>This is a golang version of what the binary can do :</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"> <span class="string">&quot;fmt&quot;</span></span><br><span class="line"> <span class="string">&quot;image&quot;</span></span><br><span class="line"> <span class="string">&quot;image/color&quot;</span></span><br><span class="line"> <span class="string">&quot;image/png&quot;</span></span><br><span class="line"> <span class="string">&quot;os&quot;</span></span><br><span class="line"> <span class="string">&quot;flag&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Create a new FlagSet to parse command line arguments</span></span><br><span class="line"> flagSet := flag.NewFlagSet(<span class="string">&quot;steganography&quot;</span>, flag.ExitOnError)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Define command line options and arguments</span></span><br><span class="line"> inputFileName := flagSet.String(<span class="string">&quot;i&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;select cover-image&quot;</span>)</span><br><span class="line"> embedFileName := flagSet.String(<span class="string">&quot;e&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;select image to be embedded&quot;</span>)</span><br><span class="line"> outputFileName := flagSet.String(<span class="string">&quot;o&quot;</span>, <span class="string">&quot;&quot;</span>, <span class="string">&quot;The output&quot;</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Parse the command line arguments</span></span><br><span class="line"> flagSet.Parse(os.Args[<span class="number">1</span>:])</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Check if the options and arguments are correct</span></span><br><span class="line"> <span class="keyword">if</span> *inputFileName == <span class="string">&quot;&quot;</span> || *embedFileName == <span class="string">&quot;&quot;</span> || *outputFileName == <span class="string">&quot;&quot;</span> &#123;</span><br><span class="line"> flagSet.Usage()</span><br><span class="line"> os.Exit(<span class="number">1</span>)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">// Open the input file</span></span><br><span class="line"> inputFile1, err := os.Open(*embedFileName)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">defer</span> inputFile1.Close()</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Decode the PNG image</span></span><br><span class="line"> inputImage1, _, err := image.Decode(inputFile1)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Check if the image is grayscale</span></span><br><span class="line"> grayImage, ok := inputImage1.(*image.Gray)</span><br><span class="line"> <span class="keyword">if</span> !ok &#123;</span><br><span class="line"> fmt.Println(<span class="string">&quot;Error: input image is not grayscale&quot;</span>)</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Get the width and height of the image</span></span><br><span class="line"> embed_width := grayImage.Bounds().Size().X</span><br><span class="line"> embed_height := grayImage.Bounds().Size().Y</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Open the input file</span></span><br><span class="line"> inputFile, err := os.Open(*inputFileName)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">defer</span> inputFile.Close()</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Decode the image as a generic Image interface value</span></span><br><span class="line"> inputImage, _, err := image.Decode(inputFile)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Assert the image to an *image.RGBA or *image.NRGBA value</span></span><br><span class="line"> rgba, ok := inputImage.(*image.RGBA)</span><br><span class="line"> <span class="keyword">if</span> !ok &#123;</span><br><span class="line"> nrgba, ok := inputImage.(*image.NRGBA)</span><br><span class="line"> <span class="keyword">if</span> !ok &#123;</span><br><span class="line"> <span class="built_in">panic</span>(<span class="string">&quot;Input image format not supported&quot;</span>)</span><br><span class="line"> &#125;</span><br><span class="line"> rgba = image.NewRGBA(nrgba.Bounds())</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Get the width and height of the image</span></span><br><span class="line"> bounds := rgba.Bounds()</span><br><span class="line"> width := bounds.Size().X</span><br><span class="line"> height := bounds.Size().Y</span><br><span class="line"> index:=<span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> width!=embed_width || height!=embed_height &#123;</span><br><span class="line"> <span class="built_in">panic</span>(<span class="string">&quot;The Images are not in the same size!&quot;</span>)</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"> <span class="comment">// Invert the colors of the image by subtracting each RGB component from 255</span></span><br><span class="line"> <span class="keyword">for</span> y := <span class="number">0</span>; y &lt; height; y++ &#123;</span><br><span class="line"> <span class="keyword">for</span> x := <span class="number">0</span>; x &lt; width; x++ &#123;</span><br><span class="line"> intensity := grayImage.GrayAt(x, y).Y &amp; <span class="number">1</span></span><br><span class="line"> i:=<span class="type">uint8</span>(index%<span class="number">2</span>)</span><br><span class="line"> data:= ((intensity &lt;&lt; i) | (<span class="number">254</span>-i))</span><br><span class="line"> r, g, b, a := rgba.At(x, y).RGBA()</span><br><span class="line"> im_pix:= [<span class="number">3</span>]<span class="type">uint8</span>&#123;<span class="type">uint8</span>(r),<span class="type">uint8</span>(g),<span class="type">uint8</span>(b)&#125;</span><br><span class="line"> j:= <span class="type">uint</span>(index%<span class="number">3</span>)</span><br><span class="line"> <span class="keyword">if</span> intensity == <span class="number">1</span> &#123;</span><br><span class="line"> im_pix[j] = im_pix[j] | (data &amp; (<span class="number">1</span>+i))</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> im_pix[j] = im_pix[j] &amp; data</span><br><span class="line"> &#125;</span><br><span class="line"> newColor := color.RGBA&#123;</span><br><span class="line"> R: <span class="type">uint8</span>(im_pix[<span class="number">0</span>]),</span><br><span class="line"> G: <span class="type">uint8</span>(im_pix[<span class="number">1</span>]),</span><br><span class="line"> B: <span class="type">uint8</span>(im_pix[<span class="number">2</span>]),</span><br><span class="line"> A: <span class="type">uint8</span>(a),</span><br><span class="line"> &#125;</span><br><span class="line"> rgba.SetRGBA(x, y, newColor)</span><br><span class="line"> index++</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Create the output file</span></span><br><span class="line"> outputFile, err := os.Create(*outputFileName)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">defer</span> outputFile.Close()</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Encode the output image as PNG</span></span><br><span class="line"> <span class="keyword">if</span> err := png.Encode(outputFile, rgba); err != <span class="literal">nil</span> &#123;</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> fmt.Println(<span class="string">&quot;Output image saved successfully&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>As we see here this script try to hide image inside another image in a specific way. We need to understand how he hide data.</p>
<p>The tool take a black-white image that have only 2 values in his pixels and try to inject this pixels in the LSB of RGB channels of the other image!<br>
But be carefull is not a traditional or simple LSB steganoraphy here! In each iteration it take a single channel. For example the 1st pixel will use the Red value, 2nd will use the Green value, 3rd will use the Blue and so on.</p>
<p>We need to reverse this algorithm and write a script that can extract from images used by this tool.</p>
<p>Let’s use this one!</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"></span><br><span class="line">INPUT_FILFE=<span class="string">&quot;input.png&quot;</span></span><br><span class="line">EXTRACTED_DATA=<span class="string">&quot;extracted.png&quot;</span></span><br><span class="line">image=Image.<span class="built_in">open</span>(INPUT_FILFE)</span><br><span class="line">image_data = image.load()</span><br><span class="line">extracted = Image.new(<span class="string">&#x27;1&#x27;</span>, (image.width,image.height), <span class="number">1</span>)</span><br><span class="line">index=<span class="number">0</span></span><br><span class="line">output_data=extracted.load()</span><br><span class="line"><span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(image.height):</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(image.width): </span><br><span class="line"> im_pix=<span class="built_in">list</span>(image_data[i,j])</span><br><span class="line"> flag_pix = (im_pix[index%<span class="number">3</span>]&amp;(<span class="number">1</span>+index%<span class="number">2</span>)) </span><br><span class="line"> <span class="keyword">if</span> flag_pix &gt;= <span class="number">1</span>:</span><br><span class="line"> flag_pix=<span class="number">255</span></span><br><span class="line"> output_data[i,j]=flag_pix</span><br><span class="line"> index+=<span class="number">1</span></span><br><span class="line">extracted.save(EXTRACTED_DATA)</span><br></pre></td></tr></table></figure>
<p>To make sure that everything is ok now! We can use the given tool and hide a black-white image and try to extract it with our new script.</p>
<p>We assume that everything is fine. Let’s take a look now how can we extract data from the video!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/video-gif.gif" alt=""></p>
<p>Let’s extract every frame from this video and try to extract a data from it using our last script. Maybe we will find something here!</p>
<h3 id="extract-all-the-frames-using-ffmpeg"><a class="markdownIt-Anchor" href="#extract-all-the-frames-using-ffmpeg">#</a> Extract all the frames using ffmpeg</h3>
<p>After running this command. we get 383 frames.</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">raf@Securinets:~$ <span class="built_in">mkdir</span> frames</span><br><span class="line">raf@Securinets:~$ ffmpeg -i challenge.mp4 frames/%3d.png</span><br></pre></td></tr></table></figure>
<h3 id="extract-data-from-each-frame-using-our-solver"><a class="markdownIt-Anchor" href="#extract-data-from-each-frame-using-our-solver">#</a> Extract data from each frame using our solver</h3>
<p>Let’s use our solver to try extracting data from each frame.</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">raf@Securinets:~$ <span class="built_in">mkdir</span> data</span><br></pre></td></tr></table></figure>
<p>We will put our solver inside a function and use a for loop to run it on each frame</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">extract</span>(<span class="params">frame,output</span>):</span><br><span class="line"> image=Image.<span class="built_in">open</span>(frame)</span><br><span class="line"> image_data = image.load()</span><br><span class="line"> extracted = Image.new(<span class="string">&#x27;1&#x27;</span>, (image.width,image.height), <span class="number">1</span>)</span><br><span class="line"> index=<span class="number">0</span></span><br><span class="line"> output_data=extracted.load()</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(image.height):</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(image.width): </span><br><span class="line"> im_pix=<span class="built_in">list</span>(image_data[i,j])</span><br><span class="line"> flag_pix = (im_pix[index%<span class="number">3</span>]&amp;(<span class="number">1</span>+index%<span class="number">2</span>)) </span><br><span class="line"> <span class="keyword">if</span> flag_pix &gt;= <span class="number">1</span>:</span><br><span class="line"> flag_pix=<span class="number">255</span></span><br><span class="line"> output_data[i,j]=flag_pix</span><br><span class="line"> index+=<span class="number">1</span></span><br><span class="line"> extracted.save(output)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">383</span>):</span><br><span class="line"> index=<span class="string">&quot;0&quot;</span>*(<span class="number">3</span>-<span class="built_in">len</span>(<span class="built_in">str</span>(i+<span class="number">1</span>)))+<span class="built_in">str</span>(i+<span class="number">1</span>)+<span class="string">&quot;.png&quot;</span></span><br><span class="line"> extract(<span class="string">&quot;frames/&quot;</span>+index,<span class="string">&quot;data/&quot;</span>+index)</span><br></pre></td></tr></table></figure>
<p>Let’s now check the result and what we get!<br>
Of couse we will get 383 images. But is all the images are usefull or not? Let’s check.</p>
<p>We find this image extracted from the 1st frame of the image!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/000.png" alt=""></p>
<p>Bingo! We are on the right way! The author told us to check the last images! Yeah we will but let’s check what we got in all the images!</p>
<p>We found a big number of image that have a black line in random position of the image!</p>
<p float="left">
<img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/015.png" width="450" style="margin-right:50px;" />
<img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/210.png" width="450" />
</p>
<p>Ok Let’s focus on the last images as the author said. This is will be better for us. Wait what?! We found a 2 pastebin links and 2 images putted as hint for us. And of couse a rabbit hole(Fake Flag)</p>
<p float="center">
<img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/372.png" width="320"style="margin-right:10px;" />
<img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/377.png" width="320"style="margin-right:10px;" />
<img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/381.png" width="320"style="margin-right:10px;" />
</p>
<p>Let’s check the content of the 2 pastebin links and see what we have!</p>
<figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">Advertising flash, it&#x27;s time to relax and rest.</span><br><span class="line">This pastebin is the solution to your problem </span><br><span class="line">Those links will Absolutely help you </span><br><span class="line"> </span><br><span class="line">https://4n6nk8s.tech</span><br><span class="line">https://anas-cherni.me/</span><br><span class="line">https://ironbyte.me/</span><br><span class="line">https://yassine-belkhadem.tech/ ( Don&#x27;t waste your time with this link)</span><br><span class="line">https://github.com/M0ngi</span><br><span class="line">https://soter14.tech/</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">Thi is the FLAG: GG_Tr0ll1ng_1s_MY_G4mE_!</span><br><span class="line"> </span><br><span class="line">https://github.com/Mohamed-Rafraf</span><br><span class="line">https://github.com/adamlahbib</span><br><span class="line">https://www.linkedin.com/in/mohamed-rafraf/</span><br><span class="line">https://www.linkedin.com/in/adamlahbib/</span><br><span class="line">https://www.linkedin.com/in/anascherni/</span><br><span class="line">https://www.linkedin.com/in/yassine-belkhadem-396266204/</span><br><span class="line">https://www.linkedin.com/in/m0ngi/</span><br><span class="line">https://www.linkedin.com/in/mohamed-ali-ouachani-00a452237/</span><br><span class="line">https://www.linkedin.com/in/rania-midaoui-b0163a1bb/</span><br><span class="line">https://www.linkedin.com/in/mohamed-ayadi-5a10621a4/</span><br><span class="line">https://www.linkedin.com/in/yassine-belarbi-853303208/</span><br></pre></td></tr></table></figure>
<p>There is another fake flag &amp; links for the blogs of the author and his team members! Yeah It’s SOter14 team. Let’s Check the other one. Maybe it will help</p>
<figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">6 &lt;--&gt; 29</span><br><span class="line">15 &lt;--&gt; 25</span><br><span class="line">11 &lt;--&gt; 34</span><br><span class="line">10 &lt;--&gt; 24</span><br><span class="line">1 &lt;--&gt; 23</span><br><span class="line">14 &lt;--&gt; 35</span><br><span class="line">2 &lt;--&gt; 19</span><br><span class="line">17 &lt;--&gt; 33</span><br><span class="line">3 &lt;--&gt; 32</span><br><span class="line">8 &lt;--&gt; 27</span><br><span class="line">13 &lt;--&gt; 31</span><br><span class="line">0 &lt;--&gt; 18</span><br><span class="line">7 &lt;--&gt; 20</span><br><span class="line">5 &lt;--&gt; 28</span><br><span class="line">12 &lt;--&gt; 30</span><br></pre></td></tr></table></figure>
<p>Absolutely this thing will help but we still didn’t know how this text file will help us! Let’s understand the explanation putted on the other frames.</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/377.png" alt=""></p>
<p>The author told us that he split the image to many slices and put each slice in an empty unique image!!! We get it! The random lines are tiny pieces of unique image!</p>
<p>But how can we collect this slice and re-order them to get the original? The lines are ordered randomly? Let’s think.</p>
<h3 id="collect-the-pieces-and-recover-the-orginal-image"><a class="markdownIt-Anchor" href="#collect-the-pieces-and-recover-the-orginal-image">#</a> collect the pieces and recover the orginal image</h3>
<p>The solution is simple. That’s assume that the white color have a <code>0 value</code> and the black color have <code>1 value</code> . We can sum the pixels of all the images with this concept to recover the image, right?</p>
<blockquote>
<p>We know that our image size is 720x720 (The resolution of our video) and from our extracted images we know that we have 360 images that splitted to slices. which mean that every line present 2px (width) from the original image.</p>
</blockquote>
<p>Take a look at this script then!</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"></span><br><span class="line">img=Image.new(<span class="string">&#x27;1&#x27;</span>,(<span class="number">720</span>,<span class="number">720</span>),<span class="number">255</span>)</span><br><span class="line">imgpixs=img.load()</span><br><span class="line"><span class="keyword">for</span> n <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">1</span>,<span class="number">360</span>):</span><br><span class="line"> name=<span class="string">&quot;0&quot;</span>*(<span class="number">3</span>-<span class="built_in">len</span>(<span class="built_in">str</span>(n+<span class="number">1</span>)))+<span class="built_in">str</span>(n+<span class="number">1</span>)+<span class="string">&quot;.png&quot;</span></span><br><span class="line"> image=Image.<span class="built_in">open</span>(<span class="string">&quot;data/&quot;</span>+name)</span><br><span class="line"> image_pixs=image.load()</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">&quot;Image Number : &quot;</span>,n)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">720</span>):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">720</span>):</span><br><span class="line"> <span class="keyword">if</span> image_pixs[i,j]!=<span class="number">255</span>:</span><br><span class="line"> imgpixs[i,j]=image_pixs[i,j]</span><br><span class="line"></span><br><span class="line">img.save(<span class="string">&quot;Recovered.png&quot;</span>)</span><br></pre></td></tr></table></figure>
<p>In this script we collect all the black pixels and ignore the white pixels. Because we generate a white image and we will fill it with the black color. Let’s recover the image now!!</p>
<p>Bingo! There is a progress, we got this image!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/recoverd.png" alt=""></p>
<p>Oh god! It’s a broken QR code. How can we deal with this thing. Oh yeah! We have another clue! The author left this hint for us!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/381.png" alt=""></p>
<p>Oh cool! The author split the QRCode to small square and shuffle them in random order! We need to recover them. The squares are numeroted from 0 to n-1 pieces. This order will help us. Now We get the utility of the pastebin link!</p>
<figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">6 &lt;--&gt; 29</span><br><span class="line">15 &lt;--&gt; 25</span><br><span class="line">11 &lt;--&gt; 34</span><br><span class="line">10 &lt;--&gt; 24</span><br><span class="line">1 &lt;--&gt; 23</span><br><span class="line">14 &lt;--&gt; 35</span><br><span class="line">2 &lt;--&gt; 19</span><br><span class="line">17 &lt;--&gt; 33</span><br><span class="line">3 &lt;--&gt; 32</span><br><span class="line">8 &lt;--&gt; 27</span><br><span class="line">13 &lt;--&gt; 31</span><br><span class="line">0 &lt;--&gt; 18</span><br><span class="line">7 &lt;--&gt; 20</span><br><span class="line">5 &lt;--&gt; 28</span><br><span class="line">12 &lt;--&gt; 3</span><br></pre></td></tr></table></figure>
<p>This is will help us how re-order the QRCode. Let’s take a deep look now the the broken QRCode!.</p>
<p>The QRCode is splitted by 6 in width and 6 in height. So each piece’s size is 120x120. And we have 36 pieces. It’s impossible to recover the image without the help of pastebin link. Let’s take this line for example <code>0 &lt;--&gt; 18</code> , this link told us that the author switch the 1st piece with the 19th piece. (We Start counting from 0 due to the explanation). So we need to write a script that can order this QRCode! We need to recover it!</p>
<p>Let’s put the content of the pastebin inside a textfile named <code>help.txt</code> and start write our solver.</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"></span><br><span class="line">W_SPLIT=<span class="number">6</span></span><br><span class="line">H_SPLIT=<span class="number">6</span></span><br><span class="line"></span><br><span class="line">ASSEMBLED_IMAGE=<span class="string">&quot;Assembled.png&quot;</span></span><br><span class="line">SPLITTED_IMAGE=<span class="string">&quot;Recovered.png&quot;</span></span><br><span class="line">image= Image.<span class="built_in">open</span>(SPLITTED_IMAGE)</span><br><span class="line">width, height = image.size</span><br><span class="line">pixels = image.load()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">change_chunk</span>(<span class="params">index1,index2</span>):</span><br><span class="line"> pos1=[]</span><br><span class="line"> pos1.append(index1 % W_SPLIT)</span><br><span class="line"> pos1.append(index1 // W_SPLIT)</span><br><span class="line"> pos2=[]</span><br><span class="line"> pos2.append(index2 % W_SPLIT)</span><br><span class="line"> pos2.append(index2 // W_SPLIT)</span><br><span class="line"> height_chunk=height // H_SPLIT</span><br><span class="line"> width_chunk= width // W_SPLIT</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span> (width_chunk):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span> (height_chunk):</span><br><span class="line"> aux= pixels[pos1[<span class="number">0</span>]*width_chunk+i,pos1[<span class="number">1</span>]*height_chunk+j]</span><br><span class="line"> pixels[pos1[<span class="number">0</span>]*width_chunk+i,pos1[<span class="number">1</span>]*height_chunk+j]= pixels[pos2[<span class="number">0</span>]*width_chunk+i,pos2[<span class="number">1</span>]*height_chunk+j]</span><br><span class="line"> pixels[pos2[<span class="number">0</span>]*width_chunk+i,pos2[<span class="number">1</span>]*height_chunk+j]= aux</span><br><span class="line"></span><br><span class="line">data=<span class="built_in">open</span>(<span class="string">&quot;help.txt&quot;</span>,<span class="string">&quot;r&quot;</span>).read().split(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(data)-<span class="number">1</span>):</span><br><span class="line"> position=data[i].split(<span class="string">&quot;&lt;--&gt;&quot;</span>)</span><br><span class="line"> <span class="built_in">print</span>(position)</span><br><span class="line"> change_chunk(<span class="built_in">int</span>(position[<span class="number">0</span>]),<span class="built_in">int</span>(position[<span class="number">1</span>]))</span><br><span class="line"></span><br><span class="line">image.save(ASSEMBLED_IMAGE)</span><br></pre></td></tr></table></figure>
<p>Yeah It works fine!! We recover the QRCode!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/Assembled.png" alt=""></p>
<p>But something is wrong here! It sills broken and We can’t scan it 😦. But why? are we have any problem with our solver?</p>
<p>Ah No. I get it! We have 36 pieces and each line from <code>help.txt</code> have correspond to 2 pieces! So we have to find 18 lines, right ?</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">raf@Securinets:~$ <span class="built_in">wc</span> -l help.txt</span><br><span class="line">15</span><br></pre></td></tr></table></figure>
<p>Oh no we have 15 lines, So we have 6 pieces we need to re-order them by ourselves! Now I get why the Author said Help <code>LITTLE BIIT</code> . He left the 6 pieces to deal with it.</p>
<p>In this case we need to do a bruteforce to all the combinasions. We have 6 pieces, so we have 6! possibility<br>
and 6! = 720 which is possible to deal with it using a python script. Let’s re-order the 6 pieces each time and try to scan the QRCode. Once the QRCode is readable, we will stop our program!</p>
<p>Let’s get the flag now !!! Let’s DO IT NOW! We’re so close!</p>
<p>So the 1st thing that we need to do it is that we need to get the index of missed pieces. The <code>help.txt</code> is the key!</p>
<p>Let’s generate an array that have the order (index) of the missed pieces. Then we use our <code>change_chunck()</code> method and try all the combinaisons using the <code>itertools</code> . Finally try to scan the QRCode each time using the <code>qrtools</code></p>
<p>Let’s install the qrtools first</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">raf@Securinets:~$ sudo apt-get install python3-qrtools</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>Now let’s write down our last script (I Hope) :</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="keyword">import</span> qrtools</span><br><span class="line"><span class="keyword">from</span> itertools <span class="keyword">import</span> permutations</span><br><span class="line"></span><br><span class="line">qr=qrtools.QR()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">missed_data</span>():</span><br><span class="line"> not_missed=[]</span><br><span class="line"> data=<span class="built_in">open</span>(<span class="string">&quot;help.txt&quot;</span>,<span class="string">&quot;r&quot;</span>).read().split(<span class="string">&quot;\n&quot;</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(data)-<span class="number">1</span>):</span><br><span class="line"> position=data[i].split(<span class="string">&quot;&lt;--&gt;&quot;</span>)</span><br><span class="line"> not_missed.append(<span class="built_in">int</span>(position[<span class="number">0</span>]))</span><br><span class="line"> not_missed.append(<span class="built_in">int</span>(position[<span class="number">1</span>]))</span><br><span class="line"> <span class="built_in">print</span>(not_missed)</span><br><span class="line"> missed=[]</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>,<span class="number">36</span>):</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> (i <span class="keyword">in</span> not_missed):</span><br><span class="line"> missed.append(i)</span><br><span class="line"> <span class="keyword">return</span> missed</span><br><span class="line"></span><br><span class="line">chuncks=missed_data()</span><br><span class="line"><span class="built_in">print</span>(chuncks)</span><br><span class="line">H_SPLIT=<span class="number">6</span></span><br><span class="line">W_SPLIT=<span class="number">6</span></span><br><span class="line">SPLITTED_IMAGE=<span class="string">&quot;Assembled.png&quot;</span></span><br><span class="line">height,width=<span class="number">720</span>,<span class="number">720</span></span><br><span class="line"></span><br><span class="line">permutations=<span class="built_in">list</span>(permutations(chuncks,<span class="number">6</span>))</span><br><span class="line">image=Image.<span class="built_in">open</span>(<span class="string">&quot;Assembled.png&quot;</span>)</span><br><span class="line">pixels=image.load()</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">change_chunk</span>(<span class="params">index1,index2</span>):</span><br><span class="line"> pos1=[]</span><br><span class="line"> pos1.append(index1 % W_SPLIT)</span><br><span class="line"> pos1.append(index1 // W_SPLIT)</span><br><span class="line"> pos2=[]</span><br><span class="line"> pos2.append(index2 % W_SPLIT)</span><br><span class="line"> pos2.append(index2 // W_SPLIT)</span><br><span class="line"> height_chunk=height // H_SPLIT</span><br><span class="line"> width_chunk= width // W_SPLIT</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span> (width_chunk):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span> (height_chunk):</span><br><span class="line"> aux= pixels[pos1[<span class="number">0</span>]*width_chunk+i,pos1[<span class="number">1</span>]*height_chunk+j]</span><br><span class="line"> pixels[pos1[<span class="number">0</span>]*width_chunk+i,pos1[<span class="number">1</span>]*height_chunk+j]= pixels[pos2[<span class="number">0</span>]*width_chunk+i,pos2[<span class="number">1</span>]*height_chunk+j]</span><br><span class="line"> pixels[pos2[<span class="number">0</span>]*width_chunk+i,pos2[<span class="number">1</span>]*height_chunk+j]= aux</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&#x27;[-] Trying to fix the QRCode and Getting the flag ...&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(permutations)):</span><br><span class="line"> comb=<span class="built_in">list</span>(permutations[i])</span><br><span class="line"> change_chunk(comb[<span class="number">0</span>],comb[<span class="number">1</span>])</span><br><span class="line"> change_chunk(comb[<span class="number">2</span>],comb[<span class="number">3</span>])</span><br><span class="line"> change_chunk(comb[<span class="number">4</span>],comb[<span class="number">5</span>])</span><br><span class="line"> image.save(<span class="string">&quot;Final.png&quot;</span>)</span><br><span class="line"> <span class="keyword">if</span> qr.decode(<span class="string">&quot;Final.png&quot;</span>):</span><br><span class="line"> <span class="built_in">print</span>(qr.data)</span><br><span class="line"> <span class="keyword">break</span></span><br></pre></td></tr></table></figure>
<p>And we got the flag as an output Here!!! BINGO! We get the flag!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/finally.png" alt=""></p>
<p>And of course the QRCode is saved! And this is our QRCode!</p>
<p><img data-src="https://github.com/4n6nk8s/quals-2023-write-ups/raw/main/Raf-Hide/Final.png" alt=""></p>
<blockquote Every_Fr4Me_H4S_HiS_own_S7ory="">
<p>The Final flag is : Securinets</p>
</blockquote>
<h2 id="couch-potato"><a class="markdownIt-Anchor" href="#couch-potato">#</a> Couch Potato</h2>
<p><img data-src="https://i.imgur.com/jHut52F.png" alt=""></p>
<p>It’s past one, I was probably sleeping in front of my screen, I’m not even sure if I was awake for a bit or not, I’m not even sure if I’m dreaming or not… All I know is that I left the device on my favorite channel and that piece of crap failed me. Agh I need to fix it now. It is no longer responding to the commands I give it, and it is no longer showing my favorite channel! I hate my life, can you help me fix it?</p>
<p>I am looking for three stuff:</p>
<ul>
<li><em>What nonsense was I watching the night the device failed me?</em></li>
<li><em>I might need the Up and Down key codes in NEC 32-bit format?</em></li>
<li><em>The expiration date of my IPTV subscription.</em></li>
</ul>
<p>Flag formal: <strong>Securinets{show_name_00UP1234_DOWN1234_YYYYMMDD}</strong></p>
<p><span class="exturl" data-url="aHR0cHM6Ly90d2l0dGVyLmNvbS9hZG1pZGEwdWk=">adm &amp; mida0ui</span></p>
<h3 id="attachment-2"><a class="markdownIt-Anchor" href="#attachment-2">#</a> Attachment</h3>
<p>A file called <code>dump.bin</code> was provided in a zip. Weighing 8 MB. Dating back to February the 1st, 2020. 1:07 AM.</p>
<p>Another file is what seems to be an updated firmware for the device, <code>Firmware.bin</code> weighing 4 MB. And dating back to August the 25th, 2020.</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9kcml2ZS5nb29nbGUuY29tL2RyaXZlL2ZvbGRlcnMvMVRHTkFPV0taWmJDelp1Vklta2xBMThJSF9jVXZ0a055P3VzcD1zaGFyaW5n">Download Link</span></p>
<h3 id="analysis"><a class="markdownIt-Anchor" href="#analysis">#</a> Analysis</h3>
<p>A Couch potato is a lazy guy that sits in front of the TV screen, indicating that we are dealing with a console, set-top-box STB or Digital Video Recorder DVR and not a PCI card satellite/Tuner card or a computer. The user mentioned that he was watching his favorite channel when he fall asleep which make it more likely an STB, or a receiver for simplicity.<br>
This also means that the show name we are looking for was broadcasted in his favorite channel.</p>
<p>The user also mentioned that the device failed him, which means that the device is not responding to the commands he is sending to it. Kind of talking about a control unit, or that’s clearly a remote control that has some keys malfunctioning, specifically the UP and DOWN arrow keys as we know.</p>
<p>On other hand, the user is suspecting that the IPTV subscription was the thing behind the interruption of his channel. This means that the IPTV subscription was a service provided by the device itself or maybe a third party service. This also means that the STB we’re dealing with is a hybrid device, meaning that it can receive satellite signals and also IPTV, making it a 2nd generation STB and there are plenty in the market today, for third world countries.</p>
<p>However, the user could be mistaken as the channels that you can shortlist in the favorites are more likely to be satellite channels, hence the IPTV subscription is not the reason behind the interruption of his favorite channel rather than the satellite signal itself or the cardsharing service he is using.</p>
<p>With all that in mind, we can start our information gathering phase.</p>
<h3 id="information-gathering"><a class="markdownIt-Anchor" href="#information-gathering">#</a> Information Gathering</h3>
<p>TL;DR.</p>
<p>The thing is devices like this are hard to find in UK, Europe and the US. Unlike Africa and Asia. That’s because in European countries and the US, they are mostly banned due to the fact that they are used for cardsharing and IPTV piracy. However, in Africa and Asia, they are still widely used and sold.</p>
<p>So where to look? These devices are not open source nor they have some kind of documentation is to where to look in their ROMs. Satellite forums, subreddits, and Facebook groups are good resources and some deep search would yield some useful tools and details to deal with dump. We kind of need to know how the memory is splitted. The file is indeed a ROM/EEPROM snapshot, so it has a mapping of the memory. We just need to know where the information part is, channel list is, and applications or services are.</p>
<p>The mapping generally includes the following:</p>
<ul>
<li>Bootloader</li>
<li>Kernel or maincode</li>
<li>User data</li>
<li>Menu</li>
<li>…</li>
</ul>
<p>Each at specific offsets and specific lengths. The user data is the most important part as it contains the channel list.</p>
<p>Keep in mind that if the IPTV subscription was provided by the device itself, then the expiration date could be stored in the device itself or their renewal website. If the IPTV subscription was provided by a third party service, then the expiration date is stored in the third party service database or user panel. In both cases, we need to find the device serial number or MAC address to be able to identify the device and the user. I believe that how they are likely to be stored in the memory dump rather than a plain expiration date.</p>
<h3 id="resources"><a class="markdownIt-Anchor" href="#resources">#</a> Resources</h3>
<ul>
<li><span class="exturl" data-url="aHR0cHM6Ly93d3cuc2F0ZWxsaXRlcy5jby51ay9mb3J1bXMv">https://www.satellites.co.uk/forums/</span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly93d3cucmVkZGl0LmNvbS9yL3NhdGVsbGl0ZS8=">https://www.reddit.com/r/satellite/</span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly93d3cudHVuaXNpYS1zYXQuY29tL2ZvcnVtcy8=">https://www.tunisia-sat.com/forums/</span></li>
<li><span class="exturl" data-url="aHR0cHM6Ly9zYXQtdW5pdmVyc2UuY29tLw==">https://sat-universe.com/</span></li>
</ul>
<h3 id="tools"><a class="markdownIt-Anchor" href="#tools">#</a> Tools</h3>
<p>HexWorkshop / HxD Editor is a good tool to start with. It is a hex editor that can be used to view and edit files in hexadecimal and binary formats. It is a good tool to start with as it can be used to view the memory dump and search for strings. It can also be used to search for patterns and hex values.</p>
<h3 id="writeup-2"><a class="markdownIt-Anchor" href="#writeup-2">#</a> Writeup</h3>
<p>First, let’s investigate the dump file.</p>
<p><code>NCRCBootloader</code> is the start point, which is the bootloader used for these chipsets as indicated in the Hex Editor screen:</p>
<ul>
<li>ALI3329</li>
<li>ALI3606</li>
<li>ALI3601</li>
<li>ALI3511</li>
<li>ALI3510</li>
<li>ALI3516</li>
<li>ALI3618</li>
<li>ALI3821</li>
</ul>
<p><img data-src="https://i.imgur.com/vSB9IGX.png" alt=""></p>
<p>Devices with those chipset have these brands <em>Starsat, Sunplus, Tiger, StarMax, Geant, Mediastar, QMAX, AzAmerica, Samsat and many more…</em></p>
<p>And all of their built-in subscriptions are part of <strong>Gosat</strong>.</p>
<p>Now, to actually find the specific brand and model, we need to inspect the firmware update file.</p>
<p>To clear things up, the memory dump serves for user data mainly the channels and services as I said while the firmware update file will indicate the remote control being used.</p>
<p>The memory dump is a mapping and can be splitted manually and further investigated. However the firmware is encrypted, you can tell by a first glance, no strings or something in there, and can’t help us much to delve into the remote control unit in use.</p>
<p>Time to google for a way to decrypt such chipset firmware. Let’s use the keyword <code>ALI3329</code> or <code>ALI3511</code> as they are the most common chipset used in these devices and combine the search with decrypt or unpack tool.</p>
<p>For example:</p>
<p><img data-src="https://i.imgur.com/DfscXB4.png" alt=""></p>
<p>And in Arabic:</p>
<p><img data-src="https://i.imgur.com/rdG9k09.png" alt=""></p>
<p>Using the tool, we determine that the model is SR-2000HD HYPER and the remote control is SR-2000HD HYPER. Hence the brand is Starsat.</p>
<p><img data-src="https://i.imgur.com/uWfBYaJ.png" alt=""></p>
<p>The unpack and repack features are used to decrypt and extract parts of the firmware like the bootloader, maincode, user data if any was supplied by the manufacturer, the menu, the remote, and sometimes a softcam (that’s out of our scope today, maybe in another challenge!). And the repack to insert modified parts and RSA encrypt the whole thing again. Like for instance, we can insert the main menu (including themes and applications) or the remote control unit of a different model or brand and repack it to be used with the device we have, as long as they are using the very same chipset. Well this time, rest assured it is the Hyper remote control and when we talk about key code we mean the IR Infrared key code.</p>
<p>So the whole memory dump thing and the firmware kind of contain similar stuff at least, one being encrypted and the other not.</p>
<p>See here, the content of the folder when unpacked.</p>
<p><img data-src="https://i.imgur.com/P8IBsRt.png" alt=""></p>
<p>So why not, giving the dump a try and unpack it as well, we are chasing the user data part anyway. And the tool might very much help. Otherwise I will show how to proceed manually knowing the offsets and lengths found on a forum.</p>
<h3 id="finding-the-show"><a class="markdownIt-Anchor" href="#finding-the-show">#</a> Finding the show</h3>
<p>As we said before, we can deal with this part either using the tool or manually.<br>
Well, the tool was able to yield this:</p>
<p><img data-src="https://i.imgur.com/f1fon6N.png" alt=""></p>
<p>Very nice, we can see <code>database.sdx</code> file there!</p>
<p>Well, to proceed manullay you need to know the offsets and lengths beforehand.<br>
This is what we meant:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : Bootloader.bin</span><br><span class="line">SIZE : 128,00 KB</span><br><span class="line">CRC : 0x00AF7F6C</span><br><span class="line">offset : 0x00000128</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : maincode.bin</span><br><span class="line">SIZE : 3,25 MB</span><br><span class="line">CRC : 0x19E8C348</span><br><span class="line">offset : 0x00020128</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : menu.bin</span><br><span class="line">SIZE : 1,38 MB</span><br><span class="line">CRC : 0x10934143</span><br><span class="line">offset : 0x00360128</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : Database.sdx</span><br><span class="line">SIZE : 9,80 KB</span><br><span class="line">CRC : 0x00146C71</span><br><span class="line">offset : 0x004C0128</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : softcam.bin</span><br><span class="line">SIZE : 42,38 KB</span><br><span class="line">CRC : 0x008D5F15</span><br><span class="line">offset : 0x004C2860</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : sattp.bin</span><br><span class="line">SIZE : 12,54 KB</span><br><span class="line">CRC : 0x00097FDA</span><br><span class="line">offset : 0x004CD1E8</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br><span class="line">Name : Padding.bin</span><br><span class="line">SIZE : 522,06 KB</span><br><span class="line">CRC : 0x040E1F6B</span><br><span class="line">offset : 0x004D040C</span><br><span class="line">++++++++++++++++++++++++++++++++++++++</span><br></pre></td></tr></table></figure>
<p>Found here: <span class="exturl" data-url="aHR0cHM6Ly93d3cudHVuaXNpYS1zYXQuY29tL2ZvcnVtcy90aHJlYWRzLzMyNDI3NjEvcGFnZS00Nw==">https://www.tunisia-sat.com/forums/threads/3242761/page-47</span></p>
<p>We know <code>database.sdx</code> holds the user data meaning the channels. sattp is another file that holds the different satellites and their frequencies aka transponders.</p>
<p>When we open the file in a hex editor, We can’t read any useful information out of it. This means that there should be a tool in place to view and edit the channels for the specific chipset family we are dealing with as the file seems highly compressed.</p>
<p>Here’s a view from hex editor first.</p>
<p>Starts off like this</p>
<p><img data-src="https://i.imgur.com/7FHWF6K.png" alt=""></p>
<p>And ends padded with 0xFF</p>
<p><img data-src="https://i.imgur.com/xqvWPxc.png" alt=""></p>
<p>Let’s google a bit…</p>
<p><img data-src="https://i.imgur.com/P5bXWY4.png" alt=""></p>
<p>We got this</p>
<p><img data-src="https://i.imgur.com/hVzUWC9.png" alt=""></p>
<p>When trying to first open the database, we got this error message</p>
<p><img data-src="https://i.imgur.com/ASWzJB9.png" alt=""></p>
<p>And the issue is that the Userdata has a static size as indicated before. As the receiver’s capacity fits a maximum of 6100 channels. So the database file is padded with 0xFF to reach the maximum size. Let’s get rid of the padded data and try again…</p>
<p><img data-src="https://i.imgur.com/NUIk82u.png" alt=""></p>
<p>Now, it’s working like charm, and I already see some familiar TV channels on Astra 1 (19.2 East).</p>
<p>Let’s expand the favorites section</p>
<p><img data-src="https://i.imgur.com/AmkpQPE.png" alt=""></p>
<p>And there is Sky Sports Main Event, UK-based sports channel that is part of BSkyB or Sky Group, pay-television channel and availble for satellite subsribers via Eurobird 1, Astra 2 (28.2 East). Sky Sports Main Event broadcasts the biggest events of sports in the UK.</p>
<p>Now, great work to reach this point, but we are not done yet. We need to find the right show at that past date, meaning at 1:07 AM on February the 1st, 2020.</p>
<p>Well, Sky TV Guide won’t keep such data for more than a week or two, so we need to find another way.</p>
<p>Guess you know what we mean, what else than the way back machine!</p>
<p>Head over to <span class="exturl" data-url="aHR0cDovL2FyY2hpdmUub3Jn">archive.org</span> and submit the link for the Sky TV Guide and try to narrow your search to a date that’s equal or close to the date in question, as shown below!</p>
<p><img data-src="https://i.imgur.com/B5scqzJ.png" alt=""></p>
<p>And that is the first part of the flag: <code>live_rugby_7's</code> or <code>live_rugby_7s</code></p>
<h3 id="finding-the-keycodes"><a class="markdownIt-Anchor" href="#finding-the-keycodes">#</a> Finding the keycodes</h3>
<p>We know it is Starsat SR-2000HD Hyper’s remote control, well unless you have the same remote control or probably a remote of the same brand and an Arduino card embedded with an IR receiver, you will need to improvise! Like check online there GitHub repos that keep track of IR key codes for different remotes. Or you can use a forum like <span class="exturl" data-url="aHR0cHM6Ly93d3cucmVtb3RlY2VudHJhbC5jb20v">https://www.remotecentral.com/</span> to find the key codes for the remote control.</p>
<p>However for this part, we will use an Android app like IRplus or any alternatives and pick the device in question from the list then head over to check the keys, we will provide screenshots for what we’ve found. Since it is the simplest and fastest way.</p>
<p>This is the LIRC protcol of Starsat <span class="exturl" data-url="aHR0cHM6Ly9saXJjLnNvdXJjZWZvcmdlLm5ldC9yZW1vdGVzL3N0YXJzYXQvMTIw">https://lirc.sourceforge.net/remotes/starsat/120</span></p>
<p>We are looking for NEC, so we found an app for that.</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9pcnBsdXMtcmVtb3RlLmdpdGh1Yi5pby8=">net.binarymode.android.irplus</span></p>
<ol>
<li>Selecting the remote control from the list:</li>
</ol>
<p><img data-src="https://i.imgur.com/3hjuMYS.png" alt=""></p>
<ol start="2">
<li>Exporting the remote config and checking the Channel Up arrow and Channel Down arrow</li>
</ol>
<p><img data-src="https://i.imgur.com/lsXXO6K.png" alt=""></p>
<p>And that is the second part of the flag: <code>00ff30cf_00ff8877</code></p>
<p>we can make sure that is the correct format using a website like <span class="exturl" data-url="aHR0cHM6Ly93d3cueWFtYWhhLmNvbS95cGFiL2lyaGV4X2NvbnZlcnRlci5hc3A=">https://www.yamaha.com/ypab/irhex_converter.asp</span><br>
converting NEC 32-bit to Pronto hex format (RAW HEX) and then to global caché to see the full sendIR command…</p>
<h3 id="finding-the-expiration-date"><a class="markdownIt-Anchor" href="#finding-the-expiration-date">#</a> Finding the expiration date</h3>
<p>Now for the fun part, if you dig around the web about Starsat 2000 Hyper you will end up with one official built in service, Apollo that offers IPTV as well as VOD Video on Demand.</p>
<p>And there is an online service to renew and check your current subscription by just providing the serial number.</p>
<p><span class="exturl" data-url="aHR0cDovL3d3dy5yZW5ld2JveC5uZXQvaW5kZXgucGhw">www.renewbox.net</span></p>
<p>The serial number in most cases is a long number like consists of maybe more than 10 digits. And it can’t be in the firmware since it is released to the public to update their devices. So it must be within the memory of the device itself.</p>
<p>Let’s grep that easily!</p>
<p><img data-src="https://i.imgur.com/XmWhATI.png" alt=""></p>
<p>And there it is, the serial number, let’s query the IPTV validity.</p>
<p><img data-src="https://i.imgur.com/lTGDuFS.png" alt=""></p>
<p>And the last part of the flag is <code>20141105</code></p>
<h3 id="final-words"><a class="markdownIt-Anchor" href="#final-words">#</a> Final Words</h3>
<p>Flag: <strong>Securinets{live_rugby_7s_00ff30cf_00ff8877_20141105}</strong></p>
<p>GGs <strong>th3_r0n1ns</strong> for solving this challenge</p>
</content>
<updated>2023-08-06T18:00:00.000Z</updated>
</entry>
<entry>
<id>http://example.com/2023/06/03/Kubernetes/post/</id>
<title>Streamlined Application Deployemet using Kubernetes</title>
<link rel="alternate" href="http://example.com/2023/06/03/Kubernetes/post/"/>
<content type="html"><h1 id="introduction"><a class="markdownIt-Anchor" href="#introduction">#</a> Introduction</h1>
<p>As second-year engineering students, we embarked our academic group project that pushes us beyond our limits. Being self-proclaimed cloud-native and Kubernetes geeks, we decided to venture into an unfamiliar territory with an advanced project. Our goal? To unravel the mysteries of Heroku, Vercel, and On-Render, the leading PaaS solutions! And here is the twist, we were running out of time, and neither ChatGPT nor Google can help us. We are mad, and we actually did it in 4 days! Fellow adventurers, let’s get you to feel the glimpse of what we have been through in just 4 days to build our project codenamed Kli8nt for streamlined application deployments into the Kubernetes realm</p>
<p>Fueled by the increasing demand for a unified platform that encompasses front-end hosting, backend deployment, and database management, our team leveraged our expertise in DevOps, Kubernetes, and web development to establish a robust and scalable solution that is client-friendly and K8s-able, hence the name Kli8nt. It is our way to design a mechanism that’s a proof-of-concept to the leading PaaS solutions</p>
<h1 id="project-details"><a class="markdownIt-Anchor" href="#project-details">#</a> Project Details :</h1>
<h2 id="high-level-architecture"><a class="markdownIt-Anchor" href="#high-level-architecture">#</a> High Level Architecture</h2>
<p>Our system consists of various interconnected components that work together seamlessly. At the front-end, users interact with the system and provide the necessary information for application deployment. The backbone of our system is the backend, which handles authentication, data storage, and serves as the communication hub with the clusters. It establishes a websocket connection to deliver real-time logs to the user. To facilitate efficient communication between the backend and clusters, we rely on RabbitMQ, a messaging system that ensures reliable information exchange. The clusters themselves take charge of the build and deployment operations, guided by custom controllers to ensure efficiency and accuracy. Lastly, Kafka, our robust data streaming platform, stores and streams application logs from the clusters to the user. Together, these components form a cohesive system that enables smooth and efficient application deployment.</p>
<p><img data-src="https://i.imgur.com/fEOyFeQ.png" alt=""></p>
<h2 id="user-interface"><a class="markdownIt-Anchor" href="#user-interface">#</a> User Interface</h2>
<p>The User Interface serves as the primary interaction point for developers using the<br>
Kli8nt platform. Designed with simplicity and ease of use in mind, the UI provides<br>
a seamless experience for users to connect to their GitHub accounts, manage their<br>
repository specifications, and initiate deployments. We aim to streamline the<br>
application management process and empower developers to effortlessly deploy<br>
their applications.</p>
<p><img data-src="https://imgur.com/O5fW0GG.png" alt=""></p>
<h2 id="user-authentication"><a class="markdownIt-Anchor" href="#user-authentication">#</a> User Authentication</h2>
<p>Kli8nt leverages the robust authentication capabilities of GitHub OAuth2 as its primary method for user login and authorization. By utilizing this powerful authentication mechanism, users can grant the platform access to their repositories. With the generated Personal Access Token (PAT) associated with the authenticated user, Kli8nt gains the ability to clone both private and public repositories, utilizing the functionalities provided by the GitHub API. This approach ensures secure and seamless integration with GitHub, allowing users to enjoy a streamlined experience while maintaining the necessary permissions and access controls.</p>
<p><img data-src="https://imgur.com/KEoSXvr.png" alt=""></p>
<h2 id="backend-service"><a class="markdownIt-Anchor" href="#backend-service">#</a> Backend Service</h2>
<p>The backend service is the backbone of the platform, ensuring efficient functionality by handling user requests, processing deployment tasks, managing logs, and facilitating seamless communication between components. It plays a vital role in request handling and routing, ensuring user requests are directed to the appropriate components for further processing. Additionally, it handles user authentication and authorization, ensuring secure access to the platform. Integration with RabbitMQ allows for the handling and queuing of deployment requests, while task scheduling ensures efficient and ordered processing. The backend service also integrates with GitHub’s Deployment Environment, facilitating synchronization and updates for deployments. Logs are streamed and stored using Kafka, with a backend endpoint responsible for streaming logs back to users for monitoring. Database interaction with PostgreSQL allows for data storage and retrieval related to user configurations, deployment records, and other relevant information, ensuring data consistency and integrity through GORM. Overall, the backend service acts as a crucial orchestrator, ensuring the smooth operation and effective management of the platform’s core functionalities.</p>
<p><img data-src="https://i.imgur.com/WyYpyTw.png" alt=""></p>
<h2 id="the-messaging-queue-system"><a class="markdownIt-Anchor" href="#the-messaging-queue-system">#</a> The Messaging Queue System</h2>
<p>To manage and queue deployment requests, we’ve integrated RabbitMQ. Simply put, it is a software where queues are defined, to which applications connect in order to transfer messages. For when a deployment request is received, the backend enqueues the task into a BUILD queue to the Kubernetes BUILD Operator. This ensures that each task is processed in the right order. The Kubernetes DEPLOY Operator in turn enqueus deployment results back here though the INFORM queue.</p>
<p><img data-src="https://i.imgur.com/zNOA4Lz.png" alt=""></p>
<h2 id="the-build-and-deploy-kubernetes-custom-controller"><a class="markdownIt-Anchor" href="#the-build-and-deploy-kubernetes-custom-controller">#</a> The Build and Deploy Kubernetes Custom Controller</h2>
<p>The clusters are responsible for the build and deployment operations. These processes are managed by custom controllers, ensuring efficiency and accuracy in deploying applications.</p>
<p><img data-src="https://i.imgur.com/kTZmlxJ.png" alt=""></p>
<h2 id="the-build-kubernetes-custom-controller"><a class="markdownIt-Anchor" href="#the-build-kubernetes-custom-controller">#</a> The Build Kubernetes Custom Controller</h2>
<p>The build controller plays a critical role in initiating the build process for each application. It acts as a listener for the queue served by RabbitMQ, enabling it to initiate the build process. When a new application is added to the queue, the controller creates an isolated environment specifically for that application. Within this isolated environment, it launches a dedicated build process. This process involves tasks such as cloning the repository and generating a Dockerfile based on the application’s stack and programming language, starting the Kaniko process to initiate the build, which includes compiling the source code, resolving dependencies, and creating a container image then pushing the resulting container image to a private registry.</p>
<p>After completing the build and push process, the isolated environment is terminated and deleted, in addition, the controller publishes a message to the deployment queue served by RabbitMQ. This queue holds the applications that are scheduled to be deployed by the deploy controller. This ensures a clean and efficient workflow, as each build process operates in its isolated context. By leveraging the build controller’s capabilities, applications can be built and prepared for deployment without interference or conflicts with other ongoing builds</p>
<h2 id="the-deploy-kubernetes-custom-controller"><a class="markdownIt-Anchor" href="#the-deploy-kubernetes-custom-controller">#</a> The Deploy Kubernetes Custom Controller</h2>
<p>After the build process concludes and the build controller sends an element to the queue, the deploy controller consumes the queue and initiates the deployment process. This involves creating a deployment object that includes a pod. The application’s Docker image is then pulled and run within this pod. Simultaneously, a cluster IP service is created and associated with the deployment, enabling internal communication within the cluster.</p>
<p>The deploy controller takes charge of exposing the application externally and adding a TLS/SSL certificate. It achieves this by adding a route rule for the service within the ingress configuration. Additionally, it adds TLS/SSL configuration to the Ingress, allowing the application to be accessed securely via HTTPS. By utilizing Nginx Ingress, the controller ensures that the application is reachable and accessible with the desired HTTPS protocol and has a specific subdomain for the application.</p>
<p>Once the application is successfully deployed and exposed to the TLS certificate, the deploy controller notifies the backend server that the application is now ready for user access. This communication informs the backend server that the newly deployed application is available and can be utilized by users.</p>
<h2 id="the-log-streaming-controller"><a class="markdownIt-Anchor" href="#the-log-streaming-controller">#</a> The Log Streaming Controller</h2>
<p>Another important aspect in such provided service, is that the user would like to have a vision over his application while and after its being prepared and sent to production. To deliver such a feature, we have implemented another controller in go, that’s responsible for listening to Pod’s lifecycle events, made possible thanks to the Shared Informer feature in the Kubernetes API which is a local cache kind of resource made to be consumed. Whenever a new Deployment is up and running, grab its logs and stream them real time to another environment to be stored. This environment being Apache Kafka, an open source distributed message streaming that’s suited for high performance data pipelines. Our Kafka is running in its own managed cluster at Confluent, a KaaS provider with additional cool features that we liked while using them (like a nice user-friendly dashboard, a built-in REST API, etc…). Kafka is going to stream the logs, each application in its own kafka topic or event, directly to the backend, and store them for future requests -so you don’t really have to be there at the right time, whenever you request them you’ll get them and if you are there already you get them live.</p>
<p><img data-src="https://i.imgur.com/UomqhLd.png" alt=""></p>
<h1 id="the-conclusion"><a class="markdownIt-Anchor" href="#the-conclusion">#</a> The conclusion</h1>
<p>Our end-of-year project theoretically proposes and empirically validate a system design able to streamline the process of deploying any mciroservice application living in Github to Kubernetes on Cloud. This project is our gateway to our graduation projects as well as internship opportunities this summer, and would be a great addition to our professional journeys</p>
<h1 id="meet-the-team"><a class="markdownIt-Anchor" href="#meet-the-team">#</a> Meet the Team</h1>
<p>Along with the immense support from our supervisor Mr. Bassem Ben Saleh and his esteemed jury.<br>
We would like to extend a heartfelt thank you to our families and close ones for their support and encouragement during late nights and long hours of work.</p>
<div class="links"><div class="item" title="Mohamed Rafraf - Raf²" style="--block-color:#2296fd;"><span class="exturl image" data-url="aHR0cHM6Ly9tb2hhbWVkLXJhZnJhZi5naXRodWIuaW8=" data-background-image="https://media.licdn.com/dms/image/C4D03AQGoi9OLQy5yfg/profile-displayphoto-shrink_800_800/0/1635769397295?e=1691020800&v=beta&t=IOYj31PodnHo-vWlY3lHvfLTCAzBeGPclWqCkdQl1bE"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly9tb2hhbWVkLXJhZnJhZi5naXRodWIuaW8=">Mohamed Rafraf - Raf²</span>
<p class="desc">Kubernetes Engineer</p>
</div></div><div class="item" title="Adam Lahbib - Adm" style="--block-color:#de2336;"><span class="exturl image" data-url="aHR0cHM6Ly9hZGFtbGFoYmliLm1l" data-background-image="https://media.licdn.com/dms/image/D4D03AQEeg7KDib8qCQ/profile-displayphoto-shrink_800_800/0/1682525314941?e=1691020800&v=beta&t=O-T0VjepTffxrdxGNc4jwwPleeh-rt6RWlMF6gol1VQ"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly9hZGFtbGFoYmliLm1l">Adam Lahbib - Adm</span>
<p class="desc">Backend Engineer / DevOps</p>
</div></div><div class="item" title="Med Sofiene Barka - NieMand" style="--block-color:#02bf1b;"><span class="exturl image" data-url="aHR0cHM6Ly93d3cuaG1sbmRyLm1lLw==" data-background-image="https://pbs.twimg.com/profile_images/1607462313182756867/WHEAVH9d_400x400.jpg"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly93d3cuaG1sbmRyLm1lLw==">Med Sofiene Barka - NieMand</span>
<p class="desc">Software Engineer</p>
</div></div><div class="item" title="Skander Soltane - RedNax" style="--block-color:#ff0378;"><span class="exturl image" data-url="aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL3NrYW5kZXItc29sdGFuZQ==" data-background-image="https://media.licdn.com/dms/image/D4D03AQGD3BI1PkShag/profile-displayphoto-shrink_800_800/0/1676590747987?e=1691020800&v=beta&t=Jo1SN1nqWZCCeJ7KyxP1f6NgWUPw4DyMGmkXPQrYvWg"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL3NrYW5kZXItc29sdGFuZQ==">Skander Soltane - RedNax</span>
<p class="desc">Software Developer</p>
</div></div><div class="item" title="Dr. Bassem Ben Salah" style="--block-color:#de2336;"><span class="exturl image" data-url="aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL2Jhc3NlbS1iZW4tc2FsYWgtMzQ4N2EyNTkv" data-background-image="https://media.licdn.com/dms/image/C4D03AQEuhp7TFHjE3Q/profile-displayphoto-shrink_800_800/0/1549533675903?e=1691020800&v=beta&t=AuBIN0Obuyu-dqcWr2HWZMS9qJNZKzAJiw5KnuVOLSg"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL2Jhc3NlbS1iZW4tc2FsYWgtMzQ4N2EyNTkv">Dr. Bassem Ben Salah</span>
<p class="desc">Our Supervisor</p>
</div></div></div>
</content>
<updated>2023-06-03T16:38:55.000Z</updated>
</entry>
<entry>
<id>http://example.com/2023/04/28/Kubernetes/k8s-auth/</id>
<title>SSO-based authentication mechanism for multi-clusters</title>
<link rel="alternate" href="http://example.com/2023/04/28/Kubernetes/k8s-auth/"/>
<content type="html"><h1 id="introduction"><a class="markdownIt-Anchor" href="#introduction">#</a> Introduction</h1>
<h2 id="how-it-comes"><a class="markdownIt-Anchor" href="#how-it-comes">#</a> How it comes</h2>
<p>As a university student, I was assigned to create an authentication project for a specific system. But instead of choosing a traditional approach like Kerberos, I decided to spice things up and bring Kubernetes and cloud-native technologies into the mix (Typical Me). After diving into the official documentation, I was hit with a barrage of authentication strategies like X509 client certs, Static Token File, Bootstrap tokens, Service Accounts, OIDC tokens, and more. My head was spinning! Then I stumbled upon some existing authentication tools like Dex, Keycloak, and Pinniped. Terms like OIDC and OAuth2 were thrown around left and right. But I wasn’t intimidated! I accepted the challenge and declared: “It’s implementation time!” And thus, the k8s-auth project was born.</p>
<h2 id="why-k8s-auth-is-born"><a class="markdownIt-Anchor" href="#why-k8s-auth-is-born">#</a> Why k8s-auth is born</h2>
<p>Managing access to Kubernetes clusters can be a challenging task, especially in large organizations where multiple teams and users need different levels of permissions. While Kubernetes provides a robust RBAC system, configuring and maintaining it can be time-consuming and error-prone, particularly if you have many clusters to manage.<br>
It can feel like you’re playing a never-ending game of whack-a-mole, trying to keep up with the constant changes and updates. And let’s be honest, it’s not the most exciting task in the world. Moving from one cluster to another, constantly changing contexts, generating kubeconfig for users, and dealing with permission problems can quickly become a chore.</p>
<p><img data-src="https://imgur.com/a5zaVhH.png" alt=""></p>
<h2 id="before-starting"><a class="markdownIt-Anchor" href="#before-starting">#</a> Before Starting</h2>
<p>Before you start reading this blog post, let’s make sure you’re ready to dive into the k8s-auth server world. First, make sure you have a solid understanding of Kubernetes basics and RBAC, as we’ll be building on those concepts. Don’t worry, we won’t ask you to explain any Kubernetes concept in binary code. We just need you to understand what a service account is, what roles and role bindings mean, and why a service account needs a secret. So, if these concepts are still a mystery to you, go ahead and brush up on your Kubernetes knowledge before jumping in. And if you need a refresher, don’t worry, we won’t judge you. We’ll just send you back to Kubernetes school.</p>
<h1 id="k8s-auth-the-sso-based-authentication-mechanism-for-multi-clusters"><a class="markdownIt-Anchor" href="#k8s-auth-the-sso-based-authentication-mechanism-for-multi-clusters">#</a> K8S-AUTH : The SSO-Based Authentication Mechanism for Multi-Clusters!</h1>
<h2 id="what-is-k8s-auth"><a class="markdownIt-Anchor" href="#what-is-k8s-auth">#</a> What is k8s-auth ?</h2>
<p>K8s-auth is a tool that provides authentication and authorization mechanisms for multiple Kubernetes clusters. With k8s-auth, users can authenticate to multiple clusters using a single set of credentials. This eliminates the need for users to have different credentials for different clusters, simplifying the authentication process. K8s-auth also allows administrators to manage user and group permissions across multiple clusters from a single centralized location, making it easier to maintain security and access control.</p>
<p><img data-src="https://imgur.com/awkZvAb.png" alt=""></p>
<h2 id="the-authentication-server"><a class="markdownIt-Anchor" href="#the-authentication-server">#</a> The Authentication server</h2>
<p>“K8s-Auth Server” is an open-source authentication server designed to simplify the authorization and authentication process for users and groups within specific Kubernetes clusters. With this server, administrators can easily manage access controls for multiple clusters, all from a centralized location.</p>
<p>With the k8s-auth server, you can say goodbye to the headache of managing RBAC configurations across multiple clusters. Instead, you can focus on the fun part of being an admin - creating users, deleting users, modifying users, creating groups, deleting groups, modifying groups, and more! And the best part? You get to do it all with a single set of credentials, like a master key that unlocks all the doors to the kingdom of Kubernetes.</p>
<p>But wait, there’s more! With SSO-based access, users can connect to multiple clusters with different permissions based on their role on each cluster, all without having to enter a password a million times. It’s like having a backstage pass to all the coolest Kubernetes events without ever having to wait in line.</p>
<h2 id="how-this-server-communicate-with-clusters"><a class="markdownIt-Anchor" href="#how-this-server-communicate-with-clusters">#</a> How This Server Communicate with Clusters ?</h2>
<p>K8s-Auth Server is designed to work seamlessly with K8s-Auth Controller, a cloud-native application that is deployed within the Kubernetes cluster. This controller acts as an agent for the server, facilitating communication between the server and the cluster.</p>
<p><img data-src="https://imgur.com/0PK9Sj5.png" alt=""></p>
<p>Before a cluster can be used with K8s-Auth Server, it must be registered with the server by the administrator. When a cluster is registered, a secret token is created, which must be used by the agent/controller deployed within the cluster to verify its existence. Once the agent/controller is verified, a connection between the cluster and the server is opened (web socket) for data communication.</p>
<p><img data-src="https://imgur.com/F1EVKK3.png" alt=""></p>
<h2 id="how-to-interact-with-this-server"><a class="markdownIt-Anchor" href="#how-to-interact-with-this-server">#</a> How to interact with this Server</h2>
<p>K8s-Auth Server comes with a powerful CLI utility that can be used by both administrators and users. The CLI behaves differently based on the user’s role - administrators can create, modify, and delete users, groups, and clusters, while normal users can check the clusters that they are authorized to connect with. Once the users selects the cluster they want to authenticate with, the CLI will automatically generate a kubeconfig file, making it easy for users to connect to the cluster and start working.</p>
<h2 id="how-users-logs-to-the-server"><a class="markdownIt-Anchor" href="#how-users-logs-to-the-server">#</a> How users logs to the server</h2>
<p>To connect to any cluster, users must first authenticate with the K8s-Auth Server. Authentication with the server is done using OAuth2 with Google, allowing users to use one set of credentials to connect to multiple clusters with different permissions based on their role on each cluster. This type of authentication can be referred to as SSO-based authentication.</p>
<h2 id="what-happen-when-user-want-to-authenticate-to-a-cluster"><a class="markdownIt-Anchor" href="#what-happen-when-user-want-to-authenticate-to-a-cluster">#</a> What happen when user want to authenticate to a cluster ?</h2>
<p>On the user side, when a user logs into the K8s-Auth Server, they can check the clusters they are authorized to access. After selecting the desired cluster, a request is sent to the server, which checks if the user is authorized to connect. If authorized, the server sends a request to the specific agent/controller, which creates the necessary Kubernetes resources, such as service accounts, roles, role bindings, and secrets, allowing the user to connect to the cluster and return the token and ca.crt that allow the automatic generation of the kubeconfig.</p>
<h2 id="the-agentcontroller-role"><a class="markdownIt-Anchor" href="#the-agentcontroller-role">#</a> The Agent/Controller role</h2>
<p>The agent/controller also manages the lifecycle of the secret and token, deleting them and all related roles and bindings after they expire or are no longer needed. For example, if an administrator decides to remove a user from a cluster, the agent/controller will delete the secret that holds the user’s token, as well as the service account, roles, and bindings associated with that user.</p>
<h2 id="before-demo"><a class="markdownIt-Anchor" href="#before-demo">#</a> Before DEMO</h2>
<div class="note danger">
<p>Please note that this project is open source and the code is available to anyone interested. It is currently an MVP version that functions effectively, and we plan to add more features in the future.</p>
</div>
<div class="note warning">
<p>Don’t forget that this project is open to contributions from the community! If you find a bug or have a feature request, feel free to open an issue on the project’s GitHub page. And if you’re interested in helping out with the development, pull requests are always welcome! Let’s work together to make this project even better.</p>
</div>
<div class="links"><div class="item" title="k8s-auth-server" style="--block-color:#2296fd;"><span class="exturl image" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLXNlcnZlcg==" data-background-image="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLXNlcnZlcg==">k8s-auth-server</span>
<p class="desc">The authentication server</p>
</div></div><div class="item" title="k8s-auth-kube" style="--block-color:#de2336;"><span class="exturl image" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLWt1YmU=" data-background-image="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLWt1YmU=">k8s-auth-kube</span>
<p class="desc">The Controller/Agent for k8s-auth</p>
</div></div><div class="item" title="k8s-auth-cli" style="--block-color:#02bf1b;"><span class="exturl image" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLWNsaQ==" data-background-image="https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"></span>
<div class="info">
<span class="exturl title" data-url="aHR0cHM6Ly9naXRodWIuY29tL01vaGFtZWQtUmFmcmFmL2s4cy1hdXRoLWNsaQ==">k8s-auth-cli</span>
<p class="desc">The CLI utility for k8s-auth</p>
</div></div></div>
<h1 id="the-demo"><a class="markdownIt-Anchor" href="#the-demo">#</a> The DEMO !</h1>
<p>And the icing on the cake? I am going to show you how to set up and use k8s-auth in a demo that will blow your mind (in a good way, of course). So grab your popcorn and let’s get this Kubernetes party started!</p>
<p>Ladies and Gentlemen, it’s showtime! Let’s get ready to k8s-authenticate! We’ll be putting the spotlight on three stars of this demo: The Authentication Server, The Agent/Controller, and the Command Line Utility! These babies were born to shine in the Go language (talk about power!) and are all open-source, so you can check them out on my GitHub page. And, to make things even easier, we’ve containerized the authentication server and agent, so you can just pull them like a cold one on a hot summer day. Check out my Docker Hub profile for more juicy details!</p>
<h2 id="setting-up-authentication-server"><a class="markdownIt-Anchor" href="#setting-up-authentication-server">#</a> Setting up Authentication Server</h2>
<p>Hold your horses, folks! The authentication server may be containerized, but it’s not going inside Kubernetes! Don’t forget to set up those environment variables for the server - especially the admin email! (He deserve a name and a full name too, don’t they?) And guess what, the admin can log in with Google OAuth2! Just make sure to give the Client ID, Client Secret, and Redirection Link, or else things won’t work too smoothly.</p>
<blockquote>
<p>You need to create an OAuth 2.0 Client with the Google API in google cloud platform!</p>
</blockquote>
<p><img data-src="https://imgur.com/YqhD79J.png" alt=""></p>
<ul>
<li><code>K8S_AUTH_ADMIN_NAME</code> : The administrator name! (My name is default value)</li>
<li><code>K8S_AUTH_ADMIN_FULLNAME</code> : The administrator name! (My name is default value)</li>
<li><code>K8S_AUTH_ADMIN_MAIL</code> : The administrator name! (My email is default value)</li>
<li><code>OAUTH2_CLIENT_ID</code> : The google Oauth2 Client ID (Required)</li>
<li><code>OAUTH2_CLIENT_SECRET</code> : The google Oauth2 Secret (Required)</li>
<li><code>OAUTH2_REDIRECT_URL</code> : The google Oauth2 Redirect URL callback (Required, it must be redirected to /callback endpoint of your server )</li>
</ul>
<blockquote>
<p>Let’s assume that the server is deployed on <span class="exturl" data-url="aHR0cHM6Ly9hdXRoLjRuNm5rOHMudGVjaA==">https://auth.4n6nk8s.tech</span>,<br>
<code>OAUTH2_REDIRECT_URL</code> must be <span class="exturl" data-url="aHR0cHM6Ly9hdXRoLjRuNm5rOHMudGVjaC9jYWxsYmFjaw==">https://auth.4n6nk8s.tech/callback</span></p>
</blockquote>
<p>It’s docker time! <code>mohamedrafraf/k8s-auth-server</code> is the docker image that you need! Let’s run this server!</p>
<figure class="highlight bash"><figcaption><span>run server</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name server -it -p 80:8080 -e OAUTH2_CLIENT_ID=xxxx -e OAUTH2_CLIENT_SECRET=xxx ... mohamedrafraf/k8s-auth-server</span><br></pre></td></tr></table></figure>
<p>Make sure to input all the necessary variables for the server to run smoothly. And once you’ve done that, sit back and relax, and let the server do its thing! Keep your hands off those logs, let them flow in peace!</p>
<h2 id="interacting-with-server-using-k8s-auth-cli"><a class="markdownIt-Anchor" href="#interacting-with-server-using-k8s-auth-cli">#</a> Interacting with server using k8s-auth CLI</h2>
<p>It’s CLI installation time, folks! This nifty command line utility is your ticket to the k8s-auth party. With the CLI, you can log in as an admin or regular user and interact with the server based on your permission level.</p>
<p>But wait, there’s more! For the first time, only the admin with their fancy schmancy email address can access the server. They’ll be the ones registering the cluster, setting up the agent, and creating a connection between the server and the agent. Then, it’s time to have some fun with users, groups, and permissions. Who said authentication couldn’t be funny?</p>
<p>You can build the command line utility or download it by running:</p>
<figure class="highlight bash"><figcaption><span>download cli</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">wget https://github.com/Mohamed-Rafraf/k8s-auth-cli/releases/download/test/k8s-auth</span><br><span class="line">sudo <span class="built_in">chmod</span> +x k8s-auth &amp;&amp; sudo <span class="built_in">mv</span> k8s-auth /usr/bin</span><br></pre></td></tr></table></figure>
<p>Now, you can use this command line utility just like any other tool in your system!</p>
<p><img data-src="https://imgur.com/EciPajC.png" alt=""></p>
<p>Before start playing with this command line you need to know that on each command you need to specify the authentication server that you want to interact with! So either you user <code>--server</code> on each command or use <code>K8S_AUTH_SERVER</code> environment variable to make it more easy for you! I’ll go with the 2nd option!</p>
<figure class="highlight bash"><figcaption><span>export env var</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> K8S_AUTH_SEVER=https://auth.4n6nk8s.tech</span><br></pre></td></tr></table></figure>
<p>Now you need to log in as an adminstrator! It’s not that hard just run <code>k8s-auth login</code> and forget to specify <code>--admin</code> to login as the super user!</p>
<p><img data-src="https://imgur.com/10prjzn.png" alt=""></p>
<p>The utility needs a secret token, which you’ll get from an URL link. This link will take you to Google for authentication and authorization as an admin. Once you’re authorized, you’ll get the secret token to paste and everything will be good to go.</p>
<p>You’ll get something like this one in case you’re authorized!<br>
<img data-src="https://imgur.com/Yt9FZgD.png" alt=""></p>
<p>Copy that thing don’t worry! Once you paste it, the utility will verify the token and let you know if you’re ready for your actions or not!</p>
<p><img data-src="https://imgur.com/MY7TTOZ.png" alt=""></p>
<p>Bingo we are ready for action! Now as an admin you can register clusters, create,delete,modify users and groups (and their permissions) inside each cluster!</p>
<blockquote>
<p>Let’s assume that you have 2 clusters! You create a user inside cluster1 and you give him permission to list pods on dev namespace. You can add that user to cluster2 with other permission like create secrets on prod namespace</p>
</blockquote>
<p>It’s time to register a cluster! You’ll recieve a secret token.</p>
<p><img data-src="https://imgur.com/yvANfkB.png" alt=""></p>
<p>And as you see here! The cluster is registered using <code>k8s-auth create cluster</code> and you can list registred clusters with <code>k8s-auth get clusters</code></p>
<blockquote>
<p>Keep in mind that registerd cluster have 2 status, not Active when the cluster is not verified yet. The Active status will show you the API SERVER address/hostname</p>
</blockquote>
<blockquote>
<p>Only Admins can see the tokens! Running the same command as a regular user will list you only the clusters that you have access to it (so not all cluster) and without the token!</p>
</blockquote>
<p>Let’s take rest now from the CLI. It’s time for kubernetes! Let’s deploy the agent/controller that will communicate with the server!</p>
<h2 id="deploy-the-agentcontroller-inside-kubernetes"><a class="markdownIt-Anchor" href="#deploy-the-agentcontroller-inside-kubernetes">#</a> Deploy the Agent/Controller inside Kubernetes</h2>
<p>Deploying the agent is not rocket science! Deploying the agent is not rocket science! (To be honest i didn’t make a helm chart yet, Sadly 😦 ). But if you want to do it the old fashioned way, no worries! It’s still a piece of cake. Just keep in mind that you need to create a namespace called “k8s-auth” in your cluster. This namespace will contain all the service accounts and secrets of the users that authenticate and have a session with the cluster.</p>
<p>The agent’s mission is to make sure everyone gets what they need! It creates service accounts, roles, and role bindings to make sure users have the right permissions in the cluster. That’s why the agent itself needs a service account and permissions to do its job inside the cluster.</p>
<p>Let’s create the namespace and the service account for this agent!</p>
<figure class="highlight yaml"><figcaption><span>create ns & sa</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Namespace</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"><span class="attr">spec:</span> &#123;&#125;</span><br><span class="line"><span class="attr">status:</span> &#123;&#125;</span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ServiceAccount</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">k8s-auth</span></span><br></pre></td></tr></table></figure>
<p>This service account need a clusterrole that allow to create roles to anything! to grant permission for creating pods you must have this permission first! You can’t give permission of create something and you can’t do it!!!</p>
<p>Next, the service account will need an appropriate permissions to carry out its mission inside the cluster. Specifically, it requires a clusterrole that grants permission to create roles for any resource.</p>
<p>In kubernetes world, granting permission to create something requires that you have the permission yourself!. For example, you can’t grant permission to create pods if you don’t have permission to create pods even you have permission to create roles!!</p>
<p>Let’s create the clusterole and the binding!</p>
<figure class="highlight yaml"><figcaption><span>create cluster role</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ClusterRole</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;*&quot;</span>]</span><br><span class="line"> <span class="attr">resources:</span> [<span class="string">&quot;*&quot;</span>]</span><br><span class="line"> <span class="attr">verbs:</span> [<span class="string">&quot;*&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">ClusterRoleBinding</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"><span class="attr">roleRef:</span></span><br><span class="line"> <span class="attr">apiGroup:</span> <span class="string">rbac.authorization.k8s.io</span></span><br><span class="line"> <span class="attr">kind:</span> <span class="string">ClusterRole</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"><span class="attr">subjects:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">kind:</span> <span class="string">ServiceAccount</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">k8s-auth</span></span><br></pre></td></tr></table></figure>
<p>Now it’s time to the last part! we will deploy the agent itself! The agent need to know some information so as expected there is some environement variable!</p>
<ul>
<li><code>CLUSTER_NAME</code> : is the same name that you put it inside the authentication server</li>
<li><code>TOKEN</code> : The generated token from the authentication server</li>
<li><code>SERVER</code> : The authentication server itself</li>
<li><code>API_SERVER</code> : This is contains the public hostname for the API SERVER. The agent can detect it correctly when you have a cluster inside Network and the cluster is not exposed in the internet</li>
</ul>
<blockquote>
<p>I used kubeadm clusters in provisionning clusters. I didn’t find a way to find the public hostname! So you need to indicate the api server until it will be fixed!</p>
</blockquote>
<figure class="highlight yaml"><figcaption><span>deploy</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">apiVersion:</span> <span class="string">apps/v1</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Deployment</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">k8s-auth</span></span><br><span class="line"><span class="attr">spec:</span></span><br><span class="line"> <span class="attr">replicas:</span> <span class="number">1</span></span><br><span class="line"> <span class="attr">selector:</span></span><br><span class="line"> <span class="attr">matchLabels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">strategy:</span> &#123;&#125;</span><br><span class="line"> <span class="attr">template:</span></span><br><span class="line"> <span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">creationTimestamp:</span> <span class="literal">null</span></span><br><span class="line"> <span class="attr">labels:</span></span><br><span class="line"> <span class="attr">app:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">spec:</span></span><br><span class="line"> <span class="attr">serviceAccountName:</span> <span class="string">k8s-auth</span></span><br><span class="line"> <span class="attr">containers:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">image:</span> <span class="string">mohamedrafraf/k8s-auth-kube</span> </span><br><span class="line"> <span class="attr">name:</span> <span class="string">k8s-auth-kube</span></span><br><span class="line"> <span class="attr">env:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">CLUSTER_NAME</span></span><br><span class="line"> <span class="attr">value:</span> <span class="string">ctf-cluster</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">TOKEN</span></span><br><span class="line"> <span class="attr">value:</span> <span class="string">&quot;Z8taw1yFw4lsq7cgSvmZ&quot;</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">SERVER</span></span><br><span class="line"> <span class="attr">value:</span> <span class="string">&quot;https://auth.4n6nk8s.tech&quot;</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">API_SERVER</span></span><br><span class="line"> <span class="attr">value:</span> <span class="string">https://172.190.91.84:6443</span></span><br><span class="line"> <span class="attr">resources:</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="attr">status:</span> &#123;&#125;</span><br></pre></td></tr></table></figure>
<p>After deploying the agent. you can check the clusters with the cli again and you’ll find everything is ok!<br>
<img data-src="https://imgur.com/MqHeeY1.png" alt=""></p>
<p>The cluster is on Active status and the api server is not empty now! You can repeat this operation with many clusters and this is how multi-clusters can work together!</p>
<h2 id="create-users-and-groups"><a class="markdownIt-Anchor" href="#create-users-and-groups">#</a> Create Users and Groups</h2>
<p>The cluster is now ready for authentication and has been verified to be functioning without any issues. The connection between the cluster and authentication has been established. Now, let’s proceed to creating groups and users.</p>
<p>Let’s see what <code>k8s-auth create</code> can do for us!</p>
<p><img data-src="2023-04-29-15-56-38.png" alt=""></p>
<p>Great news! With the <code>k8s-auth create</code> command, you can easily create groups and users for your authenticated clusters. To create a group, simply specify the cluster and provide a YAML manifest file containing the roles for that group. For creating a user, you can either assign them to an existing group or provide a YAML manifest file for the user’s roles if they do not belong to any group.</p>
<p>Let’s define the role for our group that we will create!</p>
<figure class="highlight yaml"><figcaption><span>group rule</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">dev</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">pod-and-secret</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;&quot;</span>]</span><br><span class="line"> <span class="attr">resources:</span> [<span class="string">&quot;pods&quot;</span>,<span class="string">&quot;secrets&quot;</span>]</span><br><span class="line"> <span class="attr">verbs:</span> [<span class="string">&quot;list&quot;</span>,<span class="string">&quot;create&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">kind:</span> <span class="string">Role</span></span><br><span class="line"><span class="attr">apiVersion:</span> <span class="string">rbac.authorization.k8s.io/v1</span></span><br><span class="line"><span class="attr">metadata:</span></span><br><span class="line"> <span class="attr">namespace:</span> <span class="string">prod</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">pod-list</span></span><br><span class="line"><span class="attr">rules:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">apiGroups:</span> [<span class="string">&quot;&quot;</span>]</span><br><span class="line"> <span class="attr">resources:</span> [<span class="string">&quot;pods&quot;</span>]</span><br><span class="line"> <span class="attr">verbs:</span> [<span class="string">&quot;list&quot;</span>]</span><br></pre></td></tr></table></figure>
<p>The group we’re about to create will be granted permission to create and list pods and secrets in the “dev” namespace, while they will only be able to list pods in the “prod” namespace.</p>
<blockquote>
<p>Any user will be belong to this group will have these permissions! You don’t have to repeat the same manifest for each user!. This is why groups exists!</p>
</blockquote>
<p>This command will create the group for you</p>
<figure class="highlight bash"><figcaption><span>command</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">k8s-auth create group &lt;name&gt; --cluster=&lt;cluster&gt; --file=&lt;rbac_file&gt;</span><br></pre></td></tr></table></figure>
<p><img data-src="https://imgur.com/g5YBB8u.png" alt=""></p>
<p>As you can see here! The group is create successfully and you can see his permission when you forget it using <code>k8s-auth get permission</code> command!</p>
<p>You can discover what you can do with <code>k8s-auth get</code> command!! You can a list users too!</p>
<p><img data-src="https://imgur.com/MOC7L1o.png" alt=""></p>
<p>Now let’s create a user that belong to this group! So we don’t need to specify any manifest file that define roles!</p>
<figure class="highlight bash"><figcaption><span>user</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">k8s-auth create user --name &lt;name&gt; --fullname &lt;value&gt; --mail &lt;mail&gt; --cluster &lt;cluster&gt; --group &lt;group&gt;</span><br></pre></td></tr></table></figure>
<p>In case that you want to create a user that don’t belongs to any group and have his own permission you can delete the <code>--group</code> and change it with <code>--file</code> and specify the yaml file that contains his roles!</p>
<blockquote>
<p>No need to worry about naming roles because there won’t be any overlapping between them. The agent takes care of creating roles and bindings in the background, and the names you specify in the manifest won’t be used directly.</p>
</blockquote>
<p><img data-src="https://imgur.com/n2S8BQM.png" alt=""></p>
<p>You can update the permission using the <code>k8s-auth update permisssion</code> command! This command can update groups and users permission</p>
<p>In case you change the permission for a user that belgons to a group. This user will leave that group because he will have his own permissions (different from the group one)</p>
<blockquote>
<p>You can’t delete a group if is not empty!</p>
</blockquote>
<blockquote>
<p>When User have an opened session with a cluster and use kubectl normally and you decide to delete that user the session will be closed and he can’t do anything!</p>
</blockquote>
<h2 id="authenticate-to-a-cluster"><a class="markdownIt-Anchor" href="#authenticate-to-a-cluster">#</a> Authenticate to a cluster</h2>
<p>As a regular user you need to login to the authentication server using <code>k8s-auth login</code> and you’ll receive a link as the admin login process!</p>
<p>Then you can list the clusters that you can authenticate with using <code>k8s-auth get clusters</code> and keep in your mind that you’ll never see the token of each cluster (Only admins can see tokens)</p>
<p>Once you decided which cluster you’ll authenticate! run the command <code>k8s-auth auth</code> with specifying the cluster name!</p>
<figure class="highlight bash"><figcaption><span>authenticate</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">k8s-auth auth cluster=ctf-cluster</span><br><span class="line"></span><br><span class="line">To use this cluster run this <span class="built_in">command</span>: <span class="built_in">export</span> KUBECONFIG=<span class="variable">$HOME</span>/.k8s-auth.config</span><br></pre></td></tr></table></figure>
<p>If you’re authorized, you’ll receive a message like that! What is happening?</p>
<p>Actually the k8s-auth CLI generate a kubeconfig file for you! run the command that the CLI suggest to you! BOOOM Start Kubectlying !!! xD</p>
<h2 id="conclusion"><a class="markdownIt-Anchor" href="#conclusion">#</a> Conclusion</h2>
<p>As highlighted in the blog post, the process of authentication has been simplified with just 3 simple commands - login, auth, and export KUBECONFIG. These commands enable users to easily open a session with any cluster they want, regardless of the number of clusters and different permissions required, using just a single set of credentials. Additionally, the administrator can easily set up agents in the clusters, and manage the permissions and the entire process centrally using a smooth command line interface.</p>
</content>
<updated>2023-04-28T10:29:37.000Z</updated>
</entry>
<entry>
<id>http://example.com/2023/03/23/Writeups/ncsc2023/</id>
<title>NCSC'2023 Writeup Challenges</title>
<link rel="alternate" href="http://example.com/2023/03/23/Writeups/ncsc2023/"/>
<content type="html"><p>The National Cyber Security Congress (NCSC) is a three-day event that brings together cyber security enthusiasts and experts. The event features a wide range of activities, including workshops, talks, conferences, and two exciting CTF competitions.</p>
<p><img data-src="https://imgur.com/LJslRYb.png" alt=""></p>
<p>As a technical team member, I had the chance to create challenges in Kubernetes, Digital Forensics, Misc, Hardware, and Game Hacking categories.</p>
<p>The NCSC CTF provided a unique opportunity for cyber security enthusiasts to demonstrate their problem-solving abilities, teamwork, and technical proficiency in a fun and competitive environment. Overall, the event was an exciting and rewarding experience for all involved.</p>
<p>In this blog, I will share some write-ups that players have requested!</p>
<h1 id="digital-forensics-mokni-seals"><a class="markdownIt-Anchor" href="#digital-forensics-mokni-seals">#</a> Digital Forensics : Mokni &amp; Seals</h1>
<p><img data-src="https://i.imgur.com/i231apB.png" alt=""></p>
<p>We got a zip file! I bet that file is a memory dump! So i tried to run the volatility imageinfo plugin but it takes a long time. So I tried to figure out if this file is Linux memory dump or not!</p>
<figure class="highlight bash"><figcaption><span>linux or win ?</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">raf@4n6nk8s: strings data.raw | grep <span class="string">&quot;Linux version&quot;</span> </span><br><span class="line">Linux version 5.8.0-43-generic (buildd@lcy01-amd64-018) (gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0, GNU ld (GNU Binutils <span class="keyword">for</span> Ubuntu) 2.34) 49~20.04.1-Ubuntu SMP Fri Feb 5 09:57:56 UTC 2021 (Ubuntu 5.8.0-43.49~20.04.1-generic 5.8.18)</span><br></pre></td></tr></table></figure>
<p>And yes it’s a Linux Memory dump! I guess its time to start finding/making a profile but let me check that is memory dump can be analyzed with a profile or not!</p>
<figure class="highlight bash"><figcaption><span>checking</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">strings data.raw | grep -i insmod </span><br><span class="line">sudo insmod ./lime-5.8.0-43-generic.ko path=../../Linux64.mem format=raw</span><br><span class="line">sudo insmod ./lime-5.8.0-43-generic.ko <span class="string">&quot;path=../../Linux64.mem format=raw&quot;</span></span><br><span class="line">sudo insmod ./lime-5.8.0-43-generic.ko <span class="string">&quot;path=../../Linux64.mem format=raw&quot;</span></span><br></pre></td></tr></table></figure>
<p>Oh! The format is ram! which means that even if we get the correct profile volatility can’t analyze this memory dump! Strings time! The author want us to solve this mem dump using strings !</p>
<p>Let’s try to figure out some command lines! Bash history! Let me show you this trick!</p>
<figure class="highlight bash"><figcaption><span>extract bash history</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">strings data.raw | grep -Ei <span class="string">&quot;@*:~\\$&quot;</span> </span><br><span class="line">raf-square@ubuntu:~$ vim /etc/containers/registries.conf</span><br><span class="line">raf-square@ubuntu:~$</span><br><span class="line">raf-square@ubuntu:~$ <span class="built_in">echo</span> <span class="string">&quot;This Is My Secret&quot;</span> &gt; secret.txt</span><br><span class="line">raf-square@ubuntu:~$</span><br><span class="line">raf-square@ubuntu:~$ podman login -u $(<span class="built_in">head</span> -n 2 secret.txt | <span class="built_in">tail</span> -n 1 | awk <span class="string">&#x27;&#123; print $4 &#125;&#x27;</span>) -p $(<span class="built_in">head</span> -n 3 secret.txt | <span class="built_in">tail</span> -n 1 | awk <span class="string">&#x27;&#123; print $4 &#125;&#x27;</span>)</span><br><span class="line">raf-square@ubuntu:~$ podman pull nginx</span><br><span class="line">^Craf-square@ubuntu:~$ <span class="built_in">cd</span> LiME/src/</span><br><span class="line">raf-square@ubuntu:~$ vim /etc/containers/registries.conf</span><br><span class="line">raf-square@ubuntu:~$</span><br><span class="line">raf-square@ubuntu:~$ vim /etc/containers/registries.conf</span><br><span class="line">raf-square@ubuntu:~$</span><br><span class="line">u:~$ podman login -u $(<span class="built_in">head</span> -n 2 secret.txt | <span class="built_in">tail</span> -n 1 | awk <span class="string">&#x27;&#123; print $4 &#125;&#x27;</span>) -p $(<span class="built_in">head</span> -n 3 secret.txt | <span class="built_in">tail</span> -n 1 | awk <span class="string">&#x27;&#123; print $4 &#125;&#x27;</span>)</span><br></pre></td></tr></table></figure>
<p>Mmmm nice! now at least we got some commands and we got the user-name and host-name !<br>
From these commands we can understand that the user edit <code>/etc/containers/registries.conf</code> , then create a <code>secret.txt</code> . Then logged in with podman using that secret.txt. But we don’t have any information about the content of the creds in these commands!.</p>
<p>We have 2 methods to figure out what’s happen and get the creds!</p>
<p>either running a strings and grepping on <code>CMDLINE=podman login</code> or grepping on <code>This Is My Secret</code> and check the lines before and after to see the content!</p>
<figure class="highlight bash"><figcaption><span>extract creds</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">strings data.raw | grep -Ei <span class="string">&quot;CMDLINE=podman login&quot;</span> </span><br><span class="line">_CMDLINE=podman login -u 2ecf92b1-83a8-4355-8cb7-8354f4677894 -p fwO8Q~XTlBmpYoG43J~OusANA_azV02ZS3PuzaXb</span><br></pre></td></tr></table></figure>
<p>OR</p>
<figure class="highlight bash"><figcaption><span>extract creds</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">strings data.raw | grep -Ei -C 2 <span class="string">&quot;This Is My Secret&quot;</span> </span><br><span class="line"> Documents LiME Music Public Templates</span><br><span class="line">Desktop Downloads Linux64.mem Pictures secret.txt Videos</span><br><span class="line">raf-square@ubuntu:~$ <span class="built_in">echo</span> <span class="string">&quot;This Is My Secret&quot;</span> &gt; secret.txt</span><br><span class="line">raf-square@ubuntu:~$</span><br><span class="line">fctt</span><br><span class="line">--</span><br><span class="line">application/octet-stream</span><br><span class="line">text/plain</span><br><span class="line">This Is My Secret</span><br><span class="line">Service principal ID: 2ecf92b1-83a8-4355-8cb7-8354f4677894</span><br><span class="line">Service principal password: fwO8Q~XTlBmpYoG43J~OusANA_azV02ZS3PuzaXb</span><br><span class="line">--</span><br></pre></td></tr></table></figure>
<p>So the creds are <code>2ecf92b1-83a8-4355-8cb7-8354f4677894:fwO8Q~XTlBmpYoG43J~OusANA_azV02ZS3PuzaXb</code></p>
<p>But I didn’t think this is a normal creds for <code>dockerhub</code> or any public famous container registry! Espacially he pulled a container named nginx! I bet that nginx is a customized one and its a trick!</p>
<p>Editing <code>/etc/containers/registries.conf</code> can confirm that change something! This configuration file used by the container runtime environment on Linux systems. This file specifies a list of container image registries that are trusted by the system and can be used to download container images.</p>
<p>So let’s discover how to get the registry! Pulling nginx means he pulled the latest tag or at least he tried that! So let’s grep on <code>nginx:latest</code></p>
<figure class="highlight bash"><figcaption><span>extract registry</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">strings data.raw | grep -Ei <span class="string">&quot;nginx:latest&quot;</span> </span><br><span class="line">Trying to pull qualsk8s.azurecr.io/nginx:latest...</span><br><span class="line">Trying to pull qualsk8s.azurecr.io/nginx:latest...</span><br><span class="line"><span class="string">&quot;, &quot;</span>qualsk8s.azurecr.io/nginx:latest<span class="string">&quot;) not found</span></span><br><span class="line"><span class="string">Trying to pull qualsk8s.azurecr.io/nginx:latest...</span></span><br><span class="line"><span class="string">Trying to pull qualsk8s.azurecr.io/nginx:latest...</span></span><br><span class="line"><span class="string">Trying to pull qualsk8s.azurecr.io/nginx:latest...</span></span><br></pre></td></tr></table></figure>
<p>Bingo! <code>qualsk8s.azurecr.io</code> is the container registry! If you are an Azure guy you can get that from the previous step! when we get this output!</p>
<figure class="highlight text"><figcaption><span>creds</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Service principal ID: 2ecf92b1-83a8-4355-8cb7-8354f4677894</span><br><span class="line">Service principal password: fwO8Q~XTlBmpYoG43J~OusANA_azV02ZS3PuzaXb</span><br></pre></td></tr></table></figure>
<p>Ok it’s time to login and pull that image and run it!</p>
<figure class="highlight bash"><figcaption><span>login and pull</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker login qualsk8s.azurecr.io -u 2ecf92b1-83a8-4355-8cb7-8354f4677894 -p fwO8Q~XTlBmpYoG43J~OusANA_azV02ZS3PuzaXb </span><br><span class="line"></span><br><span class="line">docker pull nginx</span><br></pre></td></tr></table></figure>
<p>After checking the image! I got that it’s a static web page so let’s run it!</p>
<figure class="highlight bash"><figcaption><span>run nginx</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --name chall -p 80:80 -d nginx </span><br></pre></td></tr></table></figure>
<p>After running this container we got this web-page and guess what!! There is a flag icon! Let’s check it !<br>
<img data-src="https://i.imgur.com/q3GSPiL.png" alt=""></p>
<p>This flag icon lead you to this link <code>https://pastebin.com/vjFtjMga</code> which is protected pastebin<br>
how to get that password now! Let’s check the docker history!</p>
<figure class="highlight bash"><figcaption><span>docker history</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">mohamed@RafSquare:~$ docker <span class="built_in">history</span> qualsk8s.azurecr.io/nginx</span><br><span class="line">IMAGE CREATED CREATED BY SIZE COMMENT</span><br><span class="line">093f65335d3a 13 days ago ENTRYPOINT [<span class="string">&quot;nginx&quot;</span> <span class="string">&quot;-g&quot;</span> <span class="string">&quot;daemon off;&quot;</span>] 0B buildkit.dockerfile.v0</span><br><span class="line">&lt;missing&gt; 13 days ago RUN /bin/sh -c <span class="built_in">chmod</span> +r -R . <span class="comment"># buildkit 563kB buildkit.dockerfile.v0</span></span><br><span class="line">&lt;missing&gt; 13 days ago RUN /bin/sh -c <span class="built_in">mv</span> password.txt .hidden.txt <span class="comment">#… 11B buildkit.dockerfile.v0</span></span><br><span class="line">&lt;missing&gt; 13 days ago COPY ./ ./ <span class="comment"># buildkit 563kB buildkit.dockerfile.v0</span></span><br><span class="line">&lt;missing&gt; 3 weeks ago RUN /bin/sh -c <span class="built_in">rm</span> -rf ./* <span class="comment"># buildkit 0B buildkit.dockerfile.v0</span></span><br><span class="line">&lt;missing&gt; 3 weeks ago WORKDIR /usr/share/nginx/html 0B buildkit.dockerfile.v0</span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="built_in">set</span> -x &amp;&amp; apkArch=<span class="string">&quot;<span class="subst">$(cat /etc… 29.2MB</span></span></span><br><span class="line"><span class="subst"><span class="string">&lt;missing&gt; 5 weeks ago /bin/sh -c #(nop)</span> ENV NJS_VERSION=0.7.9 0B</span></span><br><span class="line"><span class="string">&lt;missing&gt; 5 weeks ago /bin/sh -c #(nop) CMD [&quot;</span>nginx<span class="string">&quot; &quot;</span>-g<span class="string">&quot; &quot;</span>daemon… 0B</span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) STOPSIGNAL SIGQUIT 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) EXPOSE 80 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) ENTRYPOINT [&quot;/docker-entr… 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:e57eef017a414ca7… 4.62kB</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:abbcbf84dc17ee44… 1.27kB</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:5c18272734349488… 2.12kB</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) COPY file:7b307b62e82255f0… 1.62kB</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="built_in">set</span> -x &amp;&amp; addgroup -g 101 -S … 4.45MB</span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) ENV PKG_RELEASE=1 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) ENV NGINX_VERSION=1.23.3 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) LABEL maintainer=NGINX Do… 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) CMD [&quot;/bin/sh&quot;] 0B</span></span><br><span class="line">&lt;missing&gt; 5 weeks ago /bin/sh -c <span class="comment">#(nop) ADD file:40887ab7c06977737… 7.05MB</span></span><br></pre></td></tr></table></figure>
<p>And yes!! There is <code>.hidden.txt</code> that contain a password for sure ! let’s get that password!</p>
<figure class="highlight bash"><figcaption><span>docker exec</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">exec</span> -it 460fc5a977c5 <span class="built_in">cat</span> .hidden.txt</span><br><span class="line">vT56X19Qu3</span><br></pre></td></tr></table></figure>
<p>We got this pastebin !</p>
<p><img data-src="https://i.imgur.com/N4B9j4z.png" alt=""></p>
<p>This is will lead us to word sheet that contains a hex data!</p>
<p><img data-src="https://i.imgur.com/P0hrYhX.png" alt=""></p>
<p>The hex data seams introducing spaces and tabs! I don’t care let’s decode it and see what’s will be!<br>
I’ll try to convert it to a file using <code>xxd</code> and import that file to <span class="exturl" data-url="aHR0cDovL2Rjb2RlLmZy">dcode.fr</span></p>
<figure class="highlight bash"><figcaption><span>xxd</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xxd -r -p hex.txt &gt; result.txt</span><br></pre></td></tr></table></figure>
<p>Yeah it’s a file that contains a lot of spaces! Its whitespaces</p>
<p>Bingo! This is the flag <code>Securinets&#123;208e5976c9d654e47d73ef44cabc272d&#125;</code></p>
<h1 id="digital-forensics-recover-my-work"><a class="markdownIt-Anchor" href="#digital-forensics-recover-my-work">#</a> Digital Forensics: Recover my Work 😦</h1>
<p><img data-src="https://i.imgur.com/DWMzUMB.png" alt=""></p>
<p>We got a file named <code>memory.dmp</code> . It’s a memory dump for sure! Let’s run imageinfo plugin to get our profile!</p>
<figure class="highlight bash"><figcaption><span>profile</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">vol.py -f memory.dmp imageinfo</span><br><span class="line">Volatility Foundation Volatility Framework 2.6.1</span><br><span class="line">INFO : volatility.debug : Determining profile based on KDBG search...</span><br><span class="line">WARNING : volatility.debug : Alignment of WindowsCrashDumpSpace64 is too small, plugins will be extremely slow</span><br><span class="line">WARNING : volatility.debug : Alignment of WindowsCrashDumpSpace64 is too small, plugins will be extremely slow</span><br><span class="line">WARNING : volatility.debug : Alignment of WindowsCrashDumpSpace64 is too small, plugins will be extremely slow</span><br><span class="line">WARNING : volatility.debug : Alignment of WindowsCrashDumpSpace64 is too small, plugins will be extremely slow</span><br></pre></td></tr></table></figure>
<p>But sadly we got this type of outpût! I bet that the suggested profile (in case it exists) will be wrong! Let’s know the exact profile with my own way! Let’s run strings the file and grep “service pack”</p>
<figure class="highlight text"><figcaption><span>Extract info</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Windows 7 Professional, 64-bit Service Pack 1 (Build 7601)</span><br></pre></td></tr></table></figure>
<p>Cool, This build and service pack is supported by <code>Win7SP1x64</code> ! I guess that imageinfo plugin got problem because the iso is customizated !</p>
<p>Let’s start checking our memory dump! First thing should be checked is the running processes! I’ll use pstree for that thing!</p>
<p><img data-src="https://i.imgur.com/1xA56pZ.png" alt=""></p>
<p>MMMM intersting! Found chrome, firefox, outlook and RDP opened! what a trip! After digging on chrome history and firefox, I found rabbit holes and some links to wordlists! Bad Author (Me).</p>
<p>Checking the consoles plugin too. Another rabbit hole! rabbit hole everywhere!</p>
<p>It’s time to check and figure out that outlook process!<br>
Outlook save the mails as pst or ost files! These files contains the mails data such as the message, attachements, sender/receiver information!</p>
<p>So let’s try to extract these files !</p>
<figure class="highlight bash"><figcaption><span>check files</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">vol.py -f memory.dmp --profile=Win7SP1x64 filescan | grep -i pst$</span><br><span class="line">0x000000007d81a490 5 5 RW-r-- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Outlook.pst</span><br><span class="line">0x000000007dd59340 5 5 RW-r-- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Work Progress.pst</span><br><span class="line">0x000000007dd73220 1 0 R--rw- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Work Progress.pst</span><br><span class="line">0x000000007e3f8b30 5 5 RW-r-- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Forgot the password.pst</span><br><span class="line">0x000000007e5297a0 1 0 R--rw- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Forgot the password.pst</span><br><span class="line">0x000000007e5eee60 30 0 RW-r-- \Device\HarddiskVolume2\Users\Raf_Square\AppData\Local\Microsoft\Outlook\Outlook.pst</span><br></pre></td></tr></table></figure>
<p>After extracting the files using <code>dumpfiles</code> plugin and making sure that the files are safe and not corrupted. I opened them using a pst online viewer!</p>
<p>The 1st mail i got it is from Adam! He send to me a zip file inside mega storage after our online meeting! I bet that zip is protected with that boring password</p>
<p><img data-src="https://i.imgur.com/9a0GCzz.png" alt=""></p>
<p>Ah my bad! The mega too is protected! We need the encryption key!</p>
<p><img data-src="https://i.imgur.com/hEG0dsu.png" alt=""></p>
<p>Let’s check the other mail! and as expected Adam forget to share the decryption key of the mega link to open the zip!</p>
<p><img data-src="https://i.imgur.com/wB3m3QV.png" alt=""></p>
<p>Bingo we got the zip! But it’s protected! Tried bruteforcing the password. But I failed!</p>
<p>Mmmm Let’s think a little bit! The author said that he used to use the same password! We need to find another usage of that password to open the zip and get the flag!</p>
<p>And It’s time to investigate the <code>mstsc.exe</code> or let’s just say the RDP! Remote Desktop?? Mmmm how to extract information from that thing?</p>
<p>Let’s talk brievly! Extracting the memory part used by RDP can save our life! I’ll try to recover what the user see when he used RDP!!!</p>
<p>Yes this possible dear reader, Don’t worry You’ll see how! Just make sure that you have <code>Gimp</code></p>
<p>Let’s now extract the memory part used by RDP process using the <code>memdump</code> plugin in volatility!</p>
<figure class="highlight bash"><figcaption><span>memdump</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vol.py -f memory.dmp --profile=Win7SP1x64 memdump -p 360 -D .</span><br><span class="line">Volatility Foundation Volatility Framework 2.6.1</span><br><span class="line">************************************************************************</span><br><span class="line">Writing mstsc.exe [ 360] to 360.dmp</span><br></pre></td></tr></table></figure>
<p>After getting that file! Let’s change its extension from <code>.dmp</code> to <code>.data</code> and open that file with gimp!</p>
<p><img data-src="https://i.imgur.com/k3uwJ0M.png" alt=""></p>
<p>Now it’s time for focusing! Yeah focusing will save your time! Many people can’t figure or recover images quickly! But believe me focusing on the noise will help you recover the data in a short time!</p>
<p>After 4 mins of playing with offset and width i got it!</p>
<p>Check the offset and the width!</p>
<p><img data-src="https://i.imgur.com/wI2SQK7.png" alt=""></p>
<p>Ohhh man! The user was opened <span class="exturl" data-url="aHR0cHM6Ly9jdGYuc2VjdXJpbmV0cy50bg==">https://ctf.securinets.tn</span> (check it for know more information about our CTFs events xD ) and tried to secure a zip file with that shitty password!</p>
<p>Finally This is the flag <code>Securinets&#123;R3M0tE_DeSKtOp_1s_FunNy_!_!&#125;</code></p>
<h1 id="hardware-liquid-display"><a class="markdownIt-Anchor" href="#hardware-liquid-display">#</a> Hardware: Liquid Display</h1>
<p><img data-src="https://i.imgur.com/YVrQJqG.png" alt=""></p>
<p>We got an image and a data file!<br>
<img data-src="https://i.imgur.com/5Enx08x.png" alt=""></p>
<p>The image contains an LCD 16x2 SPI connected to something called <code>WOKWI LOGIC</code></p>
<p>After some searching I got that this component is a logic analyzer. But wait!! What is that??</p>
<p>A logic analyzer is an electronic instrument that captures and displays multiple signals from a digital system or digital circuit. A logic analyzer may convert the captured data into timing diagrams, protocol decodes, state machine traces…</p>
<p><img data-src="https://imgur.com/WEzP4bO.png" alt=""></p>
<p>As my friend said this is the hardware wireshark xD</p>
<p>So we can understand now that this circuit capture the signals of each pin of the LCD and the data file is the capture file that contains the files!</p>
<p>So after some searching we get how to open that data file (which is a ASCII text file, I didn’t recommend to analyse it as text file).</p>
<p>You can check this <span class="exturl" data-url="aHR0cHM6Ly9kb2NzLndva3dpLmNvbS9ndWlkZXMvbG9naWMtYW5hbHl6ZXI=">link</span> to get more information about the logic analyzer!</p>
<p><span class="exturl" data-url="aHR0cHM6Ly9zaWdyb2sub3JnL3dpa2kvRG93bmxvYWRz">PulseView</span> is an open source Logic Analyzer GUI belongs to The sigrok project that aims at creating a portable, cross-platform, Free/Libre/Open-Source signal analysis software suite that supports various device types</p>
<p>I’ll use that Logic Analyzer GUI for this challenge!</p>
<p><img data-src="https://imgur.com/6HyLxUY.png" alt=""></p>
<p>Import the file data in this way! and let’s the show begin!</p>
<p><img data-src="https://imgur.com/MLrvWUk.png" alt=""></p>
<p>A lot of fun wait us right?! Don’t worry man! This is not that super hard! Just all what we need to do now is to simulate these signals manually! These signals are sent to the LCD and that LCD display something (It should be the flag!). So we need to understand how LCD works! I recommend to read the datasheet this thing!</p>
<p>I will not re-write what the datasheet said! so read it! You should understand how the LCD dispaly chars!</p>
<p><img data-src="https://imgur.com/vnZLXyb.png" alt=""></p>
<p>Also don’t forget to check the instruction table and understand how these instruction works!</p>
<p><img data-src="https://imgur.com/xsRciDM.png" alt=""></p>
<p>Let’s just take an example of the 1st instruction! The <code>Clear Display</code> . This instruction clear all the data and return the cursor to the original status! Ah yeah of course you must to understand that LCD have cursors, display modes …</p>
<p>After understand how this LCD works it’s time to check how characters are written on that LCD!</p>
<p><img data-src="https://imgur.com/5JQEtHj.png" alt=""></p>
<p>This table will help us to convert the signals to chars and recover our flag!</p>
<p>After reading the datasheet. You will understand that the D0 (that correspond to RS pin) can help you to understand when the display device clear the chars and reset the cursor or write something on the screen!</p>
<p><img data-src="https://imgur.com/QTfwCZC.png" alt=""></p>
<p>If you take a closer look you’ll get it! The guy who write the program write something and clear it then write another thing then delete it and so on!<br>
<img data-src="https://imgur.com/GSgaCKF.png" alt=""></p>
<p>So now it’s time to check the write blocks and check what that guy try to do! After reversing all the block i got the flag! It’s on the last block! Let me show you how I recover that data!</p>
<p><img data-src="https://imgur.com/HZcwRyX.png" alt=""></p>
<p>Using the characters table you can recover the flag! Mapping the signal and the Big table lead you to the flag!</p>
<p>And This is will be our flag! <code>Securinets&#123;LcD_1s_H4rD_!:(&#125;</code></p>
<h1 id="game-hacking-platformer"><a class="markdownIt-Anchor" href="#game-hacking-platformer">#</a> Game Hacking: Platformer:</h1>
<p><img data-src="https://imgur.com/OAyXmNQ.png" alt=""></p>
<p>In this challenge we have a game made by unity! It’s 2D platformer game where the player can jump and run in the map! But where is the flag??<br>
<img data-src="https://imgur.com/oIzwhG8.png" alt=""></p>
<p>Mmmmm my sixth sense told me that the flag is hidden somewhere in the map and the player can’t reach it! Hack Time!!!</p>
<p>Let’s change the player ability and let him can move in any place we want it. By disabling the collision and physics mechanism! Good bye gravitiy,Rigidbody,collisions!</p>
<p>To do this let’s open <code>Assembly-CSharp.dll</code> located in <code>Platformer_Data/Managed</code> folder.</p>
<p>Wow! This is the player controller code! that allow the player to move and the animation to be played and responsable for jumping and detect ground detection to deny player to jump many times on the air!</p>
<p><img data-src="https://imgur.com/eD0vAq0.png" alt=""></p>
<p>Boring mechanism!! Let me change this shitty code by mine! I’ll let the player move to any point he want!</p>
<p><img data-src="https://imgur.com/DZqPB6p.png" alt=""><br>
You can copy that code</p>
<figure class="highlight csharp"><figcaption><span>change mechanism</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">Start</span>()</span></span><br><span class="line">&#123;</span><br><span class="line"> <span class="keyword">this</span>.rb = <span class="keyword">base</span>.GetComponent&lt;Rigidbody2D&gt;();</span><br><span class="line"> <span class="keyword">this</span>.rb.isKinematic = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">this</span>.anim = <span class="keyword">base</span>.GetComponent&lt;Animator&gt;();</span><br><span class="line"> <span class="keyword">this</span>.mySpriteRenderer = <span class="keyword">base</span>.GetComponent&lt;SpriteRenderer&gt;();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Token: 0x06000005 RID: 5</span></span><br><span class="line"><span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">FixedUpdate</span>()</span></span><br><span class="line">&#123;</span><br><span class="line"> <span class="built_in">float</span> axisRaw = Input.GetAxisRaw(<span class="string">&quot;Horizontal&quot;</span>);</span><br><span class="line"> <span class="built_in">float</span> verticalInput = Input.GetAxisRaw(<span class="string">&quot;Vertical&quot;</span>);</span><br><span class="line"> Vector3 movement = <span class="keyword">new</span> Vector3(axisRaw, verticalInput, <span class="number">0f</span>).normalized * <span class="number">10f</span> * Time.deltaTime;</span><br><span class="line"> <span class="keyword">base</span>.transform.Translate(movement);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>After applying the changes our player can now go to any place we want! But i didn’t find the flag! Oh god! This is what i found!<br>
<img data-src="https://imgur.com/6PRgDFo.png" alt=""></p>
<p>I checked all the map and sadly nothing interesting 😦</p>
<p>Let’s check the files again! Maybe we will find something!</p>
<p><img data-src="https://imgur.com/MZ9tbCH.png" alt=""></p>
<p>Oh man look here! I found that there is levels on this game! Let me back to the decompiled code!</p>
<p><img data-src="https://imgur.com/yM0C7nL.png" alt=""></p>
<p>Oh no! The game is opened on the 2nd level! Let’s change this room to “Level1” and Play again! And yes It’s a new Level</p>
<p><img data-src="https://imgur.com/me4efrx.png" alt=""></p>
<p>After moving right and left, I found the flag!</p>
<p><img data-src="https://imgur.com/gj4wGE9.png" alt=""></p>
<p>And Yes We did it! Just move right and left and collect the letters ! and you’ll get this one ! Wrap it in Securinets{}<br>
<img data-src="https://imgur.com/cpA2O6c.png" alt=""></p>
<p>Flag: <code>Securinets&#123;Gam1ng_AnD_L0VE&#125;</code></p>
<h1 id="misc-full-difference"><a class="markdownIt-Anchor" href="#misc-full-difference">#</a> Misc: Full Difference</h1>
<p><img data-src="https://imgur.com/dROW4SQ.png" alt=""></p>
<p>Full Difference, The difference will make a difference! What is that thing ?? we got 2 images with different type but same picture!<br>
<img data-src="https://imgur.com/dr87PxX.png" alt=""></p>
<p>Thinking a little bit can we understand what the author means! Full difference! It means that the pixels should be different a full difference! which means the Red,Green and Blue channels should be differents!</p>
<p>“Will make a difference!” After extracting the different pixels we should calculate the difference between each channels ?? Mmmmm makes sense!</p>
<figure class="highlight python"><figcaption><span>solver</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="keyword">import</span> string </span><br><span class="line">im1=Image.<span class="built_in">open</span>(<span class="string">&quot;tobi.jpg&quot;</span>)</span><br><span class="line">im2=Image.<span class="built_in">open</span>(<span class="string">&quot;tobi.png&quot;</span>)</span><br><span class="line">pix2=im2.load()</span><br><span class="line">pix1=im1.load()</span><br><span class="line">width,height=im1.size</span><br><span class="line">result=<span class="string">&quot;&quot;</span></span><br><span class="line">data=[]</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>,width):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>,height):</span><br><span class="line"> <span class="keyword">if</span> pix1[i,j] != pix2[i,j] <span class="keyword">and</span> pix1[i,j][<span class="number">0</span>] != pix2[i,j][<span class="number">0</span>] <span class="keyword">and</span> pix1[i,j][<span class="number">1</span>] != pix2[i,j][<span class="number">1</span>] <span class="keyword">and</span> pix1[i,j][<span class="number">2</span>] != pix2[i,j][<span class="number">2</span>]:</span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">0</span>,<span class="number">3</span>):</span><br><span class="line"> data.append(<span class="built_in">chr</span>(<span class="built_in">abs</span>(pix1[i,j][k] - pix2[i,j][k])))</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> char <span class="keyword">in</span> data:</span><br><span class="line"> <span class="keyword">if</span> char <span class="keyword">in</span> string.ascii_letters + string.digits + string.punctuation:</span><br><span class="line"> result+=char</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line"><span class="built_in">print</span>(result)</span><br></pre></td></tr></table></figure>
<p>So the logic behind that code is to extract the pixels that have a full difference then calculate the difference between them. After that we convert the numbers to chars (should be printable!)</p>
<p>This expression will give us the different pixels</p>
<figure class="highlight python"><figcaption><span>exp</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pix1[i,j] != pix2[i,j] <span class="keyword">and</span> pix1[i,j][<span class="number">0</span>] != pix2[i,j][<span class="number">0</span>] <span class="keyword">and</span> pix1[i,j][<span class="number">1</span>] != pix2[i,j][<span class="number">1</span>] <span class="keyword">and</span> pix1[i,j][<span class="number">2</span>] != pix2[i,j][<span class="number">2</span>]</span><br></pre></td></tr></table></figure>
<p>In addition this expression collect the result of calculation the diff between the 2 pixels of each image!</p>
<figure class="highlight python"><figcaption><span>diff</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">data.append(<span class="built_in">chr</span>(<span class="built_in">abs</span>(pix1[i,j][k] - pix2[i,j][k])))</span><br></pre></td></tr></table></figure>
<p>Then it’s time to convert it to printable data!</p>
<figure class="highlight python"><figcaption><span>print</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> char <span class="keyword">in</span> data:</span><br><span class="line"> <span class="keyword">if</span> char <span class="keyword">in</span> string.ascii_letters + string.digits + string.punctuation:</span><br><span class="line"> result+=char</span><br></pre></td></tr></table></figure>
<p>Running this code will give you this base64 encoding! <code>dGgxNV8xNV9zaDB1TGRfYjNfaDRyRA==</code></p>
<p>Bingo we got this statement! <code>th15_15_sh0uLd_b3_h4rD</code> . Let’s wrap it in Securinets! Oh nooo! Didn’t work. I guess the challenge is not finished!</p>
<p>We have 2 images! PNG and JPEG. Mmmm Let’s try to do some steganography on these images using the password/key that we got previously.</p>
<p>The 1st idea in my mind is to try steghide! Nothing else! Let’s try it</p>
<p><img data-src="https://imgur.com/VLbBAGf.png" alt=""></p>
<p>YEEES MAAN! We got a flag.zip file! But wait it’s protected again 😦. I tried to brute force that thing using rockyou but failed !!! What is going on here! The flag is inside that zip what we should to do now!</p>
<p>Let’s extract more information about the zip using <code>7z</code> utility</p>
<figure class="highlight bash"><figcaption><span>7z</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">7z l -slt flag.zip</span><br><span class="line"></span><br><span class="line">Path = flag.txt</span><br><span class="line">Folder = -</span><br><span class="line">Size = 40</span><br><span class="line">Packed Size = 52</span><br><span class="line">Modified = 2022-11-18 21:17:23</span><br><span class="line">Created =</span><br><span class="line">Accessed =</span><br><span class="line">Attributes = A</span><br><span class="line">Encrypted = +</span><br><span class="line">Comment =</span><br><span class="line">CRC = 4F639BBA</span><br><span class="line">Method = ZipCrypto Store</span><br><span class="line">Host OS = FAT</span><br><span class="line">Version = 20</span><br><span class="line">Volume Index = 0</span><br></pre></td></tr></table></figure>
<p>Nice the flag.txt size is 40 bytes! So our flag is 40-chars strings! The encryption method is <code>ZipCrypto</code> !</p>
<p>Bingoo! This method is vulnerable! Let’s check how can we get our flag!</p>
<p>After some searching we found a repository talking about “Crack legacy zip encryption with Biham and Kocher’s known plaintext attack.”</p>
<p>I recommend to check this <span class="exturl" data-url="aHR0cHM6Ly9naXRodWIuY29tL2tpbWNpODYvYmtjcmFjaw==">repo</span> and understand how this attack can be manipulated and how to install that tool!</p>
<p>Let’s now start downloading the tool</p>
<figure class="highlight bash"><figcaption><span>wget</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget https://github.com/kimci86/bkcrack/releases/download/v1.5.0/bkcrack-1.5.0-Linux.tar.gz</span><br></pre></td></tr></table></figure>
<p>We need to recover the internal key that will allow us to extract the file!</p>
<p>The attack requires at least 12 bytes of known plaintext. At least 8 of them must be contiguous. The larger the contiguous known plaintext, the faster the attack. In our case we have a flag.txt that contains <code>Securinets&#123;*&#125;</code></p>
<p>In our case we know 11 chars ( <code>Securinets&#123;</code> ) and the last char <code>&#125;</code></p>
<p>Let’s recover our key now!</p>
<figure class="highlight bash"><figcaption><span>prepare our data</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> -n <span class="string">&quot;Securinets&#123;&quot;</span> &gt; plaintext.txt</span><br><span class="line"><span class="built_in">echo</span> -n <span class="string">&quot;&#125;&quot;</span> | xxd <span class="comment"># 7d is the result</span></span><br></pre></td></tr></table></figure>
<p>The attack requires the plain text content and in case there is another seperate bytes we can specify the offset and the byte value in hex</p>
<p>Now time to work !</p>
<figure class="highlight bash"><figcaption><span>get the key</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">bkcrack-1.5.0-Linux/bkcrack -C flag.zip -c flag.txt -p plaintext.txt -x 39 7d </span><br><span class="line"></span><br><span class="line">bkcrack 1.5.0 - 2022-07-07</span><br><span class="line">[16:21:19] Z reduction using 4 bytes of known plaintext</span><br><span class="line">100.0 % (4 / 4)</span><br><span class="line">[16:21:19] Attack on 1405963 Z values at index 6</span><br><span class="line">Keys: 184a904b d4557686 2222c7f2</span><br><span class="line">9.2 % (129555 / 1405963)</span><br><span class="line">[16:24:40] Keys</span><br><span class="line">184a904b d4557686 2222c7f2</span><br></pre></td></tr></table></figure>
<p>We got the keys ! <code>184a904b d4557686 2222c7f2</code> . Now we can decipher/decrypt the file! which means extract it from the zip!</p>
<figure class="highlight bash"><figcaption><span>extract</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">bkcrack-1.5.0-Linux/bkcrack -C flag.zip -c flag.txt -k 184a904b d4557686 2222c7f2 -d my_flag.txt </span><br><span class="line"></span><br><span class="line">bkcrack 1.5.0 - 2022-07-07</span><br><span class="line">[16:32:25] Writing deciphered data my_flag.txt (maybe compressed)</span><br><span class="line">Wrote deciphered data.</span><br></pre></td></tr></table></figure>
<p>Bingo We got the flag!!! How 2 images can hide data like that!</p>
<p><img data-src="https://imgur.com/O8uXhZV.png" alt=""></p>
<p>Flag: <code>Securinets&#123;Z1p_CRyPt0_&amp;_5t3gH1d3_1s_BAd&#125;</code></p>
<h1 id="kubernetes-challenge-serie"><a class="markdownIt-Anchor" href="#kubernetes-challenge-serie">#</a> Kubernetes challenge serie</h1>
<p>NCSC’2023 consider the 1st tunisian CTF competition that have a whole Kubernetes Category! These are oriented for beginners/Intermediate users to consodilate their basic knowledge in Kubernetes!</p>
<p><img data-src="https://imgur.com/U69KQtM.png" alt=""></p>
<h2 id="kubernetes-secrets"><a class="markdownIt-Anchor" href="#kubernetes-secrets">#</a> Kubernetes: Secrets:</h2>
<p>In this challenge we get an IP and the author told us that he have a secret in the cluster!<br>
<img data-src="https://imgur.com/PCmO273.png" alt=""></p>
<p>Visiting the IP on the browser will lead us to the author page! This is not our objective!</p>
<p>We need to access to the API-Server. Let’s check the default port 6443</p>
<figure class="highlight bash"><figcaption><span>curl</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -sk https://20.169.73.19:6443/version</span><br></pre></td></tr></table></figure>
<p>And this request is failed! Mmmm The author change the default api-server?? Nmap time! Let’s scan that IP!</p>
<p>After checking the IP we get that port opened 7443!</p>
<p><img data-src="https://imgur.com/GunNYhA.png" alt=""></p>
<p>And Yes! We got a response! It’s KUBERNETES TIME!!</p>
<p>Let’s check what permission we have as an anonymous users! To be honest I’ll try to check if I can got namespaces Or secrets first! Let me check that!</p>
<figure class="highlight bash"><figcaption><span>curl-namespaces</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -sk https://20.169.73.19:7443/api/v1/namespaces | grep <span class="string">&#x27;&quot;name&quot;: &quot;&#x27;</span></span><br></pre></td></tr></table></figure>
<p>And we got a list of namespaces! This is cool! We have <code>task1,task2,task3 and task4</code> namespaces! I bet that each challenge is in single namespace! This is Great!<br>
<img data-src="https://imgur.com/vZrtZLd.png" alt=""></p>
<p>Hummm We need secrets and this is the 1st challenge! So We are sure that we can list the secrets in the <code>task1</code> namespace!</p>
<figure class="highlight bash"><figcaption><span>curl-namespaces</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -sk https://20.169.73.19:7443/api/v1/namespaces/task1/secrets</span><br></pre></td></tr></table></figure>
<p>Bingo We got the Secrets List! We are on the right way!<br>
<img data-src="https://imgur.com/0PFJsCI.png" alt=""></p>
<p>Flag : <code>Securinets&#123;S3crEts_Ar3_S0_CriT1c4LL&#125;</code></p>
<blockquote>
<p>We got a message! We must check it for sure!</p>
</blockquote>
<p>Look what we got here !</p>
<figure class="highlight text"><figcaption><span>check</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Look here YOU will need this one believe me!!!</span><br><span class="line"> eyJhbGciOiJSUzI1NiIsImtpZCI6IkZwcWlIMGR2QlJ5Q0ZwTHV5a0JFQnlEcVI5UWZHLUdsY2NLQkkyMGlZWU0ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ0YXNrMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJwb2QtbGlzdGVyLXRva2VuLXpoNHM2Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InBvZC1saXN0ZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIyZjc2YjA3ZS0wY2NjLTRhMDQtYWUxZi1jNGJhMzIxZjYzZmQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6dGFzazI6cG9kLWxpc3RlciJ9.cewI8cdU8u-MxhLW5enn9bqj2DnD6Kn6iJZD2Y70uSIN-Pdq4VGrCNN0oB0edWaNZd_2o3NCVfE1GY9JRIjQeMuV_Uk5-tEQ62TS1b2hpHPoq8FtRFDyji26LyTR2XGU7gSYdQV6G8axOU3z8_RRWQarN5VfSgDp-WmwizjwWJLMhENGgvWBxOKjHrF0tDCEmshH1g841NB4XtzeiXRxEC1AN9kNv-7SZvYWasHbPuva-fsGBp-AvhUUTStcCVahZ8VElJ51q3VxKBTXX-DoDWfsVD5rOcCse0yj4jxgN3GIqjIaAcjBiPI2XmhQv-tMMbYpj7gfAxrzhdh77UfaBg</span><br></pre></td></tr></table></figure>
<h2 id="kubernetes-pody"><a class="markdownIt-Anchor" href="#kubernetes-pody">#</a> Kubernetes: Pody:</h2>
<p>After getting the secrets we can move to the next challenge that named <code>Pody</code></p>
<p><img data-src="https://imgur.com/hZQya2W.png" alt=""></p>
<p>In this challenge the author told us that the container is inside a pod! So how can we get inside that pod? Thinking a little bit we didn’t get any solution expect opening a shell session inside the pod!</p>
<p>Kubectl Are you there?? Yes! It’s Kubectl time! I love to work with kubectl I will not waste my time curling endpoints 😃 So I’ll make my kubeconfig file for this challenge!</p>
<p>When I checked the secrets in the previous challenge I got the certificate authority Certifcate. And of course don’t forget the token that we got!</p>
<blockquote>
<p>This token is used for authentication and authorization in kubernetes. This authorization is occur on the api-server level not the etcd!</p>
</blockquote>
<p>Let’s make our kubeconfig! But wait! In case you don’t have kubectl, it’s time to install it! You can follow this <span class="exturl" data-url="aHR0cHM6Ly9rdWJlcm5ldGVzLmlvL2RvY3MvdGFza3MvdG9vbHMvaW5zdGFsbC1rdWJlY3RsLWxpbnV4Lw==">guide</span> to install it</p>