<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>미친해커</title>
    <link>https://crazyhacker.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 12:47:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>미친해커</managingEditor>
    <image>
      <title>미친해커</title>
      <url>https://tistory1.daumcdn.net/tistory/4783575/attach/2d477b4657a448e59972662ed438988a</url>
      <link>https://crazyhacker.tistory.com</link>
    </image>
    <item>
      <title>[Android] Run Applications as Root for Android</title>
      <link>https://crazyhacker.tistory.com/141</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;글을 시작하기 전 양해 말씀드립니다. 저는 안드로이드, 리눅스 운영체제에 대해 자세히 알지 못해 인터넷 검색과 연구하면서 알아낸 결과로 추측하여 글을 작성했습니다. 잘못된 정보가 있다면 댓글 부탁드립니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How do you typcially run an application as root?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Root 권한으로 애플리케이션을 실행하는 방법은 안드로이드 5.0을 기준으로 이전과 이후로 나뉘게 된다.&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;또한 현재 안드로이드 운영체제는 기본적으로 시스템 앱(System Application)이 아닌 일반 앱(Application)은 Root 권한으로 실행할 수 없다고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Before Android 5.0&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 5.0 이전에는 &lt;code&gt;AndroidManifest.xml&lt;/code&gt;에 &lt;code&gt;android.permission.ACCESS_SUPERUSER&lt;/code&gt; 권한을 선언하면 가능하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;After Android 5.0&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 5.0 이후에는 일반 앱을 Root 권한으로 실행하는 것은 불가능하다. &lt;code&gt;Android 5.0 Lolipop&lt;/code&gt;에서부터 &lt;code&gt;android.permission.ACCESS_SUPERUSER&lt;/code&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;figure id=&quot;og_1713401319108&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;How-To SU&quot; data-og-description=&quot;0. Table of Contents 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Table of Contents 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Introduction 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Code: libsuperuser 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;How to call su 3.1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Common pitfalls 3.2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Making the call 3.3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Checking for su availability 3.4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Checking for &quot; data-og-host=&quot;su.chainfire.eu&quot; data-og-source-url=&quot;http://su.chainfire.eu/#updates-permission&quot; data-og-url=&quot;http://su.chainfire.eu/#updates-permission&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;http://su.chainfire.eu/#updates-permission&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://su.chainfire.eu/#updates-permission&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;How-To SU&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;0. Table of Contents 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Table of Contents 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Introduction 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Code: libsuperuser 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;How to call su 3.1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Common pitfalls 3.2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Making the call 3.3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Checking for su availability 3.4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Checking for&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;su.chainfire.eu&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How applications run on Android (B&lt;span style=&quot;background-color: #fdfdfd; text-align: start;&quot;&gt;ackground Knowledge)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 5.0 이후에서 애플리케이션을 Root 권한으로 실행시키는 것이 완전히 불가능한 것은 아니다.&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;Root 권한으로 애플리케이션을 실행하기 위해서는 먼저 안드로이드의 애플리케이션이 어떤 원리로 실행되는지 알아야 할 필요가 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What language is the application written?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 알고 있다시피 안드로이드 애플리케이션은 주로 Java(자바)로 작성되어 있다. 그렇기 때문에 리눅스인 안드로이드에서 네이티브 프로세스로 실행될 수 없다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Dalvik&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dalvik은 VM이며 DVM이라고도 불린다. Android 4.4(API 19)에서 처음 등장했으며 자바를 구동하는 JVM 대신 사용된다.&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;Android가 Java를 사용하면서 JVM을 사용하지 않고 DVM을 사용하는 이유는 라이선스와 메모리 효율성 등의 문제가 있다. JVM이나 DVM이나 모두 Java를 사용한 VM이기에 애플리케이션을 동작하는데 문제는 존재하지 않는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Zygote&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 말했 듯이 안드로이드 애플리케이션은 달빅(Dalvik) 가상 머신에서 동작한다. 각 안드로이드 애플리케이션은 독립적으로 가상 머신 위에서 동작할 것이며 실행될 때마다 가상 머신을 초기화한다. 즉, 안드로이드 애플리케이션이 실행될 때마다 많은 과정이 필요하고 이로 인해 많은 시간이 소요 돼 애플리케이션의 실행을 지연시킨다.&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;안드로이드에는 Zygote(자이고트)라는 이름의 프로세스가 존재하는데 Zygote는 애플리케이션이 실행되기 전에 가상 머신의 코드 및 메모리 정보를 공유함으로써 애플리케이션이 실행되는 시간을 단축시킬 수 있다.&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;Zygote는 가상 머신의 코드 및 메모리뿐만 아니라 안드로이드 프레임워크에서 동작하는 애플리케이션이 사용할 클래스와 자원을 미리 로딩해 해당 자원에 대한 연결 정보를 구성한다. 이 덕분에 새로 실행되는 애플리케이션은 필요한 자원들에 대한 연걸 정보를 매번 구성하지 않아도 되기 때문에 빠르기 실행된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XvRpO/btsGL29tNt0/xC2WGaf0QsBuiEqPd0ni7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XvRpO/btsGL29tNt0/xC2WGaf0QsBuiEqPd0ni7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XvRpO/btsGL29tNt0/xC2WGaf0QsBuiEqPd0ni7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXvRpO%2FbtsGL29tNt0%2FxC2WGaf0QsBuiEqPd0ni7k%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;1276&quot; height=&quot;524&quot; data-origin-width=&quot;1276&quot; data-origin-height=&quot;524&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Process creation(Application execution) via Zygote&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zygote는 안드로이드 애플리케이션이 실행될 때 필요한 달빅 가상 머신의 초기화와 자원들을 미리 로딩되어 있는데 어떻게 이 리소스를 사용해 애플리케이션을 실행시킬 수 있을까? 바로 &lt;code&gt;fork(clone)&lt;/code&gt; 시스템 콜이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1231&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2MqVO/btsGJLAend2/akhmrGpsfU7FNqqiODjeq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2MqVO/btsGJLAend2/akhmrGpsfU7FNqqiODjeq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2MqVO/btsGJLAend2/akhmrGpsfU7FNqqiODjeq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2MqVO%2FbtsGJLAend2%2FakhmrGpsfU7FNqqiODjeq1%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;1231&quot; height=&quot;503&quot; data-origin-width=&quot;1231&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fork 함수는 새로운 자식 프로세스를 생성하고 새로 생성된 프로세스는 부모 프로세스의 메모리 구성 정보 및 공유 라이브러리에 대한 링크 정보를 공유한 상태이다. 프로세스가 그대로 복제되는 셈이다. Zygote는 fork를 사용해 자신을 복제한 후 그 위에 안드로이드 애플리케이션을 로드함으로써 애플리케이션을 실행한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1763&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UbTO8/btsGKWbfN2K/Dk1K8HCB8uZs1rrQICpZkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UbTO8/btsGKWbfN2K/Dk1K8HCB8uZs1rrQICpZkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UbTO8/btsGKWbfN2K/Dk1K8HCB8uZs1rrQICpZkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUbTO8%2FbtsGKWbfN2K%2FDk1K8HCB8uZs1rrQICpZkK%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;1763&quot; height=&quot;847&quot; data-origin-width=&quot;1763&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What is app_process?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Zygote 또한 자바로 작성되어 있어 다른 네이티브 서비스나 데몬처럼 init 프로세스에서 바로 실행할 수 없다. 그렇기 때문에 Zygote는 app_process를 통해 Dalvik VM을 초기화한 후 &lt;code&gt;ZygoteInit&lt;/code&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;init 프로세스는 app_process와 더불어 다양한 데몬 프로세스를 실행시키는데 이는 &lt;code&gt;/init.zygote64_32.rc&lt;/code&gt; 파일에서 확인할 수 있다. (AArch64의 경우 x86과 x64 두 개의 zygote가 실행된다. 해당 글에서 zygote는 app_process64만을 의미한다)&lt;/p&gt;
&lt;pre id=&quot;code_1713471047633&quot; class=&quot;shell&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 정의에서 알 수 있듯이 app_process는 zygote의 &quot;진짜 이름&quot;으로 app_process가 init 프로세스의 의해 서비스 데몬으로 실행되어 &lt;code&gt;ZygoteInit 클래스&lt;/code&gt; 를 로딩해 Zygote를 실행한다.&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;code&gt;/system/bin/app_process&lt;/code&gt; 는 &lt;code&gt;/system/bin/app_process64&lt;/code&gt; 의 심볼릭 링크이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1681&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vN5Eg/btsGK2bhnYG/cmcNmPXKRHpRfFJyLHqyCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vN5Eg/btsGK2bhnYG/cmcNmPXKRHpRfFJyLHqyCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vN5Eg/btsGK2bhnYG/cmcNmPXKRHpRfFJyLHqyCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvN5Eg%2FbtsGK2bhnYG%2FcmcNmPXKRHpRfFJyLHqyCK%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;1681&quot; height=&quot;620&quot; data-origin-width=&quot;1681&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Guess the workflow of Zygote&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zygote가 안드로이드 애플리케이션을 실행시킨다는 사실을 우리는 알았을 때 바로 알 수 있는 한 가지 있다. 바로 Zygote는 init 프로세스의 의해 서비스 데몬으로 실행되기에 Root 권한으로 실행된다는 것이다. 그렇다면 Zygote의 자식 프로세스로 실행되는 안드로이드 애플리케이션도 &lt;span style=&quot;color: #ee2323;&quot;&gt;&quot;원래&quot;&lt;/span&gt;는 &lt;span style=&quot;color: #ee2323;&quot;&gt;Root 권한으로 실행되었던 적이 있다&lt;/span&gt;는 사실이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1819&quot; data-origin-height=&quot;499&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/APnMe/btsGTb6TKfK/L1hddyA70Q3JiFAF8Q6fmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/APnMe/btsGTb6TKfK/L1hddyA70Q3JiFAF8Q6fmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/APnMe/btsGTb6TKfK/L1hddyA70Q3JiFAF8Q6fmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAPnMe%2FbtsGTb6TKfK%2FL1hddyA70Q3JiFAF8Q6fmK%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;1819&quot; height=&quot;499&quot; data-origin-width=&quot;1819&quot; data-origin-height=&quot;499&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;com.termux&lt;/code&gt; 애플리케이션의 부모와 조부모인 &lt;code&gt;zygote&lt;/code&gt;와 &lt;code&gt;init&lt;/code&gt;는 &lt;code&gt;Root&lt;/code&gt;권한이지만 &lt;code&gt;com.termux&lt;/code&gt; 애플리케이션은 Root 권한이 아닌 &lt;span style=&quot;color: #ee2323;&quot;&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;위와 같은 사실을 통해 Zygote가 안드로이드 애플리케이션을 로드한 후 &lt;span style=&quot;color: #ee2323;&quot;&gt;자신의 권한을 낮춘 다음에 &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;안드로이드 애플리케이션(MainActivity)을 호출&lt;/span&gt;한다는 의미가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;Zygote source code anaysis&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Zygote 프로세스의 워크플로우를 추측했으니 이제 Zygote의 소스코드를 분석해보려고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(안드로이드 7.1.2 Release 39 기준)&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;중요하다고 생각되는 함수가 호출되는 윗 라인에 주석을 달아놓았고 주석에 1), 2) 와 같이 작성되어 있는 함수는 후에 서술할 안드로이드 애플리케이션을 Root 권한으로 실행하는데 영향을 끼치는 함수들로 아래에서 따로 부가적인 설명이 존재한다.&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;code&gt;ZygoteInit.main()&lt;/code&gt;&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;부터 안드로이드 애플리케이션 호출까지의 과정은 더보기를 눌러주세요&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;code&gt;ZygoteInit.main()&lt;/code&gt; 부터 안드로이드 애플리케이션의 호출까지의 과정이다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713879266086&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;core/java/com/android/internal/os/ZygoteInit.java - platform/frameworks/base - Git at Google&quot; data-og-description=&quot;* Copyright (C) 2007 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&quot; data-og-host=&quot;android.googlesource.com&quot; data-og-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#712&quot; data-og-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#712&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#712&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#712&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;core/java/com/android/internal/os/ZygoteInit.java - platform/frameworks/base - Git at Google&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* Copyright (C) 2007 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;android.googlesource.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Call Trace&lt;br /&gt;&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;
&lt;pre id=&quot;code_1713935808641&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#712
Line 712
*/
public static void main(String argv[]) {

    /* 중간 생략 */
    
    try {
    
        /* 중간 생략 */
        
        boolean startSystemServer = false;
        String socketName = &quot;zygote&quot;;
        String abiList = null;
        for (int i = 1; i &amp;lt; argv.length; i++) {
            if (&quot;start-system-server&quot;.equals(argv[i])) {
                // Zygote를 호출할 때 --start-system-server 플래그가 존재
                startSystemServer = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                socketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException(&quot;Unknown command line argument: &quot; + argv[i]);
            }
        }
        if (abiList == null) {
            throw new RuntimeException(&quot;No ABI list supplied.&quot;);
        }
        
        /*
        안드로이드 애플리케이션 실행을 위한 요청 수신을 받기 위한 소켓 등록
        UDS(Unix Domain Socket)을 사용하며 init.rc에서 app_process를 실행할 때 등록했던 소켓을 이용
        socket zygote stream 660 root system
        */
        registerZygoteSocket(socketName);
        
        /* 중간 생략 */
        
        /*
        Classes, Resources, OpenGL, Shared Libraries, Text Resources 등을 로드
        내부에서 다음 각 함수를 호출
        preloadClasses()
        preloadResources()
        preloadOpenGL()
        preloadSharedLibraries()
        preloadTextResources()
        */
        preload();
        
        /* 중간 생략 */
        
        /*
        UDS를 모니터링 하면서 안드로이드 애플리케이션 생성 요청을 처리하는 루프를 실행
        */
        runSelectLoop(abiList);
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, &quot;Zygote died with exception&quot;, ex);
        closeServerSocket();
        throw ex;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Call Trace&lt;/p&gt;
&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()&lt;/code&gt;
&lt;pre id=&quot;code_1713935228831&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteInit.java#825
Line 825
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    // 안드로이드 애플리케이션 실행 요청 소켓을 저장할 리스트
    ArrayList&amp;lt;FileDescriptor&amp;gt; fds = new ArrayList&amp;lt;FileDescriptor&amp;gt;();
    // 안드로이드 애플리케이션 실행 대기 리스트
    ArrayList&amp;lt;ZygoteConnection&amp;gt; peers = new ArrayList&amp;lt;ZygoteConnection&amp;gt;();
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);
    while (true) {
    
        /* 중간 생략 */
        
        for (int i = pollFds.length - 1; i &amp;gt;= 0; --i) {
            if ((pollFds[i].revents &amp;amp; POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                // 0번 index에서 이벤트 발생 -&amp;gt; 안드로이드 애플리케이션 실행 요청이 들어옴
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 안드로이드 애플리케이션 실행
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1713936257042&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;core/java/com/android/internal/os/ZygoteConnection.java - platform/frameworks/base - Git at Google&quot; data-og-description=&quot;* Copyright (C) 2007 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&quot; data-og-host=&quot;android.googlesource.com&quot; data-og-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteConnection.java#132&quot; data-og-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteConnection.java#132&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteConnection.java#132&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteConnection.java#132&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;core/java/com/android/internal/os/ZygoteConnection.java - platform/frameworks/base - Git at Google&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* Copyright (C) 2007 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;android.googlesource.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Call Trace&lt;br /&gt;&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[3] core/java/com/android/internal/os/ZygoteConnection.java - runOnce()&lt;/code&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1713936285643&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/ZygoteConnection.java#132
Line 132
*/
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    /* 중간 생략 */
    
    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;
    try {
    
        /* 중간 생략 */
        
        // 애플리케이션 실행을 위해 fork() 및 권한 등 설정
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (ErrnoException ex) {
        logAndPrintError(newStderr, &quot;Exception creating pipe&quot;, ex);
    } catch (IllegalArgumentException ex) {
        logAndPrintError(newStderr, &quot;Invalid zygote arguments&quot;, ex);
    } catch (ZygoteSecurityException ex) {
        logAndPrintError(newStderr,
                &quot;Zygote security policy prevents request: &quot;, ex);
    }
    
    /* 중간 생략 */
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1713946824895&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;core/java/com/android/internal/os/Zygote.java - platform/frameworks/base - Git at Google&quot; data-og-description=&quot;* Copyright (C) 2014 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&quot; data-og-host=&quot;android.googlesource.com&quot; data-og-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/Zygote.java#91&quot; data-og-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/Zygote.java#91&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/Zygote.java#91&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/Zygote.java#91&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;core/java/com/android/internal/os/Zygote.java - platform/frameworks/base - Git at Google&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* Copyright (C) 2014 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;android.googlesource.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Call Trace&lt;br /&gt;&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[3] core/java/com/android/internal/os/ZygoteConnection.java - runOnce()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[4] core/java/com/android/internal/os/Zygote.java - forkAndSpecialize()&lt;/code&gt;
&lt;pre id=&quot;code_1713946606581&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/java/com/android/internal/os/Zygote.java#91
Line 91
*/
// Forks a new VM instance. The current VM must have been started with the -Xzygote flag.
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
      int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
      String instructionSet, String appDataDir) {
    VM_HOOKS.preFork();
    
    /*
    C/C++ 코드로 작성된 네이티브 함수를 호출
    함수 안에서 인자의 있는 uid와 gid로 프로세스의 uid와 gid가 변경 됨
    */
    int pid = nativeForkAndSpecialize(
              uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
              instructionSet, appDataDir);
              
    // Enable tracing as soon as possible for the child process.
    if (pid == 0) {
        Trace.setTracingEnabled(true);
        // Note that this event ends at the end of handleChildProc,
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, &quot;PostFork&quot;);
    }
    VM_HOOKS.postForkCommon();
    return pid;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1713947302185&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;core/jni/com_android_internal_os_Zygote.cpp - platform/frameworks/base - Git at Google&quot; data-og-description=&quot;* Copyright (C) 2008 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&quot; data-og-host=&quot;android.googlesource.com&quot; data-og-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#652&quot; data-og-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#652&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#652&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#652&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;core/jni/com_android_internal_os_Zygote.cpp - platform/frameworks/base - Git at Google&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* Copyright (C) 2008 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;android.googlesource.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Call Trace&lt;br /&gt;&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[3] core/java/com/android/internal/os/ZygoteConnection.java - runOnce()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[4] core/java/com/android/internal/os/Zygote.java - forkAndSpecialize()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[5] core/jni/com_android_internal_os_Zygote.cpp - nativeForkAndSpecialize()&lt;/code&gt;
&lt;pre id=&quot;code_1713947284233&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#652
Line 652
*/
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring se_name,
        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
    jlong capabilities = 0;
    
    /* 중간 생략 */
    
    /*
    Utility routine to fork zygote and specialize the child process.
    Zygote가 fork()를 통해 애플리케이션 실행할 때 호출되는 네이티브 함수
    */
    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
            rlimits, capabilities, capabilities, mount_external, se_info,
            se_name, false, fdsToClose, instructionSet, appDataDir);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figure id=&quot;og_1714211015657&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;core/jni/com_android_internal_os_Zygote.cpp - platform/frameworks/base - Git at Google&quot; data-og-description=&quot;* Copyright (C) 2008 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &amp;quot;License&amp;quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&quot; data-og-host=&quot;android.googlesource.com&quot; data-og-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#444&quot; data-og-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#444&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#444&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;core/jni/com_android_internal_os_Zygote.cpp - platform/frameworks/base - Git at Google&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* Copyright (C) 2008 The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/lice&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;android.googlesource.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Call Trace&lt;br /&gt;&lt;code&gt;[1] core/java/com/android/internal/os/ZygoteInit.java - main()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[3] core/java/com/android/internal/os/ZygoteConnection.java - runOnce()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[4] core/java/com/android/internal/os/Zygote.java - forkAndSpecialize()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[5] core/jni/com_android_internal_os_Zygote.cpp - nativeForkAndSpecialize()&lt;/code&gt;&lt;br /&gt;&lt;code&gt;[6] core/jni/com_android_internal_os_Zygote.cpp - ForkAndSpecializeCommon()&lt;/code&gt;
&lt;pre id=&quot;code_1713947937579&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#444
Line 444
*/
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jstring instructionSet, jstring dataDir) {
  /* 중간 생략 */
  
  /*
  Zygote 프로세스 복제(fork)
  fork()로 생성된 프로세스가 안드로이드 애플리케이션으로 실행 됨
  */
  pid_t pid = fork();
  
  if (pid == 0) {
    // 안드로이드 애플리케이션으로 실행되는 자식 프로세스 루틴
    // The child process.
    
    /* 중간 생략 */
    
    /*
    후에 인자로 들어온 uid 값으로 UID를 변경하게 되는데 이때 UID를 변경해도
    Root의 기능을 유지할 수 있도록 설정
    
    이 기능은 함수를 호출한 쓰레드에서만 동작함
    즉, UID 변경 후에도 현재 쓰레드는 Root 권한을 행사할 수 있지만 
    다른 쓰레드는 그러지 못함
    */
    // Keep capabilities across UID change, unless we're staying root.
    if (uid != 0) {
      EnableKeepCapabilities(env);
    }
    
    /*
    1) 안드로이드 애플리케이션이 실행된 이후에 Capability를 얻지 못하게 하기 위해
    Root 권한이 소유할 수 있는 모든 Capability BoundingSet을 Drop 함
    
    BoundingSet : 프로세스가 실행 중인 동안 얻을 수 있는 Capability
    */
    DropCapabilitiesBoundingSet(env);
    
    /* 중간 생략 */
    
    /*
    2) 프로세스의 Real, Effective, Saved GID를 설정
    
    현재 함수의 인자에는 gid가 존재한다. 해당 인자에는 설정되어야 하는
    안드로이드 애플리케이션의 gid가 넘어온다. 해당 gid로 프로세스의
    egid, egid, sgid를 설정한다.
    */
    int rc = setresgid(gid, gid, gid);
    if (rc == -1) {
      ALOGE(&quot;setresgid(%d) failed: %s&quot;, gid, strerror(errno));
      RuntimeAbort(env, __LINE__, &quot;setresgid failed&quot;);
    }
    
    /*
    3) 프로세스의 Real, Effective, Saved UID를 설정
    
    현재 함수의 인자에는 uid가 존재한다. 해당 인자에는 설정되어야 하는
    안드로이드 애플리케이션의 uid가 넘어온다. 해당 uid로 프로세스의
    euid, euid, suid를 설정한다.
    */
    rc = setresuid(uid, uid, uid);
    if (rc == -1) {
      ALOGE(&quot;setresuid(%d) failed: %s&quot;, uid, strerror(errno));
      RuntimeAbort(env, __LINE__, &quot;setresuid failed&quot;);
    }
    
    /* 중간 생략 */
    
    /*
    4) 함수의 인자에는 permittedCapabilities와 effectiveCapabilities가 존재한다.
    이는 실행하려는 안드로이드 애플리케이션이 특정 루트 권한의 기능이 필요한 경우
    Capability를 이용해 해당 기능을 사용할 수 있도록 설정 하는 것이다.
    
    거의 대부분의 일반적인 안드로이드 애플리케이션은 아무런 권한도 설정되지 않는다.
    */
    SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
    
    /* 중간 생략 */
    
    /*
    안드로이드 애플리케이션의 실행 준비가 완료되었다면 다음 함수를 통해
    안드로이드 애플리케이션을 호출(실행)한다.
    */
    env-&amp;gt;CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                              is_system_server, instructionSet);                          
    if (env-&amp;gt;ExceptionCheck()) {
      RuntimeAbort(env, __LINE__, &quot;Error calling post fork hooks.&quot;);
    }
  } else if (pid &amp;gt; 0) {
    // the parent process
    /* 중간 생략 */
  }
  return pid;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 애플리케이션의 실행 과정을 추측한 후에 실제로 소스코드를 분석했을 때 거의 100% 추측 결과와 일치했다.&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;안드로이드 애플리케이션을 호출하기 전에 소스코드에 주석으로 표시한 4개의 함수를 통해 프로세스 스스로의 권한을 낮춘 후 &lt;code&gt;CallStaticVoidMethod()&lt;/code&gt; 함수를 통해 안드로이드 애플리케이션 함수를 호출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1714210210120&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Call Trace
[1] core/java/com/android/internal/os/ZygoteInit.java - main()
[2] core/java/com/android/internal/os/ZygoteInit.java - runSelectLoop()
[3] core/java/com/android/internal/os/ZygoteConnection.java - runOnce()
[4] core/java/com/android/internal/os/Zygote.java - forkAndSpecialize()
[5] core/jni/com_android_internal_os_Zygote.cpp - nativeForkAndSpecialize()
[6] core/jni/com_android_internal_os_Zygote.cpp - ForkAndSpecializeCommon()
 └ static void DropCapabilitiesBoundingSet(JNIEnv* env);
 └ int setresgid(gid_t rgid, gid_t egid, gid_t sgid); // Kernel Function
 └ int setresuid(uid_t ruid, uid_t euid, uid_t suid); // Kernel Function
 └ static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;setresgid()&lt;/code&gt;와 &lt;code&gt;setresuid()&lt;/code&gt; 함수는 커널 함수로 프로세스의 gid와 uid를 변경하는 함수이다. 다음 링크에 더 자세한 설명이 작성되어 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1714210517823&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;setresuid(2) - Linux manual page&quot; data-og-description=&quot;setresuid(2) &amp;mdash; Linux manual page setresuid(2) System Calls Manual setresuid(2) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top setresuid, setresgid - set real, effective, and saved user or group ID LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Standard C library (libc, -lc) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top #de&quot; data-og-host=&quot;man7.org&quot; data-og-source-url=&quot;https://man7.org/linux/man-pages/man2/setresuid.2.html&quot; data-og-url=&quot;https://man7.org/linux/man-pages/man2/setresuid.2.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man2/setresuid.2.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://man7.org/linux/man-pages/man2/setresuid.2.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;setresuid(2) - Linux manual page&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;setresuid(2) &amp;mdash; Linux manual page setresuid(2) System Calls Manual setresuid(2) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top setresuid, setresgid - set real, effective, and saved user or group ID LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Standard C library (libc, -lc) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top #de&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;man7.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1714210675311&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#227
Line 227
*/
static void DropCapabilitiesBoundingSet(JNIEnv* env) {
  /*
  i의 값에 해당되는 Capability를 가져옴 Capability가 존재한다면
  0 이상을 반환, 존재하지 않는다면 음수를 반환
  */
  for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) &amp;gt;= 0; i++) {
    /*
    현재 프로세스에서 i 값의 Capability를 BoundingSet에서 제거
    
    Capability가 바운딩(Bounding)되어 있지 않다면 허가(Permiited)되더라도
    실제(Effective)로 사용할 수 없다. 이는 Root 권한이라고 할지라도 바운딩과
    허가되어 있지 않다며 Root 권한으로써 기능을 수행할 수 없다
    */
    int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
    if (rc == -1) {
      if (errno == EINVAL) {
        ALOGE(&quot;prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify &quot;
              &quot;your kernel is compiled with file capabilities support&quot;);
      } else {
        RuntimeAbort(env, __LINE__, &quot;prctl(PR_CAPBSET_DROP) failed&quot;);
      }
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1714210698472&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-7.1.2_r39/core/jni/com_android_internal_os_Zygote.cpp#241
Line 241
*/
static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
  __user_cap_header_struct capheader;
  memset(&amp;amp;capheader, 0, sizeof(capheader));
  capheader.version = _LINUX_CAPABILITY_VERSION_3;
  capheader.pid = 0;
  
  __user_cap_data_struct capdata[2];
  memset(&amp;amp;capdata, 0, sizeof(capdata));
  capdata[0].effective = effective;
  capdata[1].effective = effective &amp;gt;&amp;gt; 32;
  capdata[0].permitted = permitted;
  capdata[1].permitted = permitted &amp;gt;&amp;gt; 32;
  
  /*
  capset 함수를 통해 effective와 permitted capability를 설정한다.
  
  일반적인 안드로이드 애플리케이션의 경우에는 아무런 값도 설정되지 않는다.
  이는 실제(Effective)로 사용 가능한 기능과 사용에 허가(Permitted) 받은
  Capability를 모두 지우겠다는 말이 된다.
  */
  if (capset(&amp;amp;capheader, &amp;amp;capdata[0]) == -1) {
    ALOGE(&quot;capset(%&quot; PRId64 &quot;, %&quot; PRId64 &quot;) failed&quot;, permitted, effective);
    RuntimeAbort(env, __LINE__, &quot;capset failed&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;최종적으로 &lt;code&gt;ForkAndSpecializeCommon()&lt;/code&gt; 함수의 시작부터 안드로이드 애플리케이션 시작까지 소스 코드의 워크 플로우는 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4Avci/btsGYStNKDS/r6DPN7qgxqF5D4I8Pc5bmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4Avci/btsGYStNKDS/r6DPN7qgxqF5D4I8Pc5bmK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4Avci/btsGYStNKDS/r6DPN7qgxqF5D4I8Pc5bmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4Avci%2FbtsGYStNKDS%2Fr6DPN7qgxqF5D4I8Pc5bmK%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;1810&quot; height=&quot;592&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to run application as root for Android&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zygote가 프로세스를 실행하기 전 권한들을 모두 Drop하고 uid와 gid를 변경한다. 이때 특정 uid와 gid를 가지고 있는 안드로이드 애플리케이션의 경우에는 Capabilities를 Drop하지 않고 uid와 gid를 변경하지 않도록 함수를 조작할 수 있다면 특정 안드로이드 애플리케이션을 Root 권한으로 실행시키는 것이 가능해진다.&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;안드로이드 애플리케이션을 Root 권한으로 실행하기 위해 모니터링하며 조작이 필요한 함수는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1714231261307&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int setresuid(uid_t ruid, uid_t euid, uid_t suid);
int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
int prctl(int option, ...);
int capset(cap_user_header_t hdrp, const cap_user_data_t datap);&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;Zygote 프로세스의 특정 함수의 동작을 조작하기 위해서 &lt;code&gt;LD_PRELOAD&lt;/code&gt;를 사용했다.&lt;/p&gt;
&lt;figure id=&quot;og_1714663219436&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;[Reversing] LD_PRELOAD를 이용한 후킹&quot; data-og-description=&quot;LD_PRELOADLD_PRELOAD는 Linux 운영체제의 환경 변수이다.&amp;nbsp;LD_PRELOAD에는 Linux 운영체제의 공유 라이브러리(Shared Library) 파일이 설정되고 설정된 공유 라이브러리들을 모든 공유 라이브러리들보다 먼저 &quot; data-og-host=&quot;blog.crazyhacker.kr&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/140&quot; data-og-url=&quot;https://blog.crazyhacker.kr/140&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bplcQI/hyVVIDeuR1/SZxDTHVyBAn2b9bqJ6RtF0/img.png?width=800&amp;amp;height=204&amp;amp;face=0_0_800_204,https://scrap.kakaocdn.net/dn/bhleN3/hyVVMli2RQ/ZEnKVkMUk60CN45mDnCZkK/img.png?width=800&amp;amp;height=204&amp;amp;face=0_0_800_204,https://scrap.kakaocdn.net/dn/bQUFh6/hyVZk8w9G4/68OYQVdoMxSJkKDQg3PCEK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/140&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bplcQI/hyVVIDeuR1/SZxDTHVyBAn2b9bqJ6RtF0/img.png?width=800&amp;amp;height=204&amp;amp;face=0_0_800_204,https://scrap.kakaocdn.net/dn/bhleN3/hyVVMli2RQ/ZEnKVkMUk60CN45mDnCZkK/img.png?width=800&amp;amp;height=204&amp;amp;face=0_0_800_204,https://scrap.kakaocdn.net/dn/bQUFh6/hyVZk8w9G4/68OYQVdoMxSJkKDQg3PCEK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Reversing] LD_PRELOAD를 이용한 후킹&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;LD_PRELOADLD_PRELOAD는 Linux 운영체제의 환경 변수이다.&amp;nbsp;LD_PRELOAD에는 Linux 운영체제의 공유 라이브러리(Shared Library) 파일이 설정되고 설정된 공유 라이브러리들을 모든 공유 라이브러리들보다 먼저&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.crazyhacker.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LD_PRELOAD로 로드되는 후킹 라이브러리 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1714753904027&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define _GNU_SOURCE
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;dlfcn.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;sys/prctl.h&amp;gt;
#include &amp;lt;sys/capability.h&amp;gt;
#include &amp;lt;linux/seccomp.h&amp;gt;

pid_t pid = -1;

int (*origin_setresuid)(uid_t ruid, uid_t euid, uid_t suid);
int (*origin_setresgid)(gid_t rgid, gid_t egid, gid_t sgid);
int (*origin_prctl)(int option, ...);
int (*origin_capset)(cap_user_header_t __hdr_ptr, const cap_user_data_t __data_ptr);

void dropCapabilitiesBoundingSet()
{
    for (int i = 0; origin_prctl(PR_CAPBSET_READ, i, 0, 0, 0) &amp;gt;= 0; i++)
    {
        if (origin_prctl(PR_CAPBSET_DROP, i, 0, 0, 0) == -1)
        {
            printf(&quot;Failed %d\n&quot;, i);
        }
    }
}

int isRootApplication(pid_t uid)
{
    char line[512];
    FILE *package_list = fopen(&quot;/data/system/packages.list&quot;, &quot;r&quot;);
    FILE *root_app_list = fopen(&quot;/data/local/tmp/root_app.list&quot;, &quot;r&quot;);

    if (package_list == NULL || root_app_list == NULL)
        goto exit;

    while (fgets(line, sizeof(line), package_list) != NULL)
    {
        char root_package_name[64];
        char package_name[128];
        pid_t package_uid = -1;
        sscanf(line, &quot;%s %d&quot;, package_name, &amp;amp;package_uid);

        if (package_uid == uid)
        {
            while (fgets(root_package_name, sizeof(root_package_name), root_app_list) != NULL)
            {
                if (strncmp(package_name, root_package_name, strlen(package_name)) == 0)
                {
                    fclose(package_list);
                    fclose(root_app_list);
                    return 1;
                }
            }
        }
    }

exit:
    fclose(package_list);
    fclose(root_app_list);
    
    return 0;
}

int capset(cap_user_header_t __hdr_ptr, const cap_user_data_t __data_ptr)
{
    if (pid == getpid())
        return 0;

    if (origin_capset == NULL)
        origin_capset = dlsym(RTLD_NEXT, &quot;capset&quot;);

    return origin_capset(__hdr_ptr, __data_ptr);
}

int prctl(int option, ...)
{
    va_list args;
    va_start(args, option);

    long arg2 = va_arg(args, long);
    long arg3 = va_arg(args, long);
    long arg4 = va_arg(args, long);
    long arg5 = va_arg(args, long);

    va_end(args);

    if (option == PR_CAPBSET_DROP)
        return 0;

    if (origin_prctl == NULL)
        origin_prctl = dlsym(RTLD_NEXT, &quot;prctl&quot;);

    return origin_prctl(option, arg2, arg3, arg4, arg5);
}

int setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
    if (isRootApplication(ruid))
    {
        pid = getpid();
        dropCapabilitiesBoundingSet();
        return 0;
    }

    if (origin_setresuid == NULL)
        origin_setresuid = dlsym(RTLD_NEXT, &quot;setresuid&quot;);

    return origin_setresuid(ruid, euid, suid);
}

int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
    if (isRootApplication(rgid))
        return 0;
	
    if (origin_setresgid == NULL)
        origin_setresgid = dlsym(RTLD_NEXT, &quot;setresgid&quot;);

    return origin_setresgid(rgid, egid, sgid);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How does Zygote run?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;LD_PRELOAD를 사용하기 위해서는 Zygote의 환경 변수를 조작해야하기 때문에 Zygote가 어떠한 방식으로 init 프로세스의 의해 실행되는지 알아야할 필요가 있다.&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Zygote는 init 프로세스가 자기 자신을 &lt;code&gt;fork()&lt;/code&gt; 함수를 통해 복제한 뒤 &lt;code&gt;execve()&lt;/code&gt; 함수를 통해 app_process를 실행하는 방식으로 실행된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1655&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beyCG7/btsGZBx1OI3/i4kOhSP7va5yVsnoqkH5JK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beyCG7/btsGZBx1OI3/i4kOhSP7va5yVsnoqkH5JK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beyCG7/btsGZBx1OI3/i4kOhSP7va5yVsnoqkH5JK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeyCG7%2FbtsGZBx1OI3%2Fi4kOhSP7va5yVsnoqkH5JK%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;1655&quot; height=&quot;647&quot; data-origin-width=&quot;1655&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;execve() 함수의 원형을 보면 envp 인자가 존재하는데 해당 인자가 실행되는 프로그램의 환경 변수를 설정하게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1714235942841&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;int execve(const char *pathname, char *const argv[], char *const envp[]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zygote를 실행하기 위해 execve() 함수를 호출할 때 envp 인자에 LD_PRELOAD를 삽입하는 방식으로 조작할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to set the LD_PRELOAD environment variable on Zygote&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zygote의 함수를 조작하기 위해 Zygote 프로세스의 환경 변수에 &lt;code&gt;LD_PRELOAD&lt;/code&gt;를 추가해 해당 함수들을 조작해 안드로이드 애플리케이션이 Root 권한으로 실행될 수 있도록 해야한다.&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;init 프로세스를 이용해 Zygote 프로세스에 LD_PRELOAD 환경 변수를 삽입하는 순서는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;※ init 프로세스는 Zygote 프로세스가 종료되었을 때 Zygote 프로세스를 재시작한다. ※&lt;br /&gt;[1] init 프로세스를 ptrace로 감시한다.&lt;br /&gt;[2] 기존 Zygote 프로세스를 KILL 한다.&lt;br /&gt;[3] init 프로세스는 Zygote의 SIGCHLD 시그널을 받고 Zygote 프로세스를 재시작한다.&lt;br /&gt;[4] init 프로세스는 Zygote의 재시작을 위해 fork() 함수를 호출한다. 이때 해당 함수를 통해 생성된 프로세스로 ptrace를 옮긴다.&lt;br /&gt;[5] 새로 생성된 프로세스(New Zygote)에서 execve() 함수로 app_process를 실행한다. 이때 envp 인자에 LD_PRELOAD를 삽입한다.&lt;br /&gt;[6] LD_PRELOAD로 인해 위에서 언급한 4개의 함수가 후킹된 상태로 Zygote 프로세스 실행 성공&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1023&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTMTei/btsGYNMVb1N/sIyS0jEsryV6Y7qkHAk2nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTMTei/btsGYNMVb1N/sIyS0jEsryV6Y7qkHAk2nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTMTei/btsGYNMVb1N/sIyS0jEsryV6Y7qkHAk2nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTMTei%2FbtsGYNMVb1N%2FsIyS0jEsryV6Y7qkHAk2nk%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;1688&quot; height=&quot;1023&quot; data-origin-width=&quot;1688&quot; data-origin-height=&quot;1023&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PoC Video&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;PoC 코드는 다음 Github에서 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1717620079395&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Run-Application-as-Root-for-Android: Run Application as Root for Android&quot; data-og-description=&quot;Run Application as Root for Android. Contribute to jungjin0003/Run-Application-as-Root-for-Android development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Run-Application-as-Root-for-Android&quot; data-og-url=&quot;https://github.com/jungjin0003/Run-Application-as-Root-for-Android&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bglACn/hyWg3ljr1V/VBGKOmpvwodE9kWENPdYqK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Run-Application-as-Root-for-Android&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jungjin0003/Run-Application-as-Root-for-Android&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bglACn/hyWg3ljr1V/VBGKOmpvwodE9kWENPdYqK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Run-Application-as-Root-for-Android: Run Application as Root for Android&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Run Application as Root for Android. Contribute to jungjin0003/Run-Application-as-Root-for-Android development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/446517267&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bpnJhG/hyV2q1pNAt/hOz2KivoDFKkAM8HDU8jbk/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/ds7Dl2/hyV2sdRUYI/KnpwNBckD7gEDbkNoCwtnK/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot; data-original-url=&quot;&quot; data-video-title=&quot;&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/446517267?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/141</guid>
      <comments>https://crazyhacker.tistory.com/141#entry141comment</comments>
      <pubDate>Thu, 6 Jun 2024 05:41:30 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] LD_PRELOAD를 이용한 후킹</title>
      <link>https://crazyhacker.tistory.com/140</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LD_PRELOAD&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;code&gt;LD_PRELOAD&lt;/code&gt;는 Linux 운영체제의 환경 변수이다.&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;LD_PRELOAD에는 Linux 운영체제의 &lt;span style=&quot;color: #ee2323;&quot;&gt;공유 라이브러리(Shared Library) 파일&lt;/span&gt;이 설정되고 설정된 공유 라이브러리들을 &lt;span style=&quot;color: #ee2323;&quot;&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;Linux 운영체제의 응용 프로그램은 라이브러리가 &lt;span style=&quot;color: #ee2323;&quot;&gt;로드된 순서대로 사용하려는 함수가 존재하는지 확인&lt;/span&gt;한다. 이때 LD_PRELOAD로 인해 &lt;span style=&quot;color: #ee2323;&quot;&gt;먼저 로드된 라이브러리에 사용하려는 함수가 존재한다면 LD_PRELOAD의 라이브러리의 함수 주소를 가져온다&lt;/span&gt;. 이러한 원리를 이용한 방법이 LD_PRELOAD를 이용한 후킹 기법이다,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1685&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uFmlz/btsG8AyIee7/pXNw35AqWidSycV27ymDTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uFmlz/btsG8AyIee7/pXNw35AqWidSycV27ymDTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uFmlz/btsG8AyIee7/pXNw35AqWidSycV27ymDTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuFmlz%2FbtsG8AyIee7%2FpXNw35AqWidSycV27ymDTk%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;1685&quot; height=&quot;456&quot; data-origin-width=&quot;1685&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;*공유 라이브러리(Shared Libary) : Linux 운영체제의 공유 라이브러리로 확장자는 주로 .so 이며 Windows 운영체제의 DLL 파일과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LD_PRELOAD Environment Variable&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Linux 운영체제에서 LD_PRELOAD 환경 변수를 설정하는 방법은 여러가지인데, 그중 자주 사용되는 두 가지 방법이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Inline&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;첫 번째 방법은 특정 프로그램에만 설정하는 방법이다. 이렇게 Shell에서 프로그램을 실행시킬 때 앞에 LD_PRELOAD를 설정해주면 해당 프로그램에만 적용해 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714659343704&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;root@ubuntu:~# LD_PRELOAD=/tmp/libtest.so ./example&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;In the current Shell&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 방법은 현재 쉘에서 실행되는 모든 프로그램에 LD_PRELOAD를 설정하는 방법이다. 다음과 같이 export 명령어를 사용해 Shell에 환경 변수를 설정하면 이후 해당 쉘에서 실행되는 모든 프로그램에 LD_PRELOAD가 설정되어 실행된다.&lt;/p&gt;
&lt;pre id=&quot;code_1714659784609&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root@ubuntu:~# export LD_PRELOAD=/tmp/libtest.so
root@ubuntu:~# ./example&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Make a shared library to be used for LD_PRELOAD&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Linux 운영체제에서 LD_PRELOAD를 사용하는 후킹은 그렇게 어렵지 않다. 기본적으로 함수명만 동일하다면 LD_PRELOAD를 사용해 후킹을 진행할 수 있다. 반환형, 인자 등 함수명을 제외한 그 무엇도 신경쓰지 않지만 정상적으로 인자를 받고 후킹을 진행하기 위해서는 해당 함수의 원형을 사용하는 것이 좋다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;다음과 같은 코드의 프로그램에 LD_PRELOAD를 적용한다고 했을 때의 공유 라이브러리를 만들어보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714660500101&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(int argc, char *argv[])
{
    char key[] = &quot;This is secret key&quot;;
    char buf[64] = { 0 };

    strcpy(buf, key);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 프로그램 비밀키를 buf로 strcpy 함수를 이용해 복사한다. 이때 strcpy 함수를 후킹해 비밀키의 내용을 출력해보려고 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Check prototype of the function to hooking&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 strcpy 함수의 원형을 알아보자. 리눅스 매뉴얼에 따르면 strcpy 함수의 원형을 다음과 같다.&lt;/p&gt;
&lt;figure id=&quot;og_1714660674533&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;strcpy(3) - Linux manual page&quot; data-og-description=&quot;strcpy(3) &amp;mdash; Linux manual page strcpy(3) Library Functions Manual strcpy(3) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top stpcpy, strcpy, strcat - copy or catenate a string LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Standard C library (libc, -lc) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top #include char *stpcpy(char &quot; data-og-host=&quot;man7.org&quot; data-og-source-url=&quot;https://man7.org/linux/man-pages/man3/strcpy.3.html&quot; data-og-url=&quot;https://man7.org/linux/man-pages/man3/strcpy.3.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man3/strcpy.3.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://man7.org/linux/man-pages/man3/strcpy.3.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;strcpy(3) - Linux manual page&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;strcpy(3) &amp;mdash; Linux manual page strcpy(3) Library Functions Manual strcpy(3) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top stpcpy, strcpy, strcat - copy or catenate a string LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Standard C library (libc, -lc) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top #include char *stpcpy(char&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;man7.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1714660752974&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char *stpcpy(char *restrict dst, const char *restrict src);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 통해 후킹할 함수를 정의했다. 내용은 src 인자로 들어온 문자열을 출력하는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1714662785497&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

char *strcpy(char *dst, const char *src)
{
    printf(&quot;Data : %s&quot;, src);
    return dst;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 한가지 문제가 존재하는데 후킹한 함수가 정상적으로 해당 함수의 역할을 수행해야할 필요가 있다. 그렇기 때문에 원본 함수의 주소를 알아내는 방법을 알아야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to get address of original function&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux 운영체제에서는 dlsym 함수를 통해 원본 함수의 주소를 구할 수 있다.&lt;/p&gt;
&lt;figure id=&quot;og_1714661333675&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;dlsym(3) - Linux manual page&quot; data-og-description=&quot;dlsym(3) &amp;mdash; Linux manual page dlsym(3) Library Functions Manual dlsym(3) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top dlsym, dlvsym - obtain address of a symbol in a shared object or executable LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Dynamic linking library (libdl, -ldl) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to&quot; data-og-host=&quot;man7.org&quot; data-og-source-url=&quot;https://man7.org/linux/man-pages/man3/dlsym.3.html&quot; data-og-url=&quot;https://man7.org/linux/man-pages/man3/dlsym.3.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://man7.org/linux/man-pages/man3/dlsym.3.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://man7.org/linux/man-pages/man3/dlsym.3.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;dlsym(3) - Linux manual page&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;dlsym(3) &amp;mdash; Linux manual page dlsym(3) Library Functions Manual dlsym(3) NAME &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top dlsym, dlvsym - obtain address of a symbol in a shared object or executable LIBRARY &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; top Dynamic linking library (libdl, -ldl) SYNOPSIS &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;man7.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1714661355552&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;void *dlsym(void *restrict handle, const char *restrict symbol);&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;해당 함수를 사용하기 위해서는 &lt;code&gt;dlfcn.h&lt;/code&gt; 헤더 파일이 필요하고 &lt;code&gt;_GNU_SOURCE&lt;/code&gt; 상수가 정의되어 있어야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1714663052941&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define _GNU_SOURCE
#include &amp;lt;dlfcn.h&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;handle에는 함수를 검색할 라이브러리가 들어가야 하지만 특정 라이브러리에서 함수 주소를 구하는 것이 아니라면 RTLD_NEXT를 전달하면 되고 symbol에는 함수명을 전달하면 된다.&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;RTLD_NEXT는 현재 라이브러리 다음으로 로드된 라이브러리를 의미하기 때문에 다음 라이브러리부터 차례대로 해당 함수가 존재하는지 라이브러리에서 확인해 주소를 구하게 된다.&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;1679&quot; data-origin-height=&quot;429&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sOune/btsG78JeCxv/PFOb426GvokZsZRomWuiMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sOune/btsG78JeCxv/PFOb426GvokZsZRomWuiMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sOune/btsG78JeCxv/PFOb426GvokZsZRomWuiMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsOune%2FbtsG78JeCxv%2FPFOb426GvokZsZRomWuiMK%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;1679&quot; height=&quot;429&quot; data-origin-width=&quot;1679&quot; data-origin-height=&quot;429&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1714661861144&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define _GNU_SOURCE
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;dlfcn.h&amp;gt;

char *(*origin_strcpy)(char *dst, const char *src);

char *strcpy(char *dst, const char *src)
{
    if (origin_strcpy == NULL)
    {
        origin_strcpy = dlsym(RTLD_NEXT, &quot;strcpy&quot;);
    }
    printf(&quot;Data : %s&quot;, src);

    return origin_strcpy(dst, src);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 소스코드를 리눅스에서 컴파일러를 이용해 컴파일 한 후에 LD_PRELOAD를 이용해 프로그램을 실행하면 다음과 같은 결과를 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1714662286728&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root@ubuntu:/tmp# LD_PRELOAD=./libtest.so ./main
Data : This is secret key&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 비밀키를 복사한 후에 아무런 반응 없이 종료되어야할 프로그램이 LD_PRELOAD에 설정된 라이브러리로 인해 인자로 들어온 비밀키를 출력하는 모습을 볼 수 있다.&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;이렇게 LD_PRELOAD를 이용한 후킹을 진행해보았다. Linux 운영체제는 Windows 운영체제에 비해 후킹이 비교적 간단했으며 이런 기능이 운영체제 자체적으로 존재한다는 것이 신기했다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/140</guid>
      <comments>https://crazyhacker.tistory.com/140#entry140comment</comments>
      <pubDate>Fri, 3 May 2024 00:19:29 +0900</pubDate>
    </item>
    <item>
      <title>서식 테스트2</title>
      <link>https://crazyhacker.tistory.com/pages/%EC%84%9C%EC%8B%9D-%ED%85%8C%EC%8A%A4%ED%8A%B82</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;서식&amp;nbsp;테스트2&lt;/p&gt;</description>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/pages/%EC%84%9C%EC%8B%9D-%ED%85%8C%EC%8A%A4%ED%8A%B82</guid>
      <pubDate>Mon, 12 Dec 2022 02:48:37 +0900</pubDate>
    </item>
    <item>
      <title>서식 테스트</title>
      <link>https://crazyhacker.tistory.com/pages/%EC%84%9C%EC%8B%9D-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Hello World&lt;/p&gt;</description>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/pages/%EC%84%9C%EC%8B%9D-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
      <pubDate>Sat, 22 Oct 2022 00:12:00 +0900</pubDate>
    </item>
    <item>
      <title>[Network] IPv6(Internet Protocol version 6) 헤더</title>
      <link>https://crazyhacker.tistory.com/119</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인터넷 프로토콜&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인터넷&lt;/b&gt; &lt;b&gt;프로토콜&lt;/b&gt;(&lt;b&gt;IP&lt;/b&gt;, &lt;b&gt;I&lt;/b&gt;nternet &lt;b&gt;P&lt;/b&gt;rotocol)은 두 호스트가 네트워크에서 패킷을 교환하며 정보를 주고 받는 데 사용하는 규약이며, 호스트의 주소 지정과 패킷 분할 및 조립 기능을 담당한다. 줄여서 &lt;b&gt;아이피&lt;/b&gt;(IP)라고도 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주소 체계&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인터넷 프로토콜은 특정한 호스트의 주소를 지정할 수 있도록 설계되었다. 보편적으로 사용되는 IP 주소 체계는 IPv4와 IPv6가 있다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;IPv6는 인터넷 프로토콜의 6번째 버전이다. IPv4 주소가 모두 소진되어 더 이상 IPv4 주소를 할당할 수 없음에 따라 IPv6가 개발되었다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;IPv6는 128비트로 구성되어 있으며, 16비트(2바이트)를 16진수로 표현하여 8자리로 나타낸다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;IPv6 주소 예시 : 2001:0db8:85a3:08d3:1319:8a2e:0370:7334&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;IPv6 주소의 개수는 128비트로 표현할 수 있는 2^128개인 약 3.4x10^38개의 주소를 갖고 있어 거의 무한대로 쓸 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;헤더&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷 프로토콜 버전 6 헤더는 확장 헤더를 포함하지 않은 경우 40바이트이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XS2p7/btrNxewzDTo/XYa107uG5yMkop8O6RA1K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XS2p7/btrNxewzDTo/XYa107uG5yMkop8O6RA1K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XS2p7/btrNxewzDTo/XYa107uG5yMkop8O6RA1K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXS2p7%2FbtrNxewzDTo%2FXYa107uG5yMkop8O6RA1K0%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;956&quot; height=&quot;748&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;748&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;1458&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sxu9z/btrNv8KDK1b/NtrA5SzavaEawkOZ4vPJy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sxu9z/btrNv8KDK1b/NtrA5SzavaEawkOZ4vPJy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sxu9z/btrNv8KDK1b/NtrA5SzavaEawkOZ4vPJy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsxu9z%2FbtrNv8KDK1b%2FNtrA5SzavaEawkOZ4vPJy1%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;1458&quot; height=&quot;571&quot; data-origin-width=&quot;1458&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Network</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/119</guid>
      <comments>https://crazyhacker.tistory.com/119#entry119comment</comments>
      <pubDate>Sat, 1 Oct 2022 19:27:12 +0900</pubDate>
    </item>
    <item>
      <title>[Network] IPv4(Internet Protocol version 4) 헤더</title>
      <link>https://crazyhacker.tistory.com/118</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;인터넷 프로토콜&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인터넷&lt;/b&gt; &lt;b&gt;프로토콜&lt;/b&gt;(&lt;b&gt;IP&lt;/b&gt;, &lt;b&gt;I&lt;/b&gt;nternet &lt;b&gt;P&lt;/b&gt;rotocol)은 두 호스트가 네트워크에서 패킷을 교환하며 정보를 주고 받는 데 사용하는 규약이며, 호스트의 주소 지정과 패킷 분할 및 조립 기능을 담당한다. 줄여서 &lt;b&gt;아이피&lt;/b&gt;(IP)라고도 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주소 체계&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷 프로토콜은 특정한 호스트의 주소를 지정할 수 있도록 설계되었다. 보편적으로 사용되는 IP 주소 체계는 IPv4와 IPv6가 있다.&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;color: #333333;&quot;&gt;IPv4는 인터넷 프로토콜의 4번째 버전이다. 전 세계적으로 사용된 첫 번째 인트넷 프로토콜이며, 과거에 사용되던 유일한 인터넷 프로토콜이였으나 오늘날에는 IPv4의 주소가 소진되어 IPv4의 할당이 중지되고 IPv6로 대체되고 있다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;IPv4의 주소체계는 총 12자리이며 네 부분으로 나뉜다. 각 부분 마다 0~255까지 3자리의 수로 표현된다. IPv4는 32비트로 구성되어 있으며, 한 부분당 1바이트이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;IPv4 주소 예시 : 192.168.123.100&lt;/blockquote&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;color: #333333;&quot;&gt;IPv4 주소의 개수는 32비트로 표현할 수 있는 2^32개인 약 43억개이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;헤더&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인터넷 프로토콜 버전 4 헤더는 옵션 미지정시 20바이트이며, 고정 20바이트와 가변 0 ~ 40바이트가 있다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;인터넷 프로토콜 버전 4 헤더는 최소 20바이트의 사이즈를 가지며 옵션에 따라 0 ~ 40바이트가 늘어날 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;641&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnF3mj/btrNzFG38Lv/EpLapz0m57zJnCNjus5lC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnF3mj/btrNzFG38Lv/EpLapz0m57zJnCNjus5lC0/img.png&quot; data-alt=&quot;IPv4 헤더의 고정 부분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnF3mj/btrNzFG38Lv/EpLapz0m57zJnCNjus5lC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnF3mj%2FbtrNzFG38Lv%2FEpLapz0m57zJnCNjus5lC0%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;973&quot; height=&quot;641&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;641&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IPv4 헤더의 고정 부분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsdpxZ/btrNvP5uqgz/KArk87R4S1huYnqBdKaur0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsdpxZ/btrNvP5uqgz/KArk87R4S1huYnqBdKaur0/img.png&quot; data-alt=&quot;IPv4 헤더의 가변 부분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsdpxZ/btrNvP5uqgz/KArk87R4S1huYnqBdKaur0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsdpxZ%2FbtrNvP5uqgz%2FKArk87R4S1huYnqBdKaur0%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;954&quot; height=&quot;188&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;188&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;IPv4 헤더의 가변 부분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;467&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sDsXa/btrNwFA0OhS/3JHKrP3oYiHUzA926lUwY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sDsXa/btrNwFA0OhS/3JHKrP3oYiHUzA926lUwY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sDsXa/btrNwFA0OhS/3JHKrP3oYiHUzA926lUwY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsDsXa%2FbtrNwFA0OhS%2F3JHKrP3oYiHUzA926lUwY1%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;1390&quot; height=&quot;467&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;467&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1664621916566&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct _NETWORK_IP_HEADER
{
    unsigned char HeaderLength : 4;          // IP Header Length
    unsigned char Version : 4;               // Internet Protocol Version
    union
    {
        unsigned char TypeOfService;         // Type of Service
        struct
        {
            unsigned char ECN : 2;           // Differentiated Services Codepoint
            unsigned char DSCP : 6;          // Explicit Congestion Notification
        };
    };
    unsigned short TotalLength;              // Total Packet Length in byte except for Ethernet Header Length
    unsigned short Identification;           // IP Packet Identifier
    union
    {
        unsigned short Flag;                 // Information about the status of the packet segmentation.
        unsigned short FragmentOffset : 13;  // Original Location of Split Packets
        struct
        {
            unsigned short : 13;             // bit field padding
            unsigned short MoreFragment : 1; // More fragment packets present
            unsigned short DontFragment : 1; // It is last fragment packet
            unsigned short Reserved : 1;     // Reserved, always set to 0
        } Flags;
    };
    unsigned char TTL;                       // Time To Live
    unsigned char Protocol;                  // Protocol Type in the next layer
    unsigned short Checksum;                 // Header Checksum
    struct sockaddr_in SourceAddr;           // Source IP Address
    struct sockaddr_in DestinationAddr;      // Destination IP Address
    // unsigned long SourceAddr;
    // unsigned long DestinationAddr;
} NETWORK_IP_HEADER, *PNETWORK_IP_HEADER;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Network</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/118</guid>
      <comments>https://crazyhacker.tistory.com/118#entry118comment</comments>
      <pubDate>Sat, 1 Oct 2022 01:58:05 +0900</pubDate>
    </item>
    <item>
      <title>[Network] 이더넷 헤더 (Ethernet Header(Protocol))</title>
      <link>https://crazyhacker.tistory.com/117</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이더넷&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이더넷&lt;/b&gt;(Ethernet)은 컴퓨터 네트워크에서 사용하는 기술이다. LAN, MAN, WAN 등 거의 모든 네트워크 분야에서 활용되는 기술 규격이며, OSI 모델의 데이터 링크 계층에서 MAC 패킷과 프로토콜 형식을 정의한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이더넷은 네트워크에서 각 기기들이 48비트 길이의 고유한 MAC 주소를 가지고 데이터를 주고 받을 수 있도록 만들어졌다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;헤더&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이더넷 헤더의 사이즈는 총 14바이트으로 이루어져 있으며, 6바이트의 도착지(Destination) 그리고 출발지(Source) MAC 주소, 2바이트의 Ethernet Type이 존재한다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;Ethernet Type에는 다음 계층의 프로토콜이 무엇인지 기록된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xxbkB/btrNo7YKH9P/dk6ObEUdYvxdMAgpn8UtJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xxbkB/btrNo7YKH9P/dk6ObEUdYvxdMAgpn8UtJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xxbkB/btrNo7YKH9P/dk6ObEUdYvxdMAgpn8UtJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxxbkB%2FbtrNo7YKH9P%2Fdk6ObEUdYvxdMAgpn8UtJ1%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;1280&quot; height=&quot;249&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;249&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;1170&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mfYss/btrNosvrP4s/mR3O3074tpLF2pbOOlUnQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mfYss/btrNosvrP4s/mR3O3074tpLF2pbOOlUnQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mfYss/btrNosvrP4s/mR3O3074tpLF2pbOOlUnQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmfYss%2FbtrNosvrP4s%2FmR3O3074tpLF2pbOOlUnQK%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;1170&quot; height=&quot;377&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZVsOy/btrNqYUjdi8/aOWVsuQ94sk4pfIWDLrcjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZVsOy/btrNqYUjdi8/aOWVsuQ94sk4pfIWDLrcjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZVsOy/btrNqYUjdi8/aOWVsuQ94sk4pfIWDLrcjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZVsOy%2FbtrNqYUjdi8%2FaOWVsuQ94sk4pfIWDLrcjk%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;814&quot; height=&quot;135&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1664451159728&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct _NETWORK_ETHERNET_HEADER
{
    unsigned char Destination[6]; /* Destination MAC Address */
    unsigned char Source[6];      /* Source MAC Address */
    unsigned short Type;          /* Ethernet Type */
} NETWORK_ETHERNET_HEADER, *PNETWORK_ETHERNET_HEADER;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Network</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/117</guid>
      <comments>https://crazyhacker.tistory.com/117#entry117comment</comments>
      <pubDate>Thu, 29 Sep 2022 20:21:31 +0900</pubDate>
    </item>
    <item>
      <title>[Network] 네트워크 바이트 오더 (Network Byte Order)</title>
      <link>https://crazyhacker.tistory.com/116</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;바이트 오더(Byte Order)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;b&gt;Little Endian&lt;/b&gt;,&amp;nbsp;&lt;b&gt;Middle Endian&lt;/b&gt;,&amp;nbsp;&lt;b&gt;Big Endian&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;Intel과 AMD 계열의 프로세서는 주로 Little Endian을 사용한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;저장 방식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빅 엔디안은 &lt;b&gt;상위 바이트부터 순서대로 저장&lt;/b&gt; 되고 리틀 엔디안은 &lt;b&gt;하위 바이트부터 순서대로 저장&lt;/b&gt;된다는 차이점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 51px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;종류&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;0x1234 표현(2바이트 표현)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;0x12345678 표현(4바이트 표현)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;Big Endian (빅 엔디안)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 12 34 XX XX XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 12 34 56 78 XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;Little Endian (리틀 엔디안)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 34 12 XX XX XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 78 56 34 12 XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 바이트 오더(Network Byte Order)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;네트워크 바이트 오더(Network Byte Order)란 네트워크에서 사용하는 바이트 오더(Byte Order)를 말한다.&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;네트워크에서는 Big Endian을 사용한다. 그렇기 때문에 주로 Little Endian을 사용하는 대부분의 PC는 네트워크 바이트 오더를 호스트 바이트 오더(해당 PC가 사용하는 바이트 오더)로 변환해야 할 필요가 있다.&lt;/p&gt;</description>
      <category>Network</category>
      <category>byte order</category>
      <category>Network</category>
      <category>Network Byte Order</category>
      <category>네트워크</category>
      <category>네트워크 바이트 오더</category>
      <category>바이트 오더</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/116</guid>
      <comments>https://crazyhacker.tistory.com/116#entry116comment</comments>
      <pubDate>Thu, 29 Sep 2022 19:25:10 +0900</pubDate>
    </item>
    <item>
      <title>[C] 패킷의 이더넷(Ethernet) 헤더의 정보 출력하기</title>
      <link>https://crazyhacker.tistory.com/114</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이더넷 프로토콜이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이더넷은 전세계적으로 사용되는 기술 규격이다. OSI 모델 데이터 링크 계층에서 MAC 패킷과 프로토콜을 정의한다. 또한 네트워크에서 각 기기가 48비트 길이의 고유 MAC 주소를 이용하여 데이터를 주고 받을 수 있도록 만들어졌다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이더넷 헤더&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이더넷 헤더의 사이즈는 총 14바이트으로 이루어져 있으며, 6바이트의 도착지(Destination) 그리고 출발지(Source) MAC 주소, 2바이트의 Ethernet Type이 존재한다.&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;Ethernet Type에는 다음 계층의 프로토콜이 무엇인지 기록된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1485&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EN89O/btrNkaWK3NG/q2ZpwqSyKh7yTuGHOQKrwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EN89O/btrNkaWK3NG/q2ZpwqSyKh7yTuGHOQKrwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EN89O/btrNkaWK3NG/q2ZpwqSyKh7yTuGHOQKrwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEN89O%2FbtrNkaWK3NG%2Fq2ZpwqSyKh7yTuGHOQKrwK%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;1485&quot; height=&quot;289&quot; data-origin-width=&quot;1485&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구조체&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;C언어를 기준으로 구조체는 아래와 같이 정의할 수 있으며 &lt;b&gt;필요한 경우 구조체 바이트 정렬이 필요&lt;/b&gt;하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1664444159684&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct _NETWORK_ETHERNET_HEADER
{
    unsigned char Destination[6]; /* Destination MAC Address */
    unsigned char Source[6];      /* Source MAC Address */
    unsigned short Type;          /* Ethernet Type | You need to change the byte order */
} NETWORK_ETHERNET_HEADER, *PNETWORK_ETHERNET_HEADER;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 바이트 오더(Network Byte Order)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;네트워크 바이트 오더(Network Byte Order)란 네트워크에서 사용하는 바이트 오더(Byte Order)를 말한다. 쉽게 말해 컴퓨터 시스템에는 &lt;b&gt;Little Endian&lt;/b&gt;, &lt;b&gt;Middle Endian&lt;/b&gt;,&amp;nbsp;&lt;b&gt;Big Endian&lt;/b&gt;&amp;nbsp;등의 바이트 오더가 존재한다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;네트워크에서는 Big Endian을 사용하고 대부분의 프로세서는 Little Endian을 사용한다. 두 엔디안의 차이는 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 51px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;종류&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0x1234 표현(2바이트 표현)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0x12345678 표현(4바이트 표현)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Big Endian (빅 엔디안)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 12 34 XX XX XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 12 34 56 78 XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Little Endian (리틀 엔디안)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 34 12 XX XX XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 17px; text-align: left;&quot;&gt;&lt;code&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;01 02 03 04 05 06 07 08&lt;br /&gt;00000000 78 56 34 12 XX XX XX XX&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;figure id=&quot;og_1664448072614&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;[Network] 네트워크 바이트 오더 (Network Byte Order)&quot; data-og-description=&quot;바이트 오더(Byte Order) 네트워크 바이트 오더를 설명하기 전에 바이트 오더에 대해 먼저 설명해야 한다. 바이트 오더란 컴퓨터 메모리에 바이트가 저장되는 순서를 바이트 오더라고 부른다. 바이&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/116&quot; data-og-url=&quot;https://crazyhacker.tistory.com/116&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmWhri/hyPXN9UgPm/zuOsNM25bJpDiLj6rKgmRk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/ePc2Z/hyPWJOO4sK/bRUR8j982wKevpzrliA3K1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/46aIi/hyPXF45Ynq/GgNn8vcD5H2kHtKTAJh8h1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/116&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/116&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmWhri/hyPXN9UgPm/zuOsNM25bJpDiLj6rKgmRk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/ePc2Z/hyPWJOO4sK/bRUR8j982wKevpzrliA3K1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/46aIi/hyPXF45Ynq/GgNn8vcD5H2kHtKTAJh8h1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Network] 네트워크 바이트 오더 (Network Byte Order)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;바이트 오더(Byte Order) 네트워크 바이트 오더를 설명하기 전에 바이트 오더에 대해 먼저 설명해야 한다. 바이트 오더란 컴퓨터 메모리에 바이트가 저장되는 순서를 바이트 오더라고 부른다. 바이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주요 함수&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ntohs&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;code&gt;ntohs(&lt;b&gt;N&lt;/b&gt;etwork byte order &lt;b&gt;TO&lt;/b&gt; &lt;b&gt;H&lt;/b&gt;ost byte order &lt;b&gt;S&lt;/b&gt;hort)&lt;/code&gt; 함수는 2바이트 데이터를 네트워크 바이트 오더에서 호스트 바이트 오더로 변환하는 함수이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1664448149657&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;unsigned short Data = ntohs(NetworkByteOrderData);&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예제 코드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예제 코드는 이전 포스팅에서 제작한 패킷 캡쳐 프로그램에서 기능을 추가했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1664448496191&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;pcap.h&amp;gt;

typedef struct _NETWORK_ETHERNET_HEADER
{
    unsigned char Destination[6];
    unsigned char Source[6];
    unsigned short Type; // You need to change the byte order.
} NETWORK_ETHERNET_HEADER, *PNETWORK_ETHERNET_HEADER;

int main(int argc, char *argv[])
{
    if (argc &amp;lt; 2)
    {
        printf(&quot;Usage: %s [interface]\n&quot;, argv[0]);
        return -1;
    }
    
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *pcap = pcap_open_live(argv[1], BUFSIZ, 1, 1000, errbuf);

    if (pcap == NULL)
    {
        fprintf(stderr, &quot;pcap_open_live(%s) return null - %s\n&quot;, argv[1], errbuf);
        return -1;
    }

    while (1)
    {
        struct pcap_pkthdr* header;
        const unsigned char *packet;
        int res = pcap_next_ex(pcap, &amp;amp;header, &amp;amp;packet);
        if (res == 0) continue;
        if (res == PCAP_ERROR || res == PCAP_ERROR_BREAK)
        {
            printf(&quot;pcap_next_ex return %d(%s)\n&quot;, res, pcap_geterr(pcap));
			break;
        }
        
        NETWORK_ETHERNET_HEADER *Ethernet = packet;
        Ethernet-&amp;gt;Type = ntohs(Etherent-&amp;gt;Type);
        
        printf(&quot;[Destination] : &quot;);
        for (int i = 0; i &amp;lt; 6; i++)
        {
            printf(&quot;%02X &quot;, Ethernet-&amp;gt;Destination[i]);
        }
        putchar('\n');

        printf(&quot;[Source] : &quot;);
        for (int i = 0; i &amp;lt; 6; i++)
        {
            printf(&quot;%02X &quot;, Ethernet-&amp;gt;Source[i]);
        }
        putchar('\n');
        
        printf(&quot;[EthernetType] : 0x%04X\n&quot;, Ethernet-&amp;gt;Type);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1664448897125&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ifconfig
ens33: flags=4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt;  mtu 1500
		...

$ sudo ./main ens33
[Destination] : 00 50 56 FC 50 1D 
[Source] : 00 0C 29 7A 5F 24 
[EthernetType] : 0800
...&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C/pcap</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/114</guid>
      <comments>https://crazyhacker.tistory.com/114#entry114comment</comments>
      <pubDate>Wed, 28 Sep 2022 21:57:06 +0900</pubDate>
    </item>
    <item>
      <title>[C] pcap로 네트워크 패킷 캡쳐하기</title>
      <link>https://crazyhacker.tistory.com/113</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;pcap이란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;pcap&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;(&lt;b&gt;p&lt;/b&gt;acket &lt;b&gt;cap&lt;/b&gt;ture)는 네트워크 프로그래밍을 위한 라이브러리다. 유닉스 계열의 운영 체제들은 libpcap 라이브러리에&amp;nbsp; pcap이 포함되어 있어 libpcap을 이용해 네트워크 프로그래밍을 할 수 있다. &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;&lt;span style=&quot;color: #333333;&quot;&gt;윈도우는 WinPcap이라고 하는 libpcap의 포팅된 버전을 사용한다.&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;네트워크의 패킷들을 잡을 수 있으며 일반적으로는 볼수 없는 헤더들의 데이터도 모두 캡처하여 볼 수 있다. pcap API는 C언어로 작성되어 있어 여러 언어에서 사용할 수 있다는 장점이 있다. (해당 블로그에서는 Unix 계열의 운영 체제들을 기준으로 실습한다)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libpcap 설치하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;블로그에서는 Ubuntu와 Kali Linux에서 프로그래밍 실습을 진행한다. 해당 운영 체제에는 기본적으로 libpcap 라이브러리가 설치되어 있지 않기 때문에 패키지 매니저를 통한 라이브러리 설치가 필요하다. 다음 명령어로 설치할 수 있다.&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;libpcap를 사용하기 위해서는 &lt;code&gt;pcap.h&lt;/code&gt; 헤더 파일을 사용하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1663871008518&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ sudo apt-get update
$ sudo apt-get install libpcap-dev&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;891&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEqLjQ/btrMPOrl46b/a0gEnEoexm7BsR7iBub70K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEqLjQ/btrMPOrl46b/a0gEnEoexm7BsR7iBub70K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEqLjQ/btrMPOrl46b/a0gEnEoexm7BsR7iBub70K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEqLjQ%2FbtrMPOrl46b%2Fa0gEnEoexm7BsR7iBub70K%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;891&quot; height=&quot;485&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주요 함수&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;code&gt;pcap_open_live&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;pcap_open_live&lt;/code&gt; 함수는 네트워크 인터페이스를 오픈하는 함수이다. 해당 함수는 &lt;code&gt;pcap_t*&lt;/code&gt; 핸들을 반환하고 반환된 핸들을 사용해 패킷 캡쳐, 전송 등 작업을 수행할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1663871500726&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *pcap = pcap_open_live(&quot;eth0&quot;, BUFSIZ, 1, 1000, errbuf);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;code&gt;pcap_close&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;pcap_close&lt;/code&gt; 함수는 오픈한 네트워크 인터페이스 핸들을 닫아주는 함수이다. 네트워크 인터페이스를 오픈한 상태로 있다면 해당 인터페이스를 프로세스가 계속 점유하고 있기 때문에 사용하지 않을 때에는 반드시 닫아주어야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1663871601712&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pcap_close(pcap);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;code&gt;pcap_next_ex&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;pcap_next_ex&lt;/code&gt; 함수는 네트워크 인터페이스로부터 패킷을 캡쳐하는 함수이다. 캡처된 패킷은 TCP 프로토콜의 경우 Ethernet, IP, TCP 등 모든 헤더와 데이터를 반환한다. 실제 반환되는 값으로는 함수의 성공 또는 실패 여부를 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1663871748627&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct pcap_pkthdr {
    struct timeval ts;	/* time stamp */
    bpf_u_int32 caplen;	/* length of portion present */
    bpf_u_int32 len;	/* length this packet (off wire) */
};

struct pcap_pkthdr *header;
const unsigned char *packet;
int res = pcap_next_ex(pcap, &amp;amp;header, &amp;amp;packet);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;header&lt;/code&gt;에는 해당 패킷 캡쳐된 시간과 길이가 저장되어 있으며 &lt;code&gt;packet&lt;/code&gt;에는 캡쳐된 패킷의 헤더들과 데이터의 정보가 담겨 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예제 코드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제 코드는 캡쳐되는 모든 패킷들의 바이트 수를 출력하는 프로그램이다. 프로그램 실행 시에 인자로 패킷을 캡처할 네트워크 인터페이스의 이름을 넣어주면 동작한다.&lt;/p&gt;
&lt;pre id=&quot;code_1663871247526&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;pcap.h&amp;gt;

int main(int argc, char *argv[])
{
    if (argc &amp;lt; 2)
    {
        printf(&quot;Usage: %s [interface]\n&quot;, argv[0]);
        return -1;
    }
    
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *pcap = pcap_open_live(argv[1], BUFSIZ, 1, 1000, errbuf);

    if (pcap == NULL)
    {
        fprintf(stderr, &quot;pcap_open_live(%s) return null - %s\n&quot;, &quot;ens33&quot;, errbuf);
        return -1;
    }

    while (1)
    {
        struct pcap_pkthdr* header;
        const unsigned char *packet;
        int res = pcap_next_ex(pcap, &amp;amp;header, &amp;amp;packet);
        if (res == 0) continue;
        if (res == PCAP_ERROR || res == PCAP_ERROR_BREAK)
        {
            printf(&quot;pcap_next_ex return %d(%s)\n&quot;, res, pcap_geterr(pcap));
			break;
        }
        printf(&quot;%d bytes captured\n&quot;, header-&amp;gt;caplen);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1663872035758&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ ifconfig
ens33: flags=4163&amp;lt;UP,BROADCAST,RUNNING,MULTICAST&amp;gt;  mtu 1500
        ...

$ sudo ./main ens33
60 60 bytes captured
98 98 bytes captured
98 98 bytes captured
98 98 bytes captured
98 98 bytes captured
...&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C/pcap</category>
      <category>C언어 패킷캡쳐</category>
      <category>Network Programming</category>
      <category>Packet</category>
      <category>packet capture</category>
      <category>PCAP</category>
      <category>pcap packet</category>
      <category>pcap packet capture</category>
      <category>네트워크 프로그래밍</category>
      <category>패킷</category>
      <category>패킷 캡쳐</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/113</guid>
      <comments>https://crazyhacker.tistory.com/113#entry113comment</comments>
      <pubDate>Fri, 23 Sep 2022 03:42:37 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Windows 10 Kernel Debugging 환경 준비</title>
      <link>https://crazyhacker.tistory.com/112</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Install WinDbg&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;윈도우 커널 디버깅은 우리가 일반적으로 알고 있는 x64dbg와 같은 디버거로는 디버깅할 수 없다. 윈도우에서 제작한 WinDbg를 사용해 디버깅할 수 있다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;기본적으로 WinDbg는 두 종류가 있는데 하나는 SDK에서 설치할 수 있는 디버거와 Microsoft Store에서 다운로드할 수 있는 디버거이다. 본문에서는 Microsoft Store에 있는 WinDbg Preview를 기준으로 설명하겠다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&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;&lt;span style=&quot;color: #333333;&quot;&gt;WinDbg Preview는 Microsoft Store에서 &quot;Windbg&quot; 키워드로 검색하면 바로 다운로드 받을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsW1uF/btrMzPFOnkt/k57bKHDzQyW2KSj7goO6R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsW1uF/btrMzPFOnkt/k57bKHDzQyW2KSj7goO6R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsW1uF/btrMzPFOnkt/k57bKHDzQyW2KSj7goO6R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsW1uF%2FbtrMzPFOnkt%2Fk57bKHDzQyW2KSj7goO6R1%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;1202&quot; height=&quot;998&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;998&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Set the symbol path and server&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이제 디버거의 심볼 패스와 서버를 설정해야 한다. 윈도우 커널을 디버깅하면서 필요한 디버깅 심볼들이 필요하기 때문이다. 디버깅 심볼이 존재하지 않으면 그건 윈도우 자체를 아무것도 없이 리버싱하는 것과 마찬가지다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2065&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDKryh/btrMDDKSzwM/ikcPD4FevZkLzSCGiTrDgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDKryh/btrMDDKSzwM/ikcPD4FevZkLzSCGiTrDgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDKryh/btrMDDKSzwM/ikcPD4FevZkLzSCGiTrDgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDKryh%2FbtrMDDKSzwM%2FikcPD4FevZkLzSCGiTrDgK%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;2065&quot; height=&quot;801&quot; data-origin-width=&quot;2065&quot; data-origin-height=&quot;801&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;1099&quot; data-origin-height=&quot;903&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMbFyj/btrMEg9Ayww/YmgLHNb0484DBa2tQ8qxg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMbFyj/btrMEg9Ayww/YmgLHNb0484DBa2tQ8qxg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMbFyj/btrMEg9Ayww/YmgLHNb0484DBa2tQ8qxg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMbFyj%2FbtrMEg9Ayww%2FYmgLHNb0484DBa2tQ8qxg1%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;1099&quot; height=&quot;903&quot; data-origin-width=&quot;1099&quot; data-origin-height=&quot;903&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[파일] -&amp;gt; [Settings] -&amp;gt; [Debugging settings] -&amp;gt; [Default symbol path]&lt;/code&gt;를 &lt;code&gt;SRV*c:\dbgsymbols*http://msdl.microsoft.com/download/symbols&lt;/code&gt;로 설정하면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Set the Windows Debug Mode&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이제 윈도우를 디버그 모드로 부팅할 수 있도록 설정해줘야 한다. 다음과 같은 절차를 따라오면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1663680141348&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bcdedit /dbgsettings net hostip:192.168.64.135 port:50000 /* 포트는 자유이지만 대개 50000를 쓰는 듯 하다 */
bcdedit /set bootmenupolicy legacy
bcdedit /copy {current} /d &quot;Windows 10 [Debug, F8]&quot;
bcdedit /debug {GUID} on /* {GUID}는 위 명령어를 입력시 출력됨 */&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rqT0b/btrMCHHqzsr/aZl89YVEiLXVu0jctalkk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rqT0b/btrMCHHqzsr/aZl89YVEiLXVu0jctalkk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rqT0b/btrMCHHqzsr/aZl89YVEiLXVu0jctalkk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrqT0b%2FbtrMCHHqzsr%2FaZl89YVEiLXVu0jctalkk0%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;979&quot; height=&quot;512&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP, Port, Key를 WinDbg에 입력하고 [OK] 버튼을 클릭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/umPMx/btrMDXPSSEv/yfbEm8AyaMe7ZXq31CLc60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/umPMx/btrMDXPSSEv/yfbEm8AyaMe7ZXq31CLc60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/umPMx/btrMDXPSSEv/yfbEm8AyaMe7ZXq31CLc60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FumPMx%2FbtrMDXPSSEv%2FyfbEm8AyaMe7ZXq31CLc60%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;886&quot; height=&quot;693&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;693&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[OK] 버튼을 클릭하면 아래 사진과 같이 IPv4를 사용하여 커널 디버깅을 위해 클라이언트가 연결될 때까지 대기하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIpryO/btrMDpzudgU/1QVFmTE6cSkplGfredsKG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIpryO/btrMDpzudgU/1QVFmTE6cSkplGfredsKG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIpryO/btrMDpzudgU/1QVFmTE6cSkplGfredsKG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIpryO%2FbtrMDpzudgU%2F1QVFmTE6cSkplGfredsKG1%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;886&quot; height=&quot;693&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;693&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Windows &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Booting the &lt;/b&gt;&lt;/span&gt;Debug Mode&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Windbg가 커널 디버깅을 위해 대기중이라면 디버그 모드를 설정했던 윈도우를 재부팅시켜준다. 그럼 이번엔 아래와 같은 부팅화면을 볼수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sqlLL/btrMEtOxXAx/tOkk7KunFq0dIGQFow61Hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sqlLL/btrMEtOxXAx/tOkk7KunFq0dIGQFow61Hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sqlLL/btrMEtOxXAx/tOkk7KunFq0dIGQFow61Hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsqlLL%2FbtrMEtOxXAx%2FtOkk7KunFq0dIGQFow61Hk%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;960&quot; height=&quot;750&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 우리가 새롭게 추가한 부팅 옵션을 선택하고 F8 키를 눌러준다. 여기에서 디버깅 모드를 선택하면 자동으로 디버깅 모드로 부팅된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KvjcU/btrMCH1JGmy/zsQurdb3HCvoK655yzYF31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KvjcU/btrMCH1JGmy/zsQurdb3HCvoK655yzYF31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KvjcU/btrMCH1JGmy/zsQurdb3HCvoK655yzYF31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKvjcU%2FbtrMCH1JGmy%2FzsQurdb3HCvoK655yzYF31%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;960&quot; height=&quot;750&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;750&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 정상적으로 설정하였다면 디버깅 모드로 부팅을 선택한 후 대기하다보면 WinDbg가 연결되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Success Windows Kernel Debugging (Attack to Kernel)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctss5u/btrMA5V21Is/BrkrHxJZKyRNLcwdGxKpy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctss5u/btrMA5V21Is/BrkrHxJZKyRNLcwdGxKpy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctss5u/btrMA5V21Is/BrkrHxJZKyRNLcwdGxKpy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fctss5u%2FbtrMA5V21Is%2FBrkrHxJZKyRNLcwdGxKpy0%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;2560&quot; height=&quot;1400&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1400&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>Windows/Windows Kernel Driver</category>
      <category>Debug</category>
      <category>debugging</category>
      <category>Windows</category>
      <category>Windows Kernel</category>
      <category>Windows Kernel Debug</category>
      <category>windows kernel debugging</category>
      <category>디버깅</category>
      <category>윈도우</category>
      <category>윈도우 커널</category>
      <category>윈도우 커널 디버깅</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/112</guid>
      <comments>https://crazyhacker.tistory.com/112#entry112comment</comments>
      <pubDate>Tue, 20 Sep 2022 22:34:13 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Windows Kernel Driver 개발 환경 준비</title>
      <link>https://crazyhacker.tistory.com/111</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Install Visual Studio&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Visual Studio Code와 Mingw(GCC)를 활용해서도 윈도우 커널 드라이버 개발을 할 수 있지만, Visual Studio에서 개발하는 편이 훨씬 간편하다고 생각한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 개발할 윈도우 버전 선택&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 커널 드라이버는 하위 호환성은 지켜지지만 상위 호환성은 지켜지지 않는다. 그렇기에 자신이 개발할 드라이버의 대상이 되는 윈도우 버전을 잘 선택해야 한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;하위 호환성 : Windows 7 드라이버를 Windows 10에서 실행&lt;br /&gt;상위 호환성 : Windows 10 드라이버를 Windows 7에서 실행&lt;/blockquote&gt;
&lt;figure id=&quot;og_1661174147006&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;이전 WDK 버전 및 기타 다운로드 - Windows drivers&quot; data-og-description=&quot;WDK(Windows 드라이버 키트), Windows 디버거(WinDBG) 등을 설치합니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/j6mzo/hyPxmMm5B7/RK6hcw6oKeTkWl88F3pxDK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/j6mzo/hyPxmMm5B7/RK6hcw6oKeTkWl88F3pxDK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;이전 WDK 버전 및 기타 다운로드 - Windows drivers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WDK(Windows 드라이버 키트), Windows 디버거(WinDBG) 등을 설치합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 페이지에서 내가 개발하려는 윈도우의 버전에 맞춰서 Visual Studio를 설치하길 바란다. 개인적으로는 Visual Studio 2019를 추천한다. 현재 기준 최신버전 Visual Studio 2022 버전은 윈도우 커널 드라이버를 개발하는 적합하지 않고 오류도 발생한다.&lt;/p&gt;
&lt;figure id=&quot;og_1661174297658&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;Thank you for downloading Visual Studio - Visual Studio&quot; data-og-description=&quot;New to Visual Studio? Learning a new development tool can be overwhelming. Take this step-by-step learning journey at your own pace to successfully create a simple app in any language of your choice. Let&amp;rsquo;s get started! First please make sure to open your&quot; data-og-host=&quot;visualstudio.microsoft.com&quot; data-og-source-url=&quot;https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&amp;amp;rel=16&quot; data-og-url=&quot;https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bIeY9R/hyPxjhN1Zv/SOjsNHdbhW0DKpNAg4lqo1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/pz3Au/hyPxph2TIu/C8Co9XlZEPa0fcfPCWROc0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/biGkDN/hyPxgZI2Zi/VLQvQSsCXLeBg7gEMKNiV1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot;&gt;&lt;a href=&quot;https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&amp;amp;rel=16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&amp;amp;rel=16&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bIeY9R/hyPxjhN1Zv/SOjsNHdbhW0DKpNAg4lqo1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/pz3Au/hyPxph2TIu/C8Co9XlZEPa0fcfPCWROc0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512,https://scrap.kakaocdn.net/dn/biGkDN/hyPxgZI2Zi/VLQvQSsCXLeBg7gEMKNiV1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720');&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;Thank you for downloading Visual Studio - Visual Studio&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;New to Visual Studio? Learning a new development tool can be overwhelming. Take this step-by-step learning journey at your own pace to successfully create a simple app in any language of your choice. Let&amp;rsquo;s get started! First please make sure to open your&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;visualstudio.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio 2019는 위 링크에서 다운로드 받을 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. Windows SDK 설치&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Visual Studio를 설치하면 워크로드에서 &lt;code&gt;[C++를 사용한 데스크톱 개발]&lt;/code&gt; 를 선택한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;764&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbeEme/btrKetZqp8e/8QWvkHRxnasY6MfHqw8McK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbeEme/btrKetZqp8e/8QWvkHRxnasY6MfHqw8McK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbeEme/btrKetZqp8e/8QWvkHRxnasY6MfHqw8McK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbeEme%2FbtrKetZqp8e%2F8QWvkHRxnasY6MfHqw8McK%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;1353&quot; height=&quot;764&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;764&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;code&gt;[개별 구성 요소] -&amp;gt; [Windows 10 SDK(원하는 버전)]&lt;/code&gt; 을 선택해준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wCeS7/btrKloWnyrD/3wDVhe2rHOU8RaGXV1oPd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wCeS7/btrKloWnyrD/3wDVhe2rHOU8RaGXV1oPd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wCeS7/btrKloWnyrD/3wDVhe2rHOU8RaGXV1oPd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwCeS7%2FbtrKloWnyrD%2F3wDVhe2rHOU8RaGXV1oPd0%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;1357&quot; height=&quot;766&quot; data-origin-width=&quot;1357&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Install Windows Driver Kit (WDK)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Visual Studio에서 SDK까지 모두 설치가 끝났다면 이제 Windows Driver Kit (WDK)를 설치해야 한다. 본인이 설치했던 SDK와 같은 버전의 WDK를 설치해야 한다. 다음 사이트에서 SDK 버전별로 윈도우 버전을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1661175019439&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Windows SDK 및 에뮬레이터 보관&quot; data-og-description=&quot;이전 버전의 Windows 및 Windows Phone 플랫폼에서 개발을 위해 이전 Windows SDK 및 에뮬레이터 릴리스를 다운로드하여 설치합니다.&quot; data-og-host=&quot;developer.microsoft.com&quot; data-og-source-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/sdk-archive/&quot; data-og-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/sdk-archive/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pfa97/hyPxgFq1S3/HkZgF7TssBWSjjOpUWrrg1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/sdk-archive/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/sdk-archive/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pfa97/hyPxgFq1S3/HkZgF7TssBWSjjOpUWrrg1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Windows SDK 및 에뮬레이터 보관&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전 버전의 Windows 및 Windows Phone 플랫폼에서 개발을 위해 이전 Windows SDK 및 에뮬레이터 릴리스를 다운로드하여 설치합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버전을 확인하고 다음 사이트에서 해당 버전에 맞는 WDK를 설치해준다.&lt;/p&gt;
&lt;figure id=&quot;og_1661175054191&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;이전 WDK 버전 및 기타 다운로드 - Windows drivers&quot; data-og-description=&quot;WDK(Windows 드라이버 키트), Windows 디버거(WinDBG) 등을 설치합니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/j6mzo/hyPxmMm5B7/RK6hcw6oKeTkWl88F3pxDK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/windows-hardware/drivers/other-wdk-downloads&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/j6mzo/hyPxmMm5B7/RK6hcw6oKeTkWl88F3pxDK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;이전 WDK 버전 및 기타 다운로드 - Windows drivers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WDK(Windows 드라이버 키트), Windows 디버거(WinDBG) 등을 설치합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;987&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Np311/btrKmFi06Li/8NYrTrR43eka5yQmXASwwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Np311/btrKmFi06Li/8NYrTrR43eka5yQmXASwwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Np311/btrKmFi06Li/8NYrTrR43eka5yQmXASwwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNp311%2FbtrKmFi06Li%2F8NYrTrR43eka5yQmXASwwK%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;967&quot; height=&quot;987&quot; data-origin-width=&quot;967&quot; data-origin-height=&quot;987&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Finish&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 Visual Studio 프로젝트 만들기에 Empty WDM Driver 라는 템플릿이 생성되었다면 성공적으로 윈도우 커널 드라이버 개발 환경이 준비된 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo03Ea/btrKks50tIC/Uos9AYpyGg5p1cRaFwEFXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo03Ea/btrKks50tIC/Uos9AYpyGg5p1cRaFwEFXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo03Ea/btrKks50tIC/Uos9AYpyGg5p1cRaFwEFXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo03Ea%2FbtrKks50tIC%2FUos9AYpyGg5p1cRaFwEFXK%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;1024&quot; height=&quot;680&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Windows/Windows Kernel Driver</category>
      <category>driver</category>
      <category>Windows Kernel</category>
      <category>Windows Kernel Driver</category>
      <category>개발 환경 준비</category>
      <category>개발하기</category>
      <category>드라이버</category>
      <category>윈도우 커널</category>
      <category>윈도우 커널 드라이버</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/111</guid>
      <comments>https://crazyhacker.tistory.com/111#entry111comment</comments>
      <pubDate>Mon, 22 Aug 2022 12:04:39 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Instrumentation Callback 응용하기 - syscall detect</title>
      <link>https://crazyhacker.tistory.com/110</link>
      <description>&lt;figure id=&quot;og_1662650744203&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Instrumentation-Callback&quot; data-og-description=&quot;Contribute to jungjin0003/Instrumentation-Callback development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-og-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dLxLPn/hyPJSpAuUv/PtMhQfdnDBdJaWDfFgvaS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-source-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dLxLPn/hyPJSpAuUv/PtMhQfdnDBdJaWDfFgvaS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Instrumentation-Callback&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to jungjin0003/Instrumentation-Callback development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Instrumentation Callback을 통해 알 수 있는 것&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지의 포스팅만 봤을 때 Instrumentation Callback은 그저 syscall 어셈블리가 실행되었다는 정보 밖에 알 수 없었다. 하지만 Instrumentation Callback은 그 외에도 아래와 같은 정보들을 구할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; margin-top: 14px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Original Return Address (sysret 가 되었을 때 원래 돌아가야 할 주소)&lt;/li&gt;
&lt;li&gt;Syscall Number&lt;/li&gt;
&lt;li&gt;Function Name&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How Do I Get The Above Information?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instrumentation Callback으로 등록된 함수가 호출되었을 때 r10 레지스터에는 원래 돌아가야 할 리턴 주소가 기록되어 있다. 이를 보고 어떠한 커널 함수를 호출했는지 알아낼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTcM6w/btrJD30B6yh/F1KVG9Dkzkvkq0c3fD0ZYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTcM6w/btrJD30B6yh/F1KVG9Dkzkvkq0c3fD0ZYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTcM6w/btrJD30B6yh/F1KVG9Dkzkvkq0c3fD0ZYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTcM6w%2FbtrJD30B6yh%2FF1KVG9Dkzkvkq0c3fD0ZYK%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;1280&quot; height=&quot;717&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What is The Syscall Detect?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결국 tracking와 크게 다를게 없다. 하지만 이번 응용하기에서 다른점은 syscall instruction을 호출한 주소가 실제 ntdll.dll 또는 win32u.dll가 아니라면 프로그램 실행을 중지하는 원리이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Sample&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1660564735103&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

#pragma comment (lib, &quot;ntdll.lib&quot;)

#define PROCESS_INFO_CLASS_INTRUMENTATION 40
#define RIP_SANITY_CHECK(Rip,BaseAddress,ModuleSize) (Rip &amp;gt; BaseAddress) &amp;amp;&amp;amp; (Rip &amp;lt; (BaseAddress + ModuleSize))

NTSYSAPI NTSTATUS NTAPI NtSetInformationProcess(HANDLE ProcessHandle, PROCESS_INFORMATION_CLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength);

#ifdef __GUNC__
__declspec(naked) NTSTATUS SystemCall(ULONG number)
{
    __asm__ __volatile__ (&quot;mov rax, r10&quot;);
    __asm__ __volatile__ (&quot;syscall&quot;);
    __asm__ __volatile__ (&quot;ret&quot;);
}
#elif _MSC_VER
extern PVOID GetSyscallReturnAddress();
extern NTSTATUS SystemCall(ULONG number);
#endif

typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
    ULONG Version;
    ULONG Reserved;
    PVOID Callback;
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;

VOID CALLBACK InstrumentationCallback()
{
    static HANDLE NtdllBase;
    static HANDLE Win32uBase;
    
    PVOID ReturnAddress = NULL;

#ifdef __GNUC__
    __asm__ __volatile__ (
        &quot;mov %[ReturnAddress], r10\n\t&quot;
        :
        : [ReturnAddress] &quot;m&quot; (ReturnAddress)
    );
#elif _MSC_VER
    ReturnAddress = GetSyscallReturnAddress();
#else
#error This compiler is not supported. Please checck the compiler or target OS
#endif

    if (NtdllBase == NULL)
        NtdllBase = GetModuleHandleA(&quot;ntdll.dll&quot;);

    if (Win32uBase == NULL)
        Win32uBase = GetModuleHandleA(&quot;win32u.dll&quot;);

    DWORD NtdllSize = ((IMAGE_NT_HEADERS *)((ULONG_PTR)NtdllBase + ((IMAGE_DOS_HEADER *)NtdllBase)-&amp;gt;e_lfanew))-&amp;gt;OptionalHeader.SizeOfImage;
    DWORD Win32uSize = Win32uBase == NULL ? 0 : ((IMAGE_NT_HEADERS *)((ULONG_PTR)Win32uBase + ((IMAGE_DOS_HEADER *)Win32uBase)-&amp;gt;e_lfanew))-&amp;gt;OptionalHeader.SizeOfImage;

    if (!(RIP_SANITY_CHECK(ReturnAddress, (ULONG_PTR)NtdllBase, NtdllSize)) || (Win32uBase != NULL &amp;amp;&amp;amp; !(RIP_SANITY_CHECK(ReturnAddress, (ULONG_PTR)Win32uBase, Win32uSize))))
    {
        printf(&quot;[SYSCALL-DETECT] Kernel returns to unverified module, preventing further execution!\n&quot;);
        __debugbreak();
    }

    return;
}

int main(int argc, char *argv[])
{
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION nirvana;
    nirvana.Version = 0;
    nirvana.Reserved = 0;
    nirvana.Callback = InstrumentationCallback;

    NtSetInformationProcess(GetCurrentProcess(), PROCESS_INFO_CLASS_INTRUMENTATION, &amp;amp;nirvana, sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION));
    SystemCall(0x46); // NtYieldExecution

    printf(&quot;[SYSTEM] Successfully executed the syscall instruction\n&quot;);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSVC 컴파일용 어셈블리&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1660564816810&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;; File : extern.asm
_TEXT SEGMENT

PUBLIC GetSyscallReturnAddress
PUBLIC SystemCall

GetSyscallReturnAddress PROC
    mov rax, r10
    ret
GetSyscallReturnAddress ENDP

SystemCall PROC
    mov rax, rcx
    syscall
    ret
SystemCall ENDP

_TEXT ENDS

END&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1660564841087&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;=====GCC=====
CommandLine : gcc.exe main.c -o main.exe -lntdll -masm=intel
=====MSVC====
CommandLine : ml64.exe /c extern.asm =&amp;gt; result : extern.obj
CommandLink : cl.exe main.c extern.obj /Od /Z7 /link /MANIFEST:NO /DEBUG:FULL /OPT:REF /OPT:ICF /OPT:LBR&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 결과&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1660564887161&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ main.exe
[SYSCALL-DETECT] Kernel returns to unverified module, preventing further execution!&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1661178570008&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;Detecting Manual Syscalls from User Mode - Winternl&quot; data-og-description=&quot;By now direct system calls are ubiquitous in offensive tooling. Manual system calls remain effective for evading userland based EDRs. From within userland, there has been little answer to this powerful technique. Such syscalls can be effectively mitigated &quot; data-og-host=&quot;winternl.com&quot; data-og-source-url=&quot;https://winternl.com/detecting-manual-syscalls-from-user-mode/&quot; data-og-url=&quot;https://winternl.com/detecting-manual-syscalls-from-user-mode/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://winternl.com/detecting-manual-syscalls-from-user-mode/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://winternl.com/detecting-manual-syscalls-from-user-mode/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Detecting Manual Syscalls from User Mode - Winternl&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;By now direct system calls are ubiquitous in offensive tooling. Manual system calls remain effective for evading userland based EDRs. From within userland, there has been little answer to this powerful technique. Such syscalls can be effectively mitigated&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;winternl.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;</description>
      <category>Windows/Instrumentation Callback</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/110</guid>
      <comments>https://crazyhacker.tistory.com/110#entry110comment</comments>
      <pubDate>Mon, 15 Aug 2022 06:50:46 +0900</pubDate>
    </item>
    <item>
      <title>Visual Studio 컴파일러에서 msvcrt.dll 사용하기</title>
      <link>https://crazyhacker.tistory.com/109</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Visual Studio의 MSVC로 컴파일을 진행하면 vcruntime140.dll, ucrtbase.dll을 사용하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IfFnp/btrJlOwBJFF/KkAvsbBT30ynMKDUt81hSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IfFnp/btrJlOwBJFF/KkAvsbBT30ynMKDUt81hSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IfFnp/btrJlOwBJFF/KkAvsbBT30ynMKDUt81hSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIfFnp%2FbtrJlOwBJFF%2FKkAvsbBT30ynMKDUt81hSk%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;1004&quot; height=&quot;737&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 Windows SDK에 있는 라이브러리를 사용하는 것으로 알고 있는데, 해당 DLL을 사용하면 다른 윈도우에서 프로그램을 실행했을 때 ucrtbase.dll과 vcruntime140.dll이 없으면 프로그램이 동작하지 않는 문제가 발생한다.&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;물론 프로그램을 배포할 때 DLL을 함께 배포하면 문제 없지만 이는 반드시 프로그램을 실행하기 전에 DLL을 배포해야 한다는 귀찮음이 존재한다. 하지만 모든 윈도우에는 기본적으로 msvcrt.dll이 존재하고 msvcrt.dll과 ucrtbase.dll, vcruntime140.dll에 있는 함수가 다르지 않다. 버전의 차이로만 알고 있다. 그렇기 때문에 컴파일과 링킹 과정에서 이 두 DLL대신 msvcrt.dll을 사용하면 문제 없이 모든 윈도우에서 사용할 수 있다.&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;먼저 msvcrt.lib 파일을 다운로드 받아야 한다. 기본적으로 포함은 되어 있지만 확인해보니 그냥 껍데기만 있는 파일이라 실제로 사용할 수 있는 msvcrt.lib를 다운로드 받아야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/OcjYZ/btrJswAuAfl/jKtMbHT5z2Qf3iWftiH4Q0/MSVCRT.zip?attach=1&amp;amp;knm=tfile.zip&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;MSVCRT.zip&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;2.29MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S5ga4/btrJrQsshXY/YXclcrj9Nw23ipO3QeBoGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S5ga4/btrJrQsshXY/YXclcrj9Nw23ipO3QeBoGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S5ga4/btrJrQsshXY/YXclcrj9Nw23ipO3QeBoGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS5ga4%2FbtrJrQsshXY%2FYXclcrj9Nw23ipO3QeBoGk%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;890&quot; height=&quot;616&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[프로젝트 속성] -&amp;gt; [링커] -&amp;gt; [입력] -&amp;gt; [특정 기본 라이브러리 무시] -&amp;gt; libcmt.lib, msvcprt.lib 추가&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmqv85/btrJrRx8t4n/j1CUkvCsUgpD0XGdc2rdHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmqv85/btrJrRx8t4n/j1CUkvCsUgpD0XGdc2rdHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmqv85/btrJrRx8t4n/j1CUkvCsUgpD0XGdc2rdHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcmqv85%2FbtrJrRx8t4n%2Fj1CUkvCsUgpD0XGdc2rdHk%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;902&quot; height=&quot;626&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;626&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[프로젝트 속성] -&amp;gt; [링커] -&amp;gt; [입력] -&amp;gt; [추가 종속성] -&amp;gt; msvcrt.lib 추가&lt;/code&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;이렇게 추가해주면 msvcrt.dll 가 링크되어 msvcrt.dll을 사용할 수 있게된다.&lt;/p&gt;</description>
      <category>내 노가다 목록</category>
      <category>apphelp.dll</category>
      <category>Msvcrt.dll</category>
      <category>ucrtbase.dll</category>
      <category>vcruntime.dll</category>
      <category>vcruntime140.dll</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/109</guid>
      <comments>https://crazyhacker.tistory.com/109#entry109comment</comments>
      <pubDate>Thu, 11 Aug 2022 05:55:01 +0900</pubDate>
    </item>
    <item>
      <title>Visual Studio 컴파일할 때 쓸 때 없는 Reference 없애기</title>
      <link>https://crazyhacker.tistory.com/108</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio의 컴파일러인 MSVC로 컴파일을 하면 가끔 이런 이상한 코드가 추가되는 경우가 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;890&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2ECpm/btrJrP78Tja/Rsb3wfHSlWxk7CYZdJRst1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2ECpm/btrJrP78Tja/Rsb3wfHSlWxk7CYZdJRst1/img.png&quot; data-alt=&quot;모든 함수가 jmp 어셈블리로 호출되도록 이루어져 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2ECpm/btrJrP78Tja/Rsb3wfHSlWxk7CYZdJRst1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2ECpm%2FbtrJrP78Tja%2FRsb3wfHSlWxk7CYZdJRst1%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;977&quot; height=&quot;890&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;890&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모든 함수가 jmp 어셈블리로 호출되도록 이루어져 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지 처럼 모든 함수가 참조되어 있는 것을 확인할 수 있다. 그럼 해당 바이너리 내에서 호출하는 모든 함수들이 이 jmp를 거쳐서 호출되게 된다.&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;필자는 개인적으로 이걸 매우 싫어하는데 지금까지 이 때문에 Mingw를 애용했다고 해도 과언이 아니다. 하지만 이제야 해결 방법을 깨달았다. 이는 MSVC의 LINK의 최적화 옵션을 설정하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;591&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qsQGK/btrJreNQ3wy/SVnhYM8ocmjRFa4QYgLg0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qsQGK/btrJreNQ3wy/SVnhYM8ocmjRFa4QYgLg0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qsQGK/btrJreNQ3wy/SVnhYM8ocmjRFa4QYgLg0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqsQGK%2FbtrJreNQ3wy%2FSVnhYM8ocmjRFa4QYgLg0k%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;909&quot; height=&quot;591&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;591&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;[프로젝트 속성] -&amp;gt; [링커] -&amp;gt; [최적화] -&amp;gt; [참조] -&amp;gt; [/OPT:REF]&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 옵션을 설정해주면 저런 참조 코드가 생성되지 않는다. 커맨드 라인으로 한다면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;cl.exe main.c /link /OPT:REF&lt;/code&gt;&lt;/p&gt;</description>
      <category>내 노가다 목록</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/108</guid>
      <comments>https://crazyhacker.tistory.com/108#entry108comment</comments>
      <pubDate>Thu, 11 Aug 2022 05:11:45 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Instrumentation Callback 응용하기 - syscall tracking</title>
      <link>https://crazyhacker.tistory.com/107</link>
      <description>&lt;figure id=&quot;og_1662650732157&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Instrumentation-Callback&quot; data-og-description=&quot;Contribute to jungjin0003/Instrumentation-Callback development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-og-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dLxLPn/hyPJSpAuUv/PtMhQfdnDBdJaWDfFgvaS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot; data-source-url=&quot;https://github.com/jungjin0003/Instrumentation-Callback&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dLxLPn/hyPJSpAuUv/PtMhQfdnDBdJaWDfFgvaS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Instrumentation-Callback&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to jungjin0003/Instrumentation-Callback development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Instrumentation Callback을 통해 알 수 있는 것&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;지금까지의 포스팅만 봤을 때 Instrumentation Callback은 그저 syscall 어셈블리가 실행되었다는 정보 밖에 알 수 없었다. 하지만 Instrumentation Callback은 그 외에도 아래와 같은 정보들을 구할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Original Return Address (sysret 가 되었을 때 원래 돌아가야 할 주소)&lt;/li&gt;
&lt;li&gt;Syscall Number&lt;/li&gt;
&lt;li&gt;Function Name&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How Do I Get The Above Information?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Instrumentation Callback으로 등록된 함수가 호출되었을 때 r10 레지스터에는 원래 돌아가야 할 리턴 주소가 기록되어 있다. 이를 보고 어떠한 커널 함수를 호출했는지 알아낼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2493&quot; data-origin-height=&quot;1398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N9fvc/btrICP3x82q/dPZo6iQ8a18BtPJ0vGFoRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N9fvc/btrICP3x82q/dPZo6iQ8a18BtPJ0vGFoRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N9fvc/btrICP3x82q/dPZo6iQ8a18BtPJ0vGFoRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN9fvc%2FbtrICP3x82q%2FdPZo6iQ8a18BtPJ0vGFoRK%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;2493&quot; height=&quot;1398&quot; data-origin-width=&quot;2493&quot; data-origin-height=&quot;1398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Sample&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1659446959814&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

#pragma comment (lib, &quot;ntdll.lib&quot;)

#define PROCESS_INFO_CLASS_INSTRUMENTATION 40

typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
	ULONG Version;
	ULONG Reserved;
	PVOID Callback;
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, * PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;

#ifdef _MSC_VER
extern VOID GetInstrumentationCallbackData(PDWORD lpSyscallNumber, FARPROC *lpProcAddress);
#endif

VOID CALLBACK InstrumentationCallback()
{
    FARPROC Function = NULL;
	DWORD SystemCallNumber = 0;
#ifdef __GNUC__
    __asm__ __volatile__ (
        &quot;mov eax, dword ptr ds:[r10 - 0x10]\n\t&quot;
        &quot;mov %[SystemCallNumber], eax\n\t&quot;
        &quot;lea rax, qword ptr ds:[r10 - 0x14]\n\t&quot;
        &quot;mov %[Function], rax\n\t&quot;
        :
        : [SystemCallNumber] &quot;m&quot; (SystemCallNumber), [Function] &quot;m&quot; (Function)
    );
#elif _MSC_VER
    GetInstrumentationCallbackData(&amp;amp;SystemCallNumber, &amp;amp;Function);
#else
#error This compiler is not supported. Please checck the compiler or target OS
#endif
    ULONG_PTR ImageBase = GetModuleHandleA(&quot;ntdll.dll&quot;);
    IMAGE_EXPORT_DIRECTORY *EXPORT = ImageBase + ((IMAGE_NT_HEADERS *)(ImageBase + ((IMAGE_DOS_HEADER *)ImageBase)-&amp;gt;e_lfanew))-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

    printf(&quot;System Call Number : 0x%02x\n&quot;, SystemCallNumber);
    printf(&quot;Function Address : 0x%p\n&quot;, Function);

    for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
    {
        if (ImageBase + *(DWORD *)(ImageBase + EXPORT-&amp;gt;AddressOfFunctions + *(WORD *)(ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals + i * 2) * 4) == Function)
        {
            printf(&quot;Function name : %s\n&quot;, ImageBase + *(DWORD *)(ImageBase + EXPORT-&amp;gt;AddressOfNames + i * 4));
            break;
        }
    }
}

int main(int argc, char *argv[])
{
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION nirvana;
    nirvana.Version = 0;
    nirvana.Reserved = 0;
    nirvana.Callback = InstrumentationCallback;
    
    NtSetInformationProcess(GetCurrentProcess(), PROCESS_INFO_CLASS_INSTRUMENTATION, &amp;amp;nirvana, sizeof(nirvana));
    OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSVC 컴파일용 어셈블리&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1660508936922&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;; File : extern.asm
_TEXT SEGMENT

PUBLIC GetInstrumentationCallbackData

GetInstrumentationCallbackData PROC
    mov eax, dword ptr [r10 - 10h]
    mov dword ptr [rcx], eax
    lea rax, qword ptr [r10 - 14h]
    mov qword ptr [rdx], rax
    ret
GetInstrumentationCallbackData ENDP

_TEXT ENDS

END&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1659447032423&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;=====GCC=====
CommandLine : gcc.exe main.c -o main.exe -lntdll -masm=intel
=====MSVC====
CommandLine : ml64.exe /c extern.asm =&amp;gt; result : extern.obj
CommandLink : cl.exe main.c extern.obj /Od /Z7 /link /MANIFEST:NO /DEBUG:FULL /OPT:REF /OPT:ICF /OPT:LBR&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 결과&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1659447260496&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System Call Number : 0x26
Function Address : 0x00007FFD5F22D3F0
Function name : NtOpenProcess
System Call Number : 0x2c
Function Address : 0x00007FFD5F22D4B0
Function name : NtTerminateProcess
System Call Number : 0x0f
Function Address : 0x00007FFD5F22D110
Function name : NtClose
System Call Number : 0x0f
Function Address : 0x00007FFD5F22D110
Function name : NtClose
System Call Number : 0x0f
Function Address : 0x00007FFD5F22D110
Function name : NtClose
System Call Number : 0x0f
Function Address : 0x00007FFD5F22D110
Function name : NtClose&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Windows/Instrumentation Callback</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/107</guid>
      <comments>https://crazyhacker.tistory.com/107#entry107comment</comments>
      <pubDate>Tue, 2 Aug 2022 22:03:48 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Instrumentation Callback 등록하기</title>
      <link>https://crazyhacker.tistory.com/106</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Instrumentation Callback's Strcture&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instrumentation Callback을 등록하기 위해서는 특정한 구조체를 사용해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1659411722954&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
    ULONG Version;  // x64 -&amp;gt; 0 | x86 -&amp;gt; 1
    ULONG Reserved; // Always 0
    PVOID Callback; // VOID (CALLBACK *InstrumentationCallback)();
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to Reigster Instrumentation Callback?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instrumentation Callback을 등록하기 위해서는 &lt;b&gt;NtSetInforamationProcess&lt;/b&gt; 함수를 사용해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1659411722955&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;VOID CALLBACK InstrumentationCallback()
{
    printf(&quot;Instrumentation Callback\n&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1659411722955&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION nirvana;
nirvana.Version = 0;
nirvana.Reserved = 0;
nirvana.Callback = InstrumentationCallback;

NtSetInformationProcess(hProcess, PROCESS_INFO_CLASS_INSTRUMENTATION, &amp;amp;nirvana, sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION));&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Example&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1659414482312&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

#define PROCESS_INFO_CLASS_INSTRUMENTATION 40

NTSYSAPI NTSTATUS NTAPI NtSetInformationProcess(HANDLE ProcessHandle, PROCESS_INFORMATION_CLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength);

typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION
{
    ULONG Version;
    ULONG Reserved;
    PVOID Callback;
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;

VOID CALLBACK InstrumentationCallback()
{
    printf(&quot;Instrumentation Callback\n&quot;);
}

int main(int argc, char *argv[])
{
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION nirvana;
    nirvana.Version = 0;
    nirvana.Reserved = 0;
    nirvana.Callback = InstrumentationCallback;
    
    NtSetInformationProcess(GetCurrentProcess(), PROCESS_INFO_CLASS_INSTRUMENTATION, &amp;amp;nirvana, sizeof(PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION));
    OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Windows/Instrumentation Callback</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/106</guid>
      <comments>https://crazyhacker.tistory.com/106#entry106comment</comments>
      <pubDate>Tue, 2 Aug 2022 13:08:42 +0900</pubDate>
    </item>
    <item>
      <title>[Windows] Instrumentation Callback이란?</title>
      <link>https://crazyhacker.tistory.com/105</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What is Instrumentation Callback?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Instrumentation Callback&lt;/b&gt;(계측 콜백)이란 Windows 시스템에서 지원하는 콜백중 하나이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;When will this Callback be Called?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Instrumentation Callback은 프로세스에서 syscall을 호출하는 모든 커널함수들이 호출되었을 때 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예외&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;단 NtContinue, NtTerminateProcess, NtTerminateThread (현재 스레드에서 호출한 경우), NtRaiseException 함수의 경우에는 콜백이 동작하지 않는다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Windows/Instrumentation Callback</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/105</guid>
      <comments>https://crazyhacker.tistory.com/105#entry105comment</comments>
      <pubDate>Mon, 1 Aug 2022 23:46:07 +0900</pubDate>
    </item>
    <item>
      <title>[Arduino] LoRa Step 6 - 전파법에 맞춰 로라 설정하기</title>
      <link>https://crazyhacker.tistory.com/103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;대한민국에서 로라를 사용하기 위해서 신경써야하는 조항은 2개가 있다. &lt;span style=&quot;color: #ee2323;&quot;&gt;주파수와 출력세기이다. 이 부분은 하드웨어 적으로 값을 세팅해주고 사용해야 한다.&lt;/span&gt; 잠깐 연습삼아 사용하는건 괜찮을지 몰라도 지속적으로 법에 어긋나는 주파수와 출력세기를 사용하다가는 문제가 발생할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;주파수 (Channel)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;대한민국에서 등록?하지 않고 사용할 수 있는 주파수 범위는 &lt;code&gt;917.1 ~ 923.3 MHz&lt;/code&gt; 이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;E32-900T30D 주파수 설정 공식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;해당 모듈의 기본 주파수는 868MHz로 설정되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;151&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw9CnA/btrIuamnbnc/NyOqRu24aioP1yx8P99Cg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw9CnA/btrIuamnbnc/NyOqRu24aioP1yx8P99Cg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw9CnA/btrIuamnbnc/NyOqRu24aioP1yx8P99Cg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw9CnA%2FbtrIuamnbnc%2FNyOqRu24aioP1yx8P99Cg0%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;1135&quot; height=&quot;151&quot; data-origin-width=&quot;1135&quot; data-origin-height=&quot;151&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 첨부했었던 데이터 시트를 확인해보면 기본 &lt;code&gt;862MHz + CHAN * 1MHz&lt;/code&gt; 공식으로 주파수를 설정한다. 채널을 60으로 설정하게되면 &lt;code&gt;862MHz + 60 * 1MHz&lt;/code&gt;으로 922MHz 주파수를 사용할 수 있게된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;E32-900T30D 주파수 설정 방법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1659177442202&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;SoftwareSerial.h&amp;gt;
#include &quot;EBYTE.h&quot;

#define PIN_M0 4
#define PIN_M1 5
#define PIN_AX 6

SoftwareSerial LoRa(2, 3);
EBYTE Transceiver(&amp;amp;LoRa, PIN_M0, PIN_M1, PIN_AX);

void setup()
{
    Serial.begin(115200);
    LoRa.begin(9600);
    Transceiver.init();            // 초기화
    Transceiver.SetChannel(60);    // 채널(주파수) 설정
    Transceiver.SaveParameters();  // 설정 저장
}

void loop()
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;출력세기 (Transmission Power)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;출력세기는 주파수 채널별로 다른데 자세한건 아래 포스트에서 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659178140013&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;[Arduino] LoRa Step 3 - 대한민국에서 LoRa를 사용하기 위한 법 조항&quot; data-og-description=&quot;전파법 LoRa를 처음 접하는 사람이라면 갑자기 왜 법을 언급하는데 의아해 할 수도 있다. 하지만 전파는 공공재이기 때문에 국가의 관리하에 사용해야한다. 로라는 주파수를 사용해 통신하기 때&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/41&quot; data-og-url=&quot;https://crazyhacker.tistory.com/41&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/biLmNT/hyPf2HcFgP/wYfSQyfO8ge4rIJLhYleVk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/VyjQH/hyPf2tFphV/2XOepN1meUl4k9w9T6Fdfk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Jfuid/hyPf2HcFal/kjowd2aZCvRpCj7ea1ZKv0/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/41&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/41&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/biLmNT/hyPf2HcFgP/wYfSQyfO8ge4rIJLhYleVk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/VyjQH/hyPf2tFphV/2XOepN1meUl4k9w9T6Fdfk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Jfuid/hyPf2HcFal/kjowd2aZCvRpCj7ea1ZKv0/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Arduino] LoRa Step 3 - 대한민국에서 LoRa를 사용하기 위한 법 조항&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;전파법 LoRa를 처음 접하는 사람이라면 갑자기 왜 법을 언급하는데 의아해 할 수도 있다. 하지만 전파는 공공재이기 때문에 국가의 관리하에 사용해야한다. 로라는 주파수를 사용해 통신하기 때&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;E32-900T30D 출력세기 종류&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKmMeA/btrIwG0ayor/aUcfUQDbVc26DjKB2nF0Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKmMeA/btrIwG0ayor/aUcfUQDbVc26DjKB2nF0Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKmMeA/btrIwG0ayor/aUcfUQDbVc26DjKB2nF0Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKmMeA%2FbtrIwG0ayor%2FaUcfUQDbVc26DjKB2nF0Kk%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;974&quot; height=&quot;218&quot; data-origin-width=&quot;974&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 모듈의 출력세기는 데이터 시트에 나와 있듯이 총 4종류를 지원하는데 필자도 몰랐던 사실이지만 mW(밀리와트)와 dBm(데시벨 밀리와트)가 다르다는 것이었다. 위 포스팅에서는 단위가 mW로 표시되어 있지만 데이터 시트에는 dBm으로 표시되어 있다. 그래서 해당 단위를 변환해줄 필요가 있다. 아래 사이트에서 변환이 가능하다.&lt;/p&gt;
&lt;figure id=&quot;og_1659178429187&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;dBm to Watt Caluclator - everything RF&quot; data-og-description=&quot;What is dBm to watts conversion calculator? dBm to Watts conversion calculator converts the power value in dBm to Watts value. Watt (W) is a SI unit for measuring the power and dBm is a decibel unit for measuring the power. How to calculate power (in watt)&quot; data-og-host=&quot;www.everythingrf.com&quot; data-og-source-url=&quot;https://www.everythingrf.com/rf-calculators/dbm-to-watts&quot; data-og-url=&quot;https://www.everythingrf.com/rf-calculators/dbm-to-watts&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.everythingrf.com/rf-calculators/dbm-to-watts&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.everythingrf.com/rf-calculators/dbm-to-watts&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;dBm to Watt Caluclator - everything RF&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is dBm to watts conversion calculator? dBm to Watts conversion calculator converts the power value in dBm to Watts value. Watt (W) is a SI unit for measuring the power and dBm is a decibel unit for measuring the power. How to calculate power (in watt)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.everythingrf.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 사이트에서 변환하면 충격적인 결과를 알 수 있는데 바로 30dBm이 1W 였던 것이다...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nhQqO/btrIzFsbny6/0UNiKXPLdlEJgQ0I3fnQpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nhQqO/btrIzFsbny6/0UNiKXPLdlEJgQ0I3fnQpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nhQqO/btrIzFsbny6/0UNiKXPLdlEJgQ0I3fnQpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnhQqO%2FbtrIzFsbny6%2F0UNiKXPLdlEJgQ0I3fnQpK%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;467&quot; height=&quot;391&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;E32-900T30D 출력세기 설정 방법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 사용할 수 있는 최대 출력세기는 200mW 인데 1W면 규정치에 5배나 되는 세기이다. 이러한 출력 세기를 지속적으로 사용하면 무조건 문제가 발생할 수 밖에 없다. &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;&lt;span style=&quot;color: #333333;&quot;&gt;제일 낮은 21dBm을 확인해보면 125mW 인것을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m1Uca/btrIA1PiIvH/2kLDiWp3vYmntExd5nbKMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m1Uca/btrIA1PiIvH/2kLDiWp3vYmntExd5nbKMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m1Uca/btrIA1PiIvH/2kLDiWp3vYmntExd5nbKMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm1Uca%2FbtrIA1PiIvH%2F2kLDiWp3vYmntExd5nbKMK%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;467&quot; height=&quot;392&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 채널은 20 ~ 32 (920.9 ~ 923.3 MHz)를 사용하면 실외 고정용 점대점 무선기기에 한해서 200mW 이하의 출력세기를 사용할 수 있다. 그렇다는 건 밖에서 움직이며 사용할 수 없다는 것을 뜻한다...&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;어쩔 수 없지만 지금 있는 E32-900T30D 모듈을 사용하기 위해서는 이 방법 말고는 없다.&lt;/p&gt;
&lt;pre id=&quot;code_1659178821395&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;SoftwareSerial.h&amp;gt;
#include &quot;EBYTE.h&quot;

#define PIN_M0 4
#define PIN_M1 5
#define PIN_AX 6

SoftwareSerial LoRa(2, 3);
EBYTE Transceiver(&amp;amp;LoRa, PIN_M0, PIN_M1, PIN_AX);

void setup()
{
    Serial.begin(115200);
    LoRa.begin(9600);
    Transceiver.init();                 // 초기화
    Transceiver.SetChannel(60);         // 채널(주파수) 설정
    Transceiver.SetTransmitPower(0b11); // 출력세기 설정
    Transceiver.SaveParameters();       // 설정 저장
}

void loop()
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;필자가 생각했을 때 가장 중요한 요소는 주파수와 출력세기라고 생각했기 때문에 이번 포스팅에서는 두가지만 소개했다. UART Baud Rate나 Air Data Rate는 어떻게 설정하더라고 법적으로 큰 문제가 없는 것같아서 다음 포스팅에서는 이 외에 설정들을 셋팅하는 것을 해보려고 한다&lt;/span&gt;&lt;/p&gt;</description>
      <category>Arduino/LoRa</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/103</guid>
      <comments>https://crazyhacker.tistory.com/103#entry103comment</comments>
      <pubDate>Sat, 30 Jul 2022 20:03:30 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] Tree에 Item을 추가해 데이터 시각화하기</title>
      <link>https://crazyhacker.tistory.com/102</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 와이어샤크의 Tree(트리)에 TreeItem을 생성하고 생성된 TreeItem에 Item을 추가해 데이터를 보다 보기 좋게 시각화하려고 한다.&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;figure id=&quot;og_1659122995443&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;[Wireshark] Dissector로 프로토콜 만들기&quot; data-og-description=&quot;Create a Protocol use Wireshark API 우선 Wireshark(와이어샤크)에서 제공하는 API를 활용해 직접 프로토콜을 정의한다. MyProto = Proto.new(&amp;quot;MyProto&amp;quot;, &amp;quot;My Custom Protocol&amp;quot;) Define Dissector of MyProto 새..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/99&quot; data-og-url=&quot;https://crazyhacker.tistory.com/99&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/LCpEn/hyPeRNwifi/CxSVE8XWfYcpbCZWMfHV80/img.png?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/WCzi7/hyPeRfGlcX/Bh3AtNrRoKFmqO9GckFU2k/img.png?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/b9xDKU/hyPf9ls7fF/09nCIosdHeUJwof5BYOwSk/img.png?width=1701&amp;amp;height=1025&amp;amp;face=0_0_1701_1025&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/99&quot; data-source-url=&quot;https://crazyhacker.tistory.com/99&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/LCpEn/hyPeRNwifi/CxSVE8XWfYcpbCZWMfHV80/img.png?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/WCzi7/hyPeRfGlcX/Bh3AtNrRoKFmqO9GckFU2k/img.png?width=800&amp;amp;height=480&amp;amp;face=0_0_800_480,https://scrap.kakaocdn.net/dn/b9xDKU/hyPf9ls7fF/09nCIosdHeUJwof5BYOwSk/img.png?width=1701&amp;amp;height=1025&amp;amp;face=0_0_1701_1025');&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;[Wireshark] Dissector로 프로토콜 만들기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Create a Protocol use Wireshark API 우선 Wireshark(와이어샤크)에서 제공하는 API를 활용해 직접 프로토콜을 정의한다. MyProto = Proto.new(&quot;MyProto&quot;, &quot;My Custom Protocol&quot;) Define Dissector of MyProto 새..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to add TreeItem to Wireshark&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;dissector의 인자로 들어오는 root를 이용해 TreeItem을 생성할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659123163475&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MyProto = Proto.new(&quot;MyProto&quot;, &quot;My Custom Protocol&quot;)

function MyProto.dissector(buf, pinfo, root)
    pinfo.cols.protocol = &quot;MY_PROTOCOL&quot;
    local st = root:add(MyProto, &quot;MY PROTOCOL DATA&quot;, buf(0, buf:len()))
end

DissectorTable.get(&quot;tcp.port&quot;):add(8080, MyProto)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 &lt;code&gt;MY PROTOCOL DATA&lt;/code&gt;라는 이름의 트리 아이템을 추가하는 코드이다. 생성된 트리 아이템을 변수에 저장해야 하위에 아이템을 생성할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to add Sub-Item for TreeItem&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위에서 생성한 트리 아이템에 아이템을 추가해 데이터를 보기 좋게 만들 수 있다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659123837306&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;st:add(buf(0), &quot;Data: &quot; .. buf(0):bytes():tohex())&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6Q0MG/btrIwGL7T6K/eRmFFkrssBr6uBeEUtoQNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6Q0MG/btrIwGL7T6K/eRmFFkrssBr6uBeEUtoQNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6Q0MG/btrIwGL7T6K/eRmFFkrssBr6uBeEUtoQNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6Q0MG%2FbtrIwGL7T6K%2FeRmFFkrssBr6uBeEUtoQNk%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;1214&quot; height=&quot;728&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;생성된 아이템을 클릭해보면 아래에 해당되는 데이터가 파란색으로 하이라이트 되는 것을 볼 수 있는데 이는 자동적으로 되는 것이 아니라 st:add 함수에서 첫 번째 인자로 해당 범위를 지정해주는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1659124182129&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;st:add(buf(0, 2), &quot;Data: &quot; .. buf(0, 2):bytes():tohex())&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;1218&quot; data-origin-height=&quot;729&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EhEhm/btrIxwbcJFt/cOkn7LMn91LizgvIzOCGDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EhEhm/btrIxwbcJFt/cOkn7LMn91LizgvIzOCGDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EhEhm/btrIxwbcJFt/cOkn7LMn91LizgvIzOCGDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEhEhm%2FbtrIxwbcJFt%2FcOkn7LMn91LizgvIzOCGDk%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;1218&quot; height=&quot;729&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 예로 들자면 buf(0, 2) 는 TCP 프로토콜 Payload의 오프셋 0부터 2바이트를 아이템의 범위로 지정해준다는 의미이다. 맨 위의 예시에서는 offset만 지정해주고 length는 지정하지 않았기 때문에 오프셋 0부터 모든 데이터가 범위로 지정됐다.&lt;/p&gt;</description>
      <category>Wireshark/Lua Script</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/102</guid>
      <comments>https://crazyhacker.tistory.com/102#entry102comment</comments>
      <pubDate>Sat, 30 Jul 2022 04:53:28 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] EAT Hooking Step 2</title>
      <link>https://crazyhacker.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 EAT에서 함수의 주소를 구하는 원리와 EAT 후킹 방법에 대해 설명하려고 한다. EAT는 IAT와 다르게 오프셋이 저장되기 때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;x86이라면 모를까 x64 환경에서는 100% 성공한다고 장담할 수는 없다.&lt;/span&gt; 하지만 해당 블로그는 따로 명시되어 있지 않다면 Windows x64를 기준으로 작성하기 때문에 x64 환경에서 EAT 후킹 방법에 대해서 설명하려고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to do EAT hooking ways?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;EAT에서 사용하는 오프셋은 최대 4바이트로 Windows x64는 8바이트 주소를 사용하기 때문에 해당 DLL의 ImageBase로부터 4바이트 이상의 주소로 이동하도록 후킹할 수는 없다.&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;위에서 설명했지만 주소가 4바이트를 넘지 않는다면 오프셋만 덮어씌워서 후킹이 가능하다. (여기에서는 편리를 위해 x86을 기반으로 코드를 작성하겠다)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1469&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTyzUX/btrMnKQWqm0/aJhLyGQxNY1kcoTzS9LhkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTyzUX/btrMnKQWqm0/aJhLyGQxNY1kcoTzS9LhkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTyzUX/btrMnKQWqm0/aJhLyGQxNY1kcoTzS9LhkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTyzUX%2FbtrMnKQWqm0%2FaJhLyGQxNY1kcoTzS9LhkK%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;1469&quot; height=&quot;860&quot; data-origin-width=&quot;1469&quot; data-origin-height=&quot;860&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1663512299658&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    return MessageBoxA(hWnd, &quot;Hooked..!&quot;, &quot;Hooked..!&quot;, uType);
}

int main(int argc, char *argv[])
{
    ULONG_PTR ImageBase = GetModuleHandleA(&quot;user32.dll&quot;);

    if (ImageBase == NULL)
        ImageBase = LoadLibraryA(&quot;user32.dll&quot;);

    int (WINAPI *HookMessageBoxA)(HWND, LPCSTR, LPCSTR, UINT) = GetProcAddress(ImageBase, &quot;MessageBoxA&quot;);
    HookMessageBoxA(NULL, &quot;Not Hooked..!&quot;, &quot;Not Hooked..!&quot;, 0);

    printf(&quot;[*] Module Name : user32.dll\n&quot;);
    printf(&quot;[*] ImageBase : %p\n&quot;, ImageBase);

    IMAGE_DOS_HEADER *DOS = ImageBase;
    printf(&quot;[*] Image Dos Header : 0x%p\n&quot;, DOS);

    IMAGE_NT_HEADERS *NT = ImageBase + DOS-&amp;gt;e_lfanew;
    printf(&quot;[*] Image Nt Header : 0x%p\n&quot;, NT);

    IMAGE_EXPORT_DIRECTORY *EXPORT = ImageBase + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    printf(&quot;[*] Export Table : 0x%p\n&quot;, EXPORT);

    printf(&quot;[+] Number Of Functions : %d\n&quot;, EXPORT-&amp;gt;NumberOfFunctions);
    printf(&quot;[+] Number Of Names : %d\n&quot;, EXPORT-&amp;gt;NumberOfNames);

    DWORD *AddressOfFunctions = ImageBase + EXPORT-&amp;gt;AddressOfFunctions;
    DWORD *AddressOfNames = ImageBase + EXPORT-&amp;gt;AddressOfNames;
    WORD *AddressOfNameOrdinals = ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals;

    for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
    {
        if (strcmp(ImageBase + AddressOfNames[i], &quot;MessageBoxA&quot;) == 0)
        {
            DWORD flOldProtect;
            VirtualProtect(&amp;amp;AddressOfFunctions[AddressOfNameOrdinals[i]], 4, PAGE_READWRITE, &amp;amp;flOldProtect);
            AddressOfFunctions[AddressOfNameOrdinals[i]] = (ULONG_PTR)NewMessageBoxA - (ULONG_PTR)ImageBase;
            break;
        }
    }

    HookMessageBoxA = GetProcAddress(ImageBase, &quot;MessageBoxA&quot;);
    HookMessageBoxA(NULL, &quot;Not Hooked..!&quot;, &quot;Not Hooked..!&quot;, 0);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/QeAfu/btrMNJkHx36/suOksVB7k8x1sRqY9TFof0/EAT%20Hooking.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;EAT Hooking.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1663859219583&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[*] Module Name : user32.dll
[*] ImageBase : 766C0000
[*] Image Dos Header : 0x766C0000
[*] Image Nt Header : 0x766C00E8
[*] Export Table : 0x7675CC10
[+] Number Of Functions : 1215
[+] Number Of Names : 998&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 x86 아키텍쳐로 컴파일 후 실행하면 처음에 GetProcAddress 함수를 이용해 구한 함수는 정상적으로 메시지가 출력되지만 두번째에 GetProcAddress 함수를 이용해 구한 함수는 인자가 조작되어 호출되는 것을 확인할 수 있따.&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;이렇게 GetProcAddress 함수를 통해 구한 MessageBoxA 함수의 주소와 NewMessageBoxA 함수의 주소가 같은 것을 확인할 수 있다. 하지만 IAT를 통해 함수를 호출하는 경우에는 후킹이 되지 않고 정상적인 호출이 가능하다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/100</guid>
      <comments>https://crazyhacker.tistory.com/100#entry100comment</comments>
      <pubDate>Thu, 28 Jul 2022 04:10:47 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] Dissector로 프로토콜 만들기</title>
      <link>https://crazyhacker.tistory.com/99</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Create a Protocol use Wireshark API&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우선 Wireshark(와이어샤크)에서 제공하는 API를 활용해 직접 프로토콜을 정의한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1658946116231&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MyProto = Proto.new(&quot;MyProto&quot;, &quot;My Custom Protocol&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Define Dissector of MyProto&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;새롭게 생성한 프로토콜의 대한 dissector를 정의해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1658947880813&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function MyProto.dissector(buf, pinfo, root)
    pinfo.cols.protocol = &quot;MY_PROTOCOL&quot;
    root:add(MyProto, &quot;MY PROTOCOL DATA&quot;, buf(0))
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dissector 함수의 인자는 총 3개 이며 각각 패킷 데이터, 패킷 정보, 패킷 프레임?이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Parameter buf&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;dissector의 buf는 와이어샤크에서 실질적인 데이터를 버퍼를 가리킨다. (Tvb object)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;1017&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKrQlG/btrIlwXccwN/8AU9z0dxyhWRCefbEo8Ki1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKrQlG/btrIlwXccwN/8AU9z0dxyhWRCefbEo8Ki1/img.png&quot; data-alt=&quot;buf에 해당되는 부분&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKrQlG/btrIlwXccwN/8AU9z0dxyhWRCefbEo8Ki1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKrQlG%2FbtrIlwXccwN%2F8AU9z0dxyhWRCefbEo8Ki1%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;1692&quot; height=&quot;1017&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;1017&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;buf에 해당되는 부분&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이더넷 헤더와 같은 정보들은 포함되어 있지 않다. buf에 들어오는 데이터는 payload만 들어오게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1635&quot; data-origin-height=&quot;979&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mVUpo/btrIkoZoyuq/TCtKPxBaSd5wbr7RpZCft0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mVUpo/btrIkoZoyuq/TCtKPxBaSd5wbr7RpZCft0/img.png&quot; data-alt=&quot;buf에 들어오는 데이터&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mVUpo/btrIkoZoyuq/TCtKPxBaSd5wbr7RpZCft0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmVUpo%2FbtrIkoZoyuq%2FTCtKPxBaSd5wbr7RpZCft0%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;1635&quot; height=&quot;979&quot; data-origin-width=&quot;1635&quot; data-origin-height=&quot;979&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;buf에 들어오는 데이터&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Parameter pinfo&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;dissector의 pinfo는 와이어샤크의 패킷의 정보를 표시하는 테이블을 가리킨다. (Pinfo object)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1697&quot; data-origin-height=&quot;1023&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zhg5J/btrIpsML8cb/3lu8kMFyQps0PzUeKdRsSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zhg5J/btrIpsML8cb/3lu8kMFyQps0PzUeKdRsSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zhg5J/btrIpsML8cb/3lu8kMFyQps0PzUeKdRsSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzhg5J%2FbtrIpsML8cb%2F3lu8kMFyQps0PzUeKdRsSk%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;1697&quot; height=&quot;1023&quot; data-origin-width=&quot;1697&quot; data-origin-height=&quot;1023&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pinfo에는 Number, Time, Protocol 등의 Column의 정보를 수정할 수 있고 또 새로운 Column을 추가할 수 있다. 다음 코드는 Protocol Column의 데이터를 수정한다.&lt;/p&gt;
&lt;pre id=&quot;code_1658947836738&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pinfo.cols.protocol = &quot;MY_PROTOCOL&quot;&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;1622&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diyLUe/btrIkoLSm3h/k0emaKbokT1Qbuf731LO40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diyLUe/btrIkoLSm3h/k0emaKbokT1Qbuf731LO40/img.png&quot; data-alt=&quot;Protocol 컬럼이 변경된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diyLUe/btrIkoLSm3h/k0emaKbokT1Qbuf731LO40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdiyLUe%2FbtrIkoLSm3h%2Fk0emaKbokT1Qbuf731LO40%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;1622&quot; height=&quot;966&quot; data-origin-width=&quot;1622&quot; data-origin-height=&quot;966&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Protocol 컬럼이 변경된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Parameter root&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;dissector의 root는 와이어샤크의 패킷의 데이터를 표시하는 트리를 가리킨다. (TreeItem object)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1701&quot; data-origin-height=&quot;1025&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRyz3Y/btrInIbKmP6/9Q3j6FJso4EvMI5ayh9Vu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRyz3Y/btrInIbKmP6/9Q3j6FJso4EvMI5ayh9Vu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRyz3Y/btrInIbKmP6/9Q3j6FJso4EvMI5ayh9Vu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRyz3Y%2FbtrInIbKmP6%2F9Q3j6FJso4EvMI5ayh9Vu0%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;1701&quot; height=&quot;1025&quot; data-origin-width=&quot;1701&quot; data-origin-height=&quot;1025&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와이어샤크의 중앙에 있는 이 트리는 해당 패킷의 프로토콜에 맞춰서 패킷의 데이터를 보기 편하게 구분하여 보여준다. 우리가 만든 커스텀 프로토콜은 이러한 트리 구조가 등록되어 있지 않기 때문에 아무런 트리가 생성되지 않게 된다. root는&amp;nbsp; 이 트리들이 모여있는 곳을 말한다. 다음 코드는 새로운 트리를 생성하는 코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1658948320621&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root:add(MyProto, &quot;MY PROTOCOL DATA&quot;, buf(0))&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;1687&quot; data-origin-height=&quot;1007&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lsbOf/btrIi6dTHU8/t3ULYPDKBxkp73cibCHgn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lsbOf/btrIi6dTHU8/t3ULYPDKBxkp73cibCHgn1/img.png&quot; data-alt=&quot;MY PROTOCOL DATA 트리가 생성된 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lsbOf/btrIi6dTHU8/t3ULYPDKBxkp73cibCHgn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlsbOf%2FbtrIi6dTHU8%2Ft3ULYPDKBxkp73cibCHgn1%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;1687&quot; height=&quot;1007&quot; data-origin-width=&quot;1687&quot; data-origin-height=&quot;1007&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MY PROTOCOL DATA 트리가 생성된 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Set the MyProto&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이제는 저 수 많은 패킷중 어떤 패킷이 MyProto에 속하는 패킷인지 설정해야 한다. 해당 방법은 와이어샤크의 필터를 사용하는 방법과 유사하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1658948717174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DissectorTable.get(&quot;tcp.port&quot;):add(8080, MyProto)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 TCP 프로토콜의 포트가 8080일 경우 MyProto로 설정한다는 말이다. 이렇게 설정하게 된다면 8080 포트로 통신하는 모든 TCP 패킷들이 MyProto.dissector 함수를 거치게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최종 코드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1658948866618&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MyProto = Proto.new(&quot;MyProto&quot;, &quot;My Custom Protocol&quot;)

function MyProto.dissector(buf, pinfo, root)
    pinfo.cols.protocol = &quot;MY_PROTOCOL&quot;
    root:add(MyProto, &quot;MY PROTOCOL DATA&quot;, buf(0, buf:len()))
end

DissectorTable.get(&quot;tcp.port&quot;):add(8080, MyProto)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;여기까지 Lua 스크립트를 이용해 와이어샤크에 커스텀 프로토콜을 추가해 하위 트리를 생성 그리고 프로토콜의 이름을 수정하는 방법을 알아보았다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;다음 포스팅에서는 우리가 생성했던 하위 트리(MY PROTOCOL DATA)에 Item을 생성하여 데이터를 분류하여 표시하는 방법을 알아보려고 한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Wireshark/Lua Script</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/99</guid>
      <comments>https://crazyhacker.tistory.com/99#entry99comment</comments>
      <pubDate>Thu, 28 Jul 2022 03:51:30 +0900</pubDate>
    </item>
    <item>
      <title>[Wireshark] Lua Script 개발 환경설정</title>
      <link>https://crazyhacker.tistory.com/98</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Install Visual Studio Code Lua Script Extenstion&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;VS Code에서 Lua Script에 대한 확장을 설치해줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1375&quot; data-origin-height=&quot;1033&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DYUca/btrIn4ZVg1M/2EZQLqV8PxGsBKCmb2huv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DYUca/btrIn4ZVg1M/2EZQLqV8PxGsBKCmb2huv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DYUca/btrIn4ZVg1M/2EZQLqV8PxGsBKCmb2huv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDYUca%2FbtrIn4ZVg1M%2F2EZQLqV8PxGsBKCmb2huv0%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;1375&quot; height=&quot;1033&quot; data-origin-width=&quot;1375&quot; data-origin-height=&quot;1033&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;환경설정 끝&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Lua를 이용해 Wireshark의 스크립트를 추가할 계획이기 때문에 따로 Lua를 설치해줄 필요는 없다. 그리고 사실 VS Code에서 Lua 확장을 설치하던 설치하지 않던 큰 차이는 발생하지 않는다. 어차피 Wireshark의 API 함수들을 VS Code가 자동으로 IntelliSense 해주지 못하기 때문이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Wireshark/Lua Script</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/98</guid>
      <comments>https://crazyhacker.tistory.com/98#entry98comment</comments>
      <pubDate>Thu, 28 Jul 2022 03:15:10 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] EAT Hooking Step 1</title>
      <link>https://crazyhacker.tistory.com/97</link>
      <description>&lt;figure id=&quot;og_1659108680943&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;[Reversing] EAT Hooking Step 0&quot; data-og-description=&quot;EAT Hooking EAT(Export Address Table) Hooking 이란 EAT의 API 주소를 조작하여 후킹하는 기법을 말한다. EAT에는 라이브러리가 외부로 Export 하는 함수명 또는 변수명과 주소가 기록되어 있다. 응용 프로그램..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/95&quot; data-og-url=&quot;https://crazyhacker.tistory.com/95&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jW9Lt/hyPf9FLHZv/LW7RppuF41IGDDCe7oeaO1/img.png?width=800&amp;amp;height=487&amp;amp;face=0_0_800_487,https://scrap.kakaocdn.net/dn/uu4iq/hyPeJBTX5w/H7TSNd2Sd1WUAUKTs7OzHK/img.png?width=800&amp;amp;height=487&amp;amp;face=0_0_800_487,https://scrap.kakaocdn.net/dn/r57M9/hyPf0Pyn43/GWC9MeL1aaNbeC6YotZKD1/img.png?width=1873&amp;amp;height=901&amp;amp;face=0_0_1873_901&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/95&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jW9Lt/hyPf9FLHZv/LW7RppuF41IGDDCe7oeaO1/img.png?width=800&amp;amp;height=487&amp;amp;face=0_0_800_487,https://scrap.kakaocdn.net/dn/uu4iq/hyPeJBTX5w/H7TSNd2Sd1WUAUKTs7OzHK/img.png?width=800&amp;amp;height=487&amp;amp;face=0_0_800_487,https://scrap.kakaocdn.net/dn/r57M9/hyPf0Pyn43/GWC9MeL1aaNbeC6YotZKD1/img.png?width=1873&amp;amp;height=901&amp;amp;face=0_0_1873_901');&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;[Reversing] EAT Hooking Step 0&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;EAT Hooking EAT(Export Address Table) Hooking 이란 EAT의 API 주소를 조작하여 후킹하는 기법을 말한다. EAT에는 라이브러리가 외부로 Export 하는 함수명 또는 변수명과 주소가 기록되어 있다. 응용 프로그램..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 EAT 구조에 대해서 간단히 배웠었다. 이번 포스팅에서는 C언어를 활용해 실제 EAT에 등록되어 있는 함수들의 이름과 주소를 불러오는 프로그램을 만들어볼 예정이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Get Library ImageBase&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;EAT 주소를 구하기 위해서는 &lt;code&gt;IMAGE_DOS_HEADER(Dos Header)&lt;/code&gt;를 구해야 한다. Dos Header의 주소는 해당 라이브러리의 &lt;code&gt;ImageBase&lt;/code&gt;의 주소와 동일하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659108919933&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ULONGLONG ImageBase = GetModuleHandleA(&quot;user32.dll&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetModuleHandleA&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;GetModuleHandleA API는 &lt;span style=&quot;color: #ee2323;&quot;&gt;특정 라이브러리의 ImageBase를 반환하는 함수&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;code&gt;LPCSTR(const char *)&lt;/code&gt; 자료형을 인자로 받으며 라이브러리의 이름을 전달하면 된다. &lt;span style=&quot;color: #006dd7;&quot;&gt;NULL이 전달될 경우 해당 함수는 현재 프로그램의 ImageBase를 반환한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659109014194&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HMODULE GetModuleHandleA(LPCSTR lpModuleName);&lt;/code&gt;&lt;/pre&gt;
&lt;figure id=&quot;og_1659108996919&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;GetModuleHandleA function (libloaderapi.h) - Win32 apps&quot; data-og-description=&quot;Retrieves a module handle for the specified module. The module must have been loaded by the calling process. (ANSI)&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qTDnM/hyPeNjXt02/pFC6KfdBshExXB7pHVzlY1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qTDnM/hyPeNjXt02/pFC6KfdBshExXB7pHVzlY1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;GetModuleHandleA function (libloaderapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Retrieves a module handle for the specified module. The module must have been loaded by the calling process. (ANSI)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 함수 원형을 살펴보면 &lt;code&gt;HMODULE&lt;/code&gt;이라는 Handle(핸들)을 반환하지만 이는 과거 &lt;span style=&quot;color: #ee2323;&quot;&gt;MS-DOS 시절의 호환성을 위한 것일 뿐, 신경 쓰지 않아도 된다. 실제 반환되는 값을 확인해보면 ImageBase의 주소&lt;/span&gt;인 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to get EAT Address From DOS Header&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EAT 주소를 구하기 전 NT Header의 주소를 구해야 한다. NT Header 주소는 Dos Header를 이용해 구할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;First, Get NT Header From DOS Header&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dos Header의 &lt;code&gt;e_lfanew&lt;/code&gt; 멤버 변수와 ImageBase를 더하는 방법으로 NT Header 주소를 구할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1659109483889&quot; class=&quot;perl&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;IMAGE_DOS_HEADER *DOS = ImageBase;
printf(&quot;Image Dos Header : 0x%p\n&quot;, DOS);

IMAGE_NT_HEADERS *NT = ImageBase + DOS-&amp;gt;e_lfanew;
printf(&quot;Image Nt Header : 0x%p\n&quot;, NT);​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 구했던 ImageBase 주소를 DOS Header의 주소로 설정하고 참조 연산자를 이용해 e_lfanew에 접근하여 NT Header 주소를 구할 수 있다.&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;NT Header는 &lt;b&gt;x86&lt;/b&gt;, &lt;b&gt;x64&lt;/b&gt; 이렇게 나뉘는데 해당 포스팅에서는 x64를 기준으로 설명한다. 하지만 x86, x64 간의 큰 차이는 없다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Second, Get EAT Address From NT Header&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;NT Header의 Optional Header에 있는 DataDirectory 0번째 인덱스(IMAGE_DIRECTORY_ENTRY_EXPORT를 사용하면 된다)에 EAT의 RVA가 기록되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659109659517&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;IMAGE_EXPORT_DIRECTORY *EXPORT = ImageBase + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
printf(&quot;Export Table : 0x%p\n&quot;, EXPORT);

printf(&quot;Number Of Functions : %d\n&quot;, EXPORT-&amp;gt;NumberOfFunctions);
printf(&quot;Number Of Names : %d\n&quot;, EXPORT-&amp;gt;NumberOfNames);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;VA = ImageBase + RVA&lt;/code&gt; 공식이 성립하기 때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;ImageBase에 RVA를 더하여 실제 EAT 주소를 구할 수 있다.&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;위 코드를 보면 IMAGE_DIRECTORY_ENTRY_EXPORT를 사용해 인덱스를 구하는데 헤더파일을 보면 DataDirectory 각각의 위치가 정의 되어 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1659127218948&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define IMAGE_DIRECTORY_ENTRY_EXPORT          0
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8
#define IMAGE_DIRECTORY_ENTRY_TLS             9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11
#define IMAGE_DIRECTORY_ENTRY_IAT            12
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Print a Function Name and Address&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 주소는 Ordinal을 이용해 구할 수 있다. &lt;span style=&quot;color: #ee2323;&quot;&gt;Ordinal이란 AddressOfFunctions의 인덱스로 사용된다.&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;&lt;span style=&quot;color: #006dd7;&quot;&gt;AddressOfNameOrdinals에서 현재 인덱스의 해당되는 함수명의 함수 주소의 Ordinal을 구할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659125054421&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
{
    printf(&quot;%s : %p\n&quot;, ImageBase + *(DWORD *)(ImageBase + EXPORT-&amp;gt;AddressOfNames + i * 4), ImageBase + *(DWORD *)(ImageBase + EXPORT-&amp;gt;AddressOfFunctions + *(WORD *)(ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals + i * 2) * 4));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Export 되는 &lt;span style=&quot;color: #ee2323;&quot;&gt;함수들이 반드시 함수명을 포함해서 Export 되는 것은 아니다&lt;/span&gt;. 그렇기 때문에 예시에서는 NumberOfNames로 이름이 존재하는 함수들의 대한 정보만 출력했다.&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_1659125708981&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DWORD *AddressOfFunctions = ImageBase + EXPORT-&amp;gt;AddressOfFunctions;
DWORD *AddressOfNames = ImageBase + EXPORT-&amp;gt;AddressOfNames;
WORD *AddressOfNameOrdinals = ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals;

for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
{
    printf(&quot;%s : %p\n&quot;, ImageBase + AddressOfNames[i], ImageBase + AddressOfFunctions[AddressOfNameOrdinals[i]]);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드가 훨씬도 가독성이 좋고 예쁘지만 필자는 쓸 때 없는 메모리 사용을 싫어하기 때문에 변수를 사용하지 않고 라인 하나로 처리하는 것을 좋아한다.&lt;s&gt;(이거 쓰면서 생각났는데 그럼 register 변수를 선언하면 되는 거였다...)&lt;/s&gt;&lt;s&gt;&lt;/s&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Compile and Troubleshooting&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;왜 제목을 컴파일 그리고 트러블 슈팅이라고 했을까? 그렇다.. 위에 예시 코드 그대로 이어서 컴파일하면 무조건 런타임 에러가 발생할 것이다. 그래도 우선 컴파일하고 실행해보자 아래는 완성된 코드다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659126057701&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    ULONGLONG ImageBase = LoadLibraryA(&quot;user32.dll&quot;);

    IMAGE_DOS_HEADER *DOS = ImageBase;
    printf(&quot;Image Dos Header : 0x%p\n&quot;, DOS);

    IMAGE_NT_HEADERS *NT = ImageBase + DOS-&amp;gt;e_lfanew;
    printf(&quot;Image Nt Header : 0x%p\n&quot;, NT);

    IMAGE_EXPORT_DIRECTORY *EXPORT = ImageBase + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    printf(&quot;Export Table : 0x%p\n&quot;, EXPORT);

    printf(&quot;Number Of Functions : %d\n&quot;, EXPORT-&amp;gt;NumberOfFunctions);
    printf(&quot;Number Of Names : %d\n&quot;, EXPORT-&amp;gt;NumberOfNames);

    DWORD *AddressOfFunctions = ImageBase + EXPORT-&amp;gt;AddressOfFunctions;
    DWORD *AddressOfNames = ImageBase + EXPORT-&amp;gt;AddressOfNames;
    WORD *AddressOfNameOrdinals = ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals;

    for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
    {
        printf(&quot;%s : %p\n&quot;, ImageBase + AddressOfNames[i], ImageBase + AddressOfFunctions[AddressOfNameOrdinals[i]]);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 아래와 같이 출력되고 프로그램이 강제 종료될 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1659126122263&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Image Dos Header : 0x0000000000000000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력된 결과를 보면 GetModuleHandleA의 반환 값이 NULL이라는 것을 알 수 있는데 왜 NULL을 반환하는 걸까?&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Why dose GetModuleHandleA Return NULL?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;GetModuleHandleA가 NULL을 반환하는 이유는 MSDN을 확인해보면 알 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qqtdp/btrIvTygnYZ/T33DNwK4CjqmTZap2anEvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qqtdp/btrIvTygnYZ/T33DNwK4CjqmTZap2anEvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qqtdp/btrIvTygnYZ/T33DNwK4CjqmTZap2anEvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqqtdp%2FbtrIvTygnYZ%2FT33DNwK4CjqmTZap2anEvK%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;973&quot; height=&quot;471&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파라미터 항목에 분명하게 &quot;로드된 모듈의 이름&quot; 이라고 적혀있다. &lt;span style=&quot;color: #ee2323;&quot;&gt;런타임 에러가 발생하는 원인은 해당 프로세스에 user32.dll이 로드되어 있지 않기 때문&lt;/span&gt;이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;Solution&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;해결방법은 간단하다. 로드되어 있지 않는 것이 문제라면 로드시키면 된다. 모듈을 로드를 하기 위해서는 다음 함수를 사용하면 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1659126690367&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HMODULE LoadLibraryA(LPCSTR lpLibFileName);&lt;/code&gt;&lt;/pre&gt;
&lt;figure id=&quot;og_1659126656548&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;LoadLibraryA function (libloaderapi.h) - Win32 apps&quot; data-og-description=&quot;Loads the specified module into the address space of the calling process. (LoadLibraryA)&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b15ZtI/hyPeMFsfpe/B7WYrblxfgcvW7gmKqf8lK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b15ZtI/hyPeMFsfpe/B7WYrblxfgcvW7gmKqf8lK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;LoadLibraryA function (libloaderapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Loads the specified module into the address space of the calling process. (LoadLibraryA)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LoadLibraryA는 GetModuleHandleA와 똑같이 해당 모듈의 ImageBase를 반환한다.&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;차이점은 GetModuleHandleA 모듈이 로드되어 있어야 하는 것이라면 LoadLibraryA는 모듈이 로드되어 있지 않다면 해당 모듈을 로드하고 ImageBase를 반환한다. 즉 모듈이 존재하지 않는 이상 NULL이 반환되지 않는다.&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Modified Code&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1659126889236&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    ULONGLONG ImageBase = GetModuleHandleA(&quot;user32.dll&quot;);
    
    if (ImageBase == NULL)
        ImageBase = LoadLibrary(&quot;user32.dll&quot;);

    IMAGE_DOS_HEADER *DOS = ImageBase;
    printf(&quot;Image Dos Header : 0x%p\n&quot;, DOS);

    IMAGE_NT_HEADERS *NT = ImageBase + DOS-&amp;gt;e_lfanew;
    printf(&quot;Image Nt Header : 0x%p\n&quot;, NT);

    IMAGE_EXPORT_DIRECTORY *EXPORT = ImageBase + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    printf(&quot;Export Table : 0x%p\n&quot;, EXPORT);

    printf(&quot;Number Of Functions : %d\n&quot;, EXPORT-&amp;gt;NumberOfFunctions);
    printf(&quot;Number Of Names : %d\n&quot;, EXPORT-&amp;gt;NumberOfNames);

    DWORD *AddressOfFunctions = ImageBase + EXPORT-&amp;gt;AddressOfFunctions;
    DWORD *AddressOfNames = ImageBase + EXPORT-&amp;gt;AddressOfNames;
    WORD *AddressOfNameOrdinals = ImageBase + EXPORT-&amp;gt;AddressOfNameOrdinals;

    for (int i = 0; i &amp;lt; EXPORT-&amp;gt;NumberOfNames; i++)
    {
        printf(&quot;%s : %p\n&quot;, ImageBase + AddressOfNames[i], ImageBase + AddressOfFunctions[AddressOfNameOrdinals[i]]);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된 코드를 다시 컴파일해 실행해보면 정상적으로 실행되는 것을 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1659126997515&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Image Dos Header : 0x00007FFA16120000
Image Nt Header : 0x00007FFA161200F8
Export Table : 0x00007FFA161C1D50
Number Of Functions : 1215
Number Of Names : 1005
ActivateKeyboardLayout : 00007FFA1614C660
AddClipboardFormatListener : 00007FFA1614CE40
------------중략------------
wsprintfW : 00007FFA161499A0
wvsprintfA : 00007FFA161473F0
wvsprintfW : 00007FFA161499D0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 실제 EAT 후킹을 해볼 생각이다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/97</guid>
      <comments>https://crazyhacker.tistory.com/97#entry97comment</comments>
      <pubDate>Thu, 28 Jul 2022 02:31:13 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] EAT Hooking Step 0</title>
      <link>https://crazyhacker.tistory.com/95</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EAT Hooking&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;EAT(Export Address Table) Hooking&lt;/span&gt; 이란 EAT의 API 주소를 조작하여 후킹하는 기법을 말한다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;EAT에는 라이브러리가 외부로 Export 하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;함수명 또는 변수명과 주소&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;응용 프로그램 또는 다른 라이브러리가&amp;nbsp;&lt;a title=&quot;GetProcAddress&quot; href=&quot;https://docs.microsoft.com/ko-kr/cpp/build/getprocaddress&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GetProcAddress&lt;/a&gt;를 사용하여 라이브러리가 Export 하는 함수 또는 변수의 주소를 가져온다. 이때 &lt;span style=&quot;color: #ee2323;&quot;&gt;GetProcAddress API는 이 테이블을 참조하여 주소를 구한다&lt;/span&gt;. EAT Hooking은 이 원리를 이용한 후킹 기법이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EAT Structure&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EAT 구조는 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1659023890471&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Name;                  // 라이브러리의 이름
    DWORD Base;
    DWORD NumberOfFunctions;     // export 함수의 개수
    DWORD NumberOfNames;         // export 함수 중 이름을 가지는 함수의 개수
    DWORD AddressOfFunctions;    // 함수의 RVA를 가지는 배열의 시작 주소
    DWORD AddressOfNames;        // 함수 이름의 RVA를 가지는 배열의 시작 주소
    DWORD AddressOfNameOrdinals; // 이름이 있는 함수의 Oridnal 배열의 시작 주소
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;&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;1401&quot; data-origin-height=&quot;854&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n6BkD/btrIoAMgogX/kzibJ0VC0j9MK1kvQVRLlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n6BkD/btrIoAMgogX/kzibJ0VC0j9MK1kvQVRLlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n6BkD/btrIoAMgogX/kzibJ0VC0j9MK1kvQVRLlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn6BkD%2FbtrIoAMgogX%2FkzibJ0VC0j9MK1kvQVRLlK%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;1401&quot; height=&quot;854&quot; data-origin-width=&quot;1401&quot; data-origin-height=&quot;854&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;NumberOfFunctions&lt;/li&gt;
&lt;li&gt;NumberOfNames&lt;/li&gt;
&lt;li&gt;AddressOfFunctions&lt;/li&gt;
&lt;li&gt;AddressOfNames&lt;/li&gt;
&lt;li&gt;AddressOfNameOrdinals&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to get IMAGE_EXPORT_DIRECTORY address?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;IMAGE_EXPORT_DIRECTORY&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;&lt;span style=&quot;color: #333333;&quot;&gt;IMAGE_EXPORT_DIRECTORY는 NT Header(&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_nt_headers64&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IMAGE_NT_HEADER&lt;/a&gt;)를 통해 구할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;751&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bowbEK/btrInEHWhVA/8aHGjaGbRfkVuhs0grxWfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bowbEK/btrInEHWhVA/8aHGjaGbRfkVuhs0grxWfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bowbEK/btrInEHWhVA/8aHGjaGbRfkVuhs0grxWfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbowbEK%2FbtrInEHWhVA%2F8aHGjaGbRfkVuhs0grxWfk%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;1280&quot; height=&quot;751&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;751&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;1873&quot; data-origin-height=&quot;901&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxQXJ5/btrItuxt72D/3JtbZS1yB9lS70A5pjSuI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxQXJ5/btrItuxt72D/3JtbZS1yB9lS70A5pjSuI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxQXJ5/btrItuxt72D/3JtbZS1yB9lS70A5pjSuI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxQXJ5%2FbtrItuxt72D%2F3JtbZS1yB9lS70A5pjSuI1%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;1873&quot; height=&quot;901&quot; data-origin-width=&quot;1873&quot; data-origin-height=&quot;901&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NT Header의 Optional Header를 보면 DataDirectory가 배열로 존재한다. DataDirectory의 0번째 인덱스의 VirtualAddress가 IMAGE_EXPORT_DIRECTORY의 RVA이다. 코드로 나타낸다면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1659024703492&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;IMAGE_NT_HEADERS *NT;
IMAGE_IMPORT_DESCRIPTOR *IMPORT = ImageBase + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서 EAT를 이해하려고 하지 않아도 된다. 다음 포스팅부터 C언어로 작성된 코드를 보면 EAT에 대해 보다 빠르게 이해할 수 있을 것같다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/95</guid>
      <comments>https://crazyhacker.tistory.com/95#entry95comment</comments>
      <pubDate>Tue, 19 Jul 2022 23:44:20 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] WoW 프로세스의 커널 함수 호출 과정</title>
      <link>https://crazyhacker.tistory.com/88</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How are ntdll.dll and WoW ntdll.dll different?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ntdll.dll은 커널 함수가 정의 되어 있는 DLL이다. 유저 모드의 커널 함수들은 syscall을 통해 커널 함수를 호출할 수 있다. 하지만 운영체제(커널)은 64Bit이며 WoW 프로세스는 32Bit로 동작한다. 그렇기에 32Bit 프로세스는 syscall 하기 전 64Bit 모드로 전환할 필요가 있다.&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/AKR8b/btrHxL0yOuy/0JwIh1gsqjvkKVpBla9MtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AKR8b/btrHxL0yOuy/0JwIh1gsqjvkKVpBla9MtK/img.png&quot; data-origin-width=&quot;434&quot; data-origin-height=&quot;265&quot; data-is-animation=&quot;false&quot; style=&quot;width: 51.877%; margin-right: 10px;&quot; data-widthpercent=&quot;52.49&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AKR8b/btrHxL0yOuy/0JwIh1gsqjvkKVpBla9MtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAKR8b%2FbtrHxL0yOuy%2F0JwIh1gsqjvkKVpBla9MtK%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;434&quot; height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nvjkf/btrHrNliBeN/LODirHTsT5FWhsUmKk66hK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nvjkf/btrHrNliBeN/LODirHTsT5FWhsUmKk66hK/img.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;286&quot; data-is-animation=&quot;false&quot; style=&quot;width: 46.9603%;&quot; data-widthpercent=&quot;47.51&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nvjkf/btrHrNliBeN/LODirHTsT5FWhsUmKk66hK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNvjkf%2FbtrHrNliBeN%2FLODirHTsT5FWhsUmKk66hK%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;424&quot; height=&quot;286&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;lt;좌&amp;gt; WoW ntdll.dll &amp;lt;우&amp;gt; 64Bit ntdll.dll&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지와 같이 WoW ntdll.dll의 경우 syscall number를 eax 레지스터에 지정하고 &lt;code&gt;syscall&lt;/code&gt;이 아닌 &lt;code&gt;call edx&lt;/code&gt;로 어떠한 함수를 호출하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Which function is invoked using edx register?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;call edx&lt;/code&gt;는 &lt;code&gt;ntdll!Wow64SystemServiceCall&lt;/code&gt;함수를 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;349&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xUyF1/btrHul2C86t/rAg1P0Xd261KH2LKlmdotK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xUyF1/btrHul2C86t/rAg1P0Xd261KH2LKlmdotK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xUyF1/btrHul2C86t/rAg1P0Xd261KH2LKlmdotK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxUyF1%2FbtrHul2C86t%2FrAg1P0Xd261KH2LKlmdotK%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;349&quot; height=&quot;186&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 함수는 &lt;code&gt;ntdll!Wow64Transition&lt;/code&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;code&gt;ntdll!Wow64SystemServiceCall&lt;/code&gt;에서 &lt;code&gt;wow64cpu!KiFastSystemCall&lt;/code&gt;로 넘어가게 된다.&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/ewQGnk/btrHummWlIa/g8cRE1pdVSm4gVeFYaYSdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewQGnk/btrHummWlIa/g8cRE1pdVSm4gVeFYaYSdK/img.png&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;219&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.3661%; margin-right: 10px;&quot; data-widthpercent=&quot;48.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewQGnk/btrHummWlIa/g8cRE1pdVSm4gVeFYaYSdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FewQGnk%2FbtrHummWlIa%2Fg8cRE1pdVSm4gVeFYaYSdK%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;502&quot; height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lBz45/btrHtwDm7LN/yG976I4lMk1IolKRDaCqA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lBz45/btrHtwDm7LN/yG976I4lMk1IolKRDaCqA0/img.png&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;125&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;51.06&quot; data-filename=&quot;edited_blob&quot; style=&quot;width: 50.4711%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lBz45/btrHtwDm7LN/yG976I4lMk1IolKRDaCqA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlBz45%2FbtrHtwDm7LN%2FyG976I4lMk1IolKRDaCqA0%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;299&quot; height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;&amp;lt;좌&amp;gt; IDA Pro &amp;lt;우&amp;gt; Cheat Engine x64&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 IDA Pro에서는 jmp far 어셈블리가 해석되지 않는다. 아무래도 Opcode 0xEA 어셈블리가 지원되지 않는 모양이다.&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;code&gt;jmp far 0033:XXXXXXXX&lt;/code&gt; 는 아래에 있는 &lt;code&gt;jmp qword ptr ds:[r15+0xF8]&lt;/code&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;여기부터는 64Bit 모드로 동작하게 된다. 계속해서 r15 레지스터에 어떤 값이 들어가 있는지 확인해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What is the value of the r15 register?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oq0Tg/btrHsEn7Tf0/Y39X7FzTmf8yXHuiQ4rQL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oq0Tg/btrHsEn7Tf0/Y39X7FzTmf8yXHuiQ4rQL0/img.png&quot; data-alt=&quot;점프하기 전 레지스터의 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oq0Tg/btrHsEn7Tf0/Y39X7FzTmf8yXHuiQ4rQL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOq0Tg%2FbtrHsEn7Tf0%2FY39X7FzTmf8yXHuiQ4rQL0%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;445&quot; height=&quot;140&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;점프하기 전 레지스터의 상태&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzZz5y/btrHuUDtRxR/wyC5dEdCVQlKKQ9SXSrf8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzZz5y/btrHuUDtRxR/wyC5dEdCVQlKKQ9SXSrf8K/img.png&quot; data-alt=&quot;r15 레지스터가 가르키는 주소로 이동해 값을 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzZz5y/btrHuUDtRxR/wyC5dEdCVQlKKQ9SXSrf8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzZz5y%2FbtrHuUDtRxR%2FwyC5dEdCVQlKKQ9SXSrf8K%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;574&quot; height=&quot;296&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;r15 레지스터가 가르키는 주소로 이동해 값을 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;r15가 0x77893620이고 해당 주소는 &lt;code&gt;wow64cpu!TurboThunkDispatch&lt;/code&gt;의 주소라는 것을 Windbg를 통해 알 수 있었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Where is the address to jump (jmp qword ptr ds:[r15+0xF8])&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;r15(0x77893620) + 0xF8 = 0x77893718&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0x77893718에는 &lt;code&gt;wow64cpu!CpupReturnFromSimulatedCode&lt;/code&gt;의 주소가 작성되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;574&quot; data-origin-height=&quot;77&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byhliD/btrHp5MMvx5/8XJYwRhwCYQg2MrJgbTABK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byhliD/btrHp5MMvx5/8XJYwRhwCYQg2MrJgbTABK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byhliD/btrHp5MMvx5/8XJYwRhwCYQg2MrJgbTABK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyhliD%2FbtrHp5MMvx5%2F8XJYwRhwCYQg2MrJgbTABK%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;574&quot; height=&quot;77&quot; data-origin-width=&quot;574&quot; data-origin-height=&quot;77&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 64Bit 모드로 전환하고 점프(호출)하는 함수를 알아낼 수 있었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;wow64cpu!CpupReturnFromSimulatedCode&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 함수의 어셈블리를 먼저 확인해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;wow64cpu!CpupReturnFromSimulatedCode&lt;/code&gt;, &lt;code&gt;wow64cpu!TurboDispatchJumpAddressStart&lt;/code&gt;, &lt;code&gt;wow64cpu!ServiceNoTurbo&lt;/code&gt;함수가 있는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;761&quot; data-origin-height=&quot;291&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6rWpK/btrHvoEQCVK/Os2LE240wuJgWNfCes4WU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6rWpK/btrHvoEQCVK/Os2LE240wuJgWNfCes4WU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6rWpK/btrHvoEQCVK/Os2LE240wuJgWNfCes4WU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6rWpK%2FbtrHvoEQCVK%2FOs2LE240wuJgWNfCes4WU1%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;761&quot; height=&quot;291&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;291&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;wow64cpu!CpupReturnFromSimulatedCode&lt;/code&gt;와 &lt;code&gt;wow64cpu!TurboDispatchJumpAddressStart&lt;/code&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;code&gt;wow64cpu!TurboDispatchJumpAddressStart&lt;/code&gt;에서 &lt;code&gt;jmp qword ptr ds:[r15+rcx*8]&lt;/code&gt;을 하게 되는데 디버깅 결과, &lt;code&gt;wow64cpu!ServiceNoTurbo&lt;/code&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;code&gt;wow64cpu!ServiceNoTurbo&lt;/code&gt;는 &lt;code&gt;wow64cpu!TurboDispatchJumpAddressEnd&lt;/code&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;code&gt;call qword ptr ds:[wow64cpu!_imp_Wow64SystemServiceEx]&lt;/code&gt;이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;wow64cpu!_imp_Wow64SystemServiceEx&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심볼 네이밍을 보면 &lt;code&gt;Wow64SystemServiceEx&lt;/code&gt;를 &lt;code&gt;wow64cpu.dll&lt;/code&gt;이 import 하기 때문에 IAT에 등록되어 있음을 알 수 있다.&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;code&gt;Wow64SystemServiceEx&lt;/code&gt;는 &lt;code&gt;wow64.dll&lt;/code&gt;에 존재하는 것을 확인 했고 해당 함수를 IDA Pro로 확인해보았다.&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;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;__int64 __fastcall Wow64SystemServiceEx(unsigned int SyscallNumber, __int64 a2)
{
  struct _TEB *v3; // rdi
  __int64 v4; // r8
  __int64 v5; // rdx
  struct _TEB *v6; // rbx
  __int64 v7; // rax
  __int64 (__fastcall *v8)(__int64); // rsi
  _QWORD *v9; // rsi
  __int64 *v10; // rdi
  __int64 *v11; // rax
  __int64 v12; // rcx
  _QWORD *v14; // rcx
  unsigned int v15; // [rsp+20h] [rbp-898h]
  PVOID v16; // [rsp+38h] [rbp-880h] BYREF
  int v17; // [rsp+40h] [rbp-878h]
  char v18[8]; // [rsp+48h] [rbp-870h] BYREF
  __int64 v19; // [rsp+50h] [rbp-868h]
  unsigned int v20; // [rsp+58h] [rbp-860h]
  unsigned int v21; // [rsp+5Ch] [rbp-85Ch]
  unsigned int v22; // [rsp+60h] [rbp-858h]
  char v23; // [rsp+64h] [rbp-854h]
  PVOID v24; // [rsp+70h] [rbp-848h] BYREF
  __int64 v25[259]; // [rsp+78h] [rbp-840h] BYREF
  __int64 v26; // [rsp+890h] [rbp-28h] BYREF

  v16 = NtCurrentTeb()-&amp;gt;TlsSlots[12];
  v3 = 0i64;
  v17 = 0;
  NtCurrentTeb()-&amp;gt;TlsSlots[12] = &amp;amp;v16;
  v4 = (SyscallNumber &amp;gt;&amp;gt; 12) &amp;amp; 3;
  v5 = SyscallNumber &amp;amp; 0xFFF;
  if ( (unsigned int)v5 &amp;gt; LODWORD(ServiceTables[3 * v4 + 1]) )
  {
    v15 = 0xC000001C;
  }
  else
  {
    v6 = NtCurrentTeb();
    v7 = (int)v6-&amp;gt;SpareUlong0;
    if ( (_DWORD)v7 )
    {
      if ( (int)v7 &amp;lt; 0 )
        v3 = v6;
      else
        v3 = (struct _TEB *)((char *)v6 + v7);
    }
    v24 = v6-&amp;gt;TlsSlots[3];
    v25[1] = (__int64)v25;
    v25[0] = (__int64)v25;
    v25[2] = (__int64)&amp;amp;v26;
    v6-&amp;gt;TlsSlots[3] = &amp;amp;v24;
    v8 = *(__int64 (__fastcall **)(__int64))(*(_QWORD *)&amp;amp;ServiceTables[3 * v4] + 8 * v5);
    v20 = (SyscallNumber &amp;gt;&amp;gt; 12) &amp;amp; 3;
    v21 = SyscallNumber &amp;amp; 0xFFF;
    v6-&amp;gt;LastErrorValue = HIDWORD(v3-&amp;gt;NtTib.Self);
    if ( pfnWow64LogSystemService )
    {
      v19 = a2;
      v23 = 0;
      Wow64LogSystemServiceWrapper(v18);
      v15 = v8(a2);
      v23 = 1;
      v22 = v15;
      Wow64LogSystemServiceWrapper(v18);
    }
    else if ( v8 == whNtSetTimerEx )
    {
      v15 = whNtSetTimerEx(a2);
    }
    else if ( v8 == whNtCallbackReturn )
    {
      v15 = whNtCallbackReturn(a2);
    }
    else if ( v8 == whNtQueryVirtualMemory )
    {
      v15 = whNtQueryVirtualMemory(a2);
    }
    else if ( v8 == whNtOpenKeyEx )
    {
      v15 = whNtOpenKeyEx(a2);
    }
    else if ( v8 == whNtQueryValueKey )
    {
      v15 = whNtQueryValueKey(a2);
    }
    else
    {
      v15 = v8(a2);
    }
    HIDWORD(v3-&amp;gt;NtTib.Self) = v6-&amp;gt;LastErrorValue;
    v9 = v6-&amp;gt;TlsSlots[3];
    v10 = v9 + 1;
    v11 = (__int64 *)v9[1];
    v12 = *v11;
    if ( (_QWORD *)v11[1] != v9 + 1 || *(__int64 **)(v12 + 8) != v11 )
      __fastfail(3u);
    *v10 = v12;
    for ( *(_QWORD *)(v12 + 8) = v10; v11 != v10; v14[1] = v10 )
    {
      RtlFreeHeap(NtCurrentPeb()-&amp;gt;ProcessHeap, 0, v11);
      v11 = (__int64 *)*v10;
      v14 = *(_QWORD **)*v10;
      if ( *(__int64 **)(*v10 + 8) != v10 || (__int64 *)v14[1] != v11 )
        __fastfail(3u);
      *v10 = (__int64)v14;
    }
    v6-&amp;gt;TlsSlots[3] = (PVOID)*v9;
  }
  NtCurrentTeb()-&amp;gt;TlsSlots[12] = v16;
  if ( *(_DWORD *)(Wow64InfoPtr + 8) &amp;amp;&amp;amp; (v17 &amp;amp; 3) == 0 &amp;amp;&amp;amp; (v17 &amp;amp; 4) == 0 )
    Wow64SetupForInstrumentationReturn();
  return v15;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;__int128 ServiceTables[];

__int64 __fastcall Wow64SystemServiceEx(unsigned int SyscallNumber, __int64 a2)
{
  .....
  v4 = (SyscallNumber &amp;gt;&amp;gt; 12) &amp;amp; 3; // Syscall Number가 정상이라면 0
  v5 = SyscallNumber &amp;amp; 0xFFF;     // Syscall Number가 정상이라면 0
  /*
    LODWORD(ServiceTables[3 * v4 + 1])의 값이 정상적인 Syscall Number를
    인자로 받은 호출이라면 0x1000이 된다. 그러기에 반드시 else 빠지는 것이
    정상적인 진행이다.
  */
  if ( (unsigned int)v5 &amp;gt; LODWORD(ServiceTables[3 * v4 + 1]) )
  {
    v15 = 0xC000001C;
  }
  else
  {
    ....
    //whNtXXXXX Syscall Number에 맞는 함수 주소를 가져옴
    v8 = *(__int64 (__fastcall **)(__int64))(*(_QWORD *)&amp;amp;ServiceTables[3 * v4] + 8 * v5);
    v20 = (SyscallNumber &amp;gt;&amp;gt; 12) &amp;amp; 3;
    v21 = SyscallNumber &amp;amp; 0xFFF;
    v6-&amp;gt;LastErrorValue = HIDWORD(v3-&amp;gt;NtTib.Self);
    if ( pfnWow64LogSystemService )
    {
      v19 = a2;
      v23 = 0;
      Wow64LogSystemServiceWrapper(v18);
      v15 = v8(a2);
      v23 = 1;
      v22 = v15;
      Wow64LogSystemServiceWrapper(v18);
    }
    else if ( v8 == whNtSetTimerEx )
    {
    ....
    else
    {
      v15 = v8(a2); // whNtxxxxxx 함수 호출
    }
    ....
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석해본 결과 &lt;code&gt;v8&lt;/code&gt;에 현재 호출한 커널 함수 이름의 wh(ex: whNtxxxxxxx)를 붙인 함수의 주소를 저장한다.&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;code&gt;NtOpenProcess&lt;/code&gt;를 호출했다면, &lt;code&gt;v8&lt;/code&gt;에는 &lt;code&gt;whNtOpenProcess&lt;/code&gt;의 주소가 담긴다. 그리고 해당 함수들이 &lt;code&gt;v15 = v8(a2)&lt;/code&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;code&gt;v15 = v8(a2)&lt;/code&gt; 라인에서 실행하지 않고 if문으로 실행하는 루틴이 빠져있다. 왜 인지는 모르겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;537&quot; data-origin-height=&quot;515&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/leUGZ/btrHoOrNcbS/Jk2FIcN1BwRctHK942YsuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/leUGZ/btrHoOrNcbS/Jk2FIcN1BwRctHK942YsuK/img.png&quot; data-alt=&quot;일부 커널 함수들은 따로 if문으로 걸러내어 호출하게 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/leUGZ/btrHoOrNcbS/Jk2FIcN1BwRctHK942YsuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FleUGZ%2FbtrHoOrNcbS%2FJk2FIcN1BwRctHK942YsuK%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;537&quot; height=&quot;515&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;515&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일부 커널 함수들은 따로 if문으로 걸러내어 호출하게 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;What is the whNtxxxxxxx function in wow64.dll?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;whNtxxxxxxxx&lt;/code&gt; 함수는 실제 &lt;code&gt;Ntxxxxxxx&lt;/code&gt; 함수를 호출하기 전에 호출되는 함수이다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;NTSTATUS __fastcall whNtOpenProcess(unsigned int *a1)
{
  _DWORD *v1; // rdi
  ACCESS_MASK v2; // er14
  int *v3; // rsi
  void **v4; // rbx
  struct _CLIENT_ID *v5; // r9
  NTSTATUS result; // eax
  __int64 v7; // [rsp+0h] [rbp-68h] BYREF
  int v8; // [rsp+20h] [rbp-48h]
  __int64 v9; // [rsp+28h] [rbp-40h] BYREF
  POBJECT_ATTRIBUTES ObjectAttributes; // [rsp+30h] [rbp-38h] BYREF
  __int64 *v11; // [rsp+38h] [rbp-30h]
  struct _CLIENT_ID ClientId; // [rsp+40h] [rbp-28h] BYREF

  v11 = &amp;amp;v7;
  v1 = (_DWORD *)*a1;
  v2 = a1[1];
  v3 = (int *)a1[3];
  v9 = 0i64;
  v4 = (void **)((unsigned __int64)&amp;amp;v9 &amp;amp; -(__int64)((_DWORD)v1 != 0));
  v8 = Wow64ShallowThunkAllocObjectAttributes32TO64_FNC((_DWORD *)a1[2], (__int64 *)&amp;amp;ObjectAttributes);
  if ( v8 &amp;lt; 0 )
  {
    local_unwind_0(v11, &amp;amp;loc_18000BADF);
  }
  else if ( (_DWORD)v3 )
  {
    v5 = &amp;amp;ClientId;
    ClientId.UniqueThread = (HANDLE)v3[1];
    ClientId.UniqueProcess = (HANDLE)*v3;
    goto LABEL_4;
  }
  v5 = 0i64;
LABEL_4:
  result = NtOpenProcess(v4, v2, ObjectAttributes, v5);
  if ( (_DWORD)v1 )
    *v1 = *(_DWORD *)v4;
  return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나도 아직 정확히 모든 분석을 끝내지는 못하였지만 a1은 Ntxxxxxxx 함수의 인자가 담겨있는 스택의 주소인 것으로 추정된다.&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;x86 ntdll.dll에서 호출된 커널함수의 인자는 x86 아키텍쳐에 맞춰 정렬되어 있기 때문에 해당 구조(체)를 x64 아키텍쳐 맞춰서 변환하는 작업을 하는 것으로 보인다.&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;code&gt;whNtxxxxxxx&lt;/code&gt; 함수는 x86 아키텍쳐에 맞춰진 인자들을 실제 커널 함수(Ntxxxxxxx)를 호출하기 전에 x64 아키텍쳐에 맞춰 세팅하고 커널 함수를 호출하는 것으로 확인된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WoW 프로세스의 커널 함수 호출 과정&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;code&gt;Ntxxxxxxxxx&lt;/code&gt; (ntdll.dll x86)&lt;br /&gt;2. &lt;code&gt;Wow64SystemServiceCall&lt;/code&gt; -&amp;gt; &lt;code&gt;Wow64Transition&lt;/code&gt; 참조 (wow64cpu.dll)&lt;br /&gt;3. &lt;code&gt;KiFastSystemCall&lt;/code&gt; (wow64cpu.dll)&lt;br /&gt;4. &lt;code&gt;CpupReturnFromSimulatedCode&lt;/code&gt; (wow64cpu.dll)&lt;br /&gt;5. &lt;code&gt;TurboDispatchJumpAddressStart&lt;/code&gt; (wow64cpu.dll)&lt;br /&gt;6. &lt;code&gt;TurboDispatchJumpAddressEnd(ServiceNoTurbo)&lt;/code&gt; (wow64cpu.dll)&lt;br /&gt;7. &lt;code&gt;Wow64SystemServiceEx&lt;/code&gt; (wow64.dll)&lt;br /&gt;8. &lt;code&gt;whNtxxxxxxxxx&lt;/code&gt; (wow64.dll)&lt;br /&gt;9. &lt;code&gt;Ntxxxxxxxxx&lt;/code&gt; (ntdll.dll x64)&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/88</guid>
      <comments>https://crazyhacker.tistory.com/88#entry88comment</comments>
      <pubDate>Tue, 14 Jun 2022 11:09:22 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] Windbg를 이용해 WoW 프로세스 디버깅하기</title>
      <link>https://crazyhacker.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;나는 지금까지 WoW(Windows on Windows) 프로세스를 완벽하게 디버깅하기 위해서는 CheatEngine을 사용해야 한다고 생각했다. 왜냐하면 CS 레지스터의 값이 바뀌면서 모드가 변경되면 일반적인 디버거들은 오류를 일으키거나 해당 부분을 건너뛰어서 디버깅을 했다. 그렇기 때문에 CheatEngine을 사용해야한다고 생각했는데 해당 CheatEngine도 불편해서 사실상 제대로된 디버깅은 해본적이 없다. 그런데 Windbg를 이용하면 정상적으로 디버깅이 가능하다는 글을 보게되었다. 당연한 사실이지만 생각보다 지원되는 기능들이 많아서 너무 편하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to Debug for WoW Process use Windbg&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱히 특별한 방법이 있는건 아니다. 아래 페이지에서 설치관리자를 다운받고 실행하면 된다.&lt;/p&gt;
&lt;figure id=&quot;og_1655070791474&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Windows SDK - Windows 앱 개발&quot; data-og-description=&quot;Windows 11 Windows SDK에는 Windows 실행되는 앱을 만들 때 사용할 수 있는 헤더, 라이브러리 및 도구가 포함되어 있습니다.&quot; data-og-host=&quot;developer.microsoft.com&quot; data-og-source-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/windows-sdk/&quot; data-og-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/windows-sdk/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ba9k8J/hyOJHD04ib/rxp9h1L4hXVk5ibQNTonQ1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/windows-sdk/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.microsoft.com/ko-kr/windows/downloads/windows-sdk/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ba9k8J/hyOJHD04ib/rxp9h1L4hXVk5ibQNTonQ1/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;Windows SDK - Windows 앱 개발&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Windows 11 Windows SDK에는 Windows 실행되는 앱을 만들 때 사용할 수 있는 헤더, 라이브러리 및 도구가 포함되어 있습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치관리자에 보면 Windbg를 설치하는 부분에 체크하고 Next를 진행하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WoW 프로세스를 디버깅하기 위해서는 WinDbg (X64) 버전을 사용해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;783&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRAfwZ/btrExH22nF1/L4jtNJ2knp6IkYFV2SCBkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRAfwZ/btrExH22nF1/L4jtNJ2knp6IkYFV2SCBkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRAfwZ/btrExH22nF1/L4jtNJ2knp6IkYFV2SCBkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRAfwZ%2FbtrExH22nF1%2FL4jtNJ2knp6IkYFV2SCBkK%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;783&quot; height=&quot;640&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 WinDbg Preview 버전이 깔끔하고 멋지기 때문에 선호하지만 제대로 WoW 프로세스에 대해서 디버깅이 되지 않는 것같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1522&quot; data-origin-height=&quot;825&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bduy0u/btrEF8RU0e8/Cfnj2kBcjCpgDG1kdO7Ik0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bduy0u/btrEF8RU0e8/Cfnj2kBcjCpgDG1kdO7Ik0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bduy0u/btrEF8RU0e8/Cfnj2kBcjCpgDG1kdO7Ik0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbduy0u%2FbtrEF8RU0e8%2FCfnj2kBcjCpgDG1kdO7Ik0%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;1522&quot; height=&quot;825&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;825&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진처럼 Windbg를 실행했으면 [File]에서 여러 디버깅 방법들을 확인할 수 있다. 필자는 [Attach to a Process] 보다는 [Open Executable] 기능을 더 많이 사용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Windbg's WoW commands&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 85px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 6.2064%;&quot;&gt;!load wow64exts&lt;/td&gt;
&lt;td style=&quot;width: 25.1744%; height: 17px;&quot;&gt;디버거 확장 로드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 6.2064%;&quot;&gt;!wow64exts.sw&lt;/td&gt;
&lt;td style=&quot;width: 25.1744%; height: 17px;&quot;&gt;x86과 x64간 모드를 전환한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 6.2064%;&quot;&gt;!wow64exts.k &lt;i&gt;count&lt;/i&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25.1744%; height: 17px;&quot;&gt;32/64 비트 스택 추적을 덤프한다. &lt;i&gt;count&lt;/i&gt; 를 지정하면 지정된 개수의 주소를 덤프한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 6.2064%;&quot;&gt;!wow64exts.info&lt;/td&gt;
&lt;td style=&quot;width: 25.1744%; height: 17px;&quot;&gt;프로세스의 PEB, 현재 스레드의 TEB 및 WOW64에서 사용하는 스레드 TLS 슬롯에 대한 기본 정보를 덤프한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 6.2064%;&quot;&gt;!wow64exts.r &lt;i&gt;address&lt;/i&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25.1744%; height: 17px;&quot;&gt;지정된 주소에 대한 컨텍스트를 덤프한다. &lt;i&gt;address&lt;/i&gt;를 지정하지 않으면 프로세서에 대한 컨텍스트를 덤프한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;간단하게 Windbg를 이용해 WoW 프로세스를 디버깅하는 방법을 살펴보았다. 그리고 &lt;code&gt;!wow64exts.sw&lt;/code&gt; 명령을 사용하지 않더라도 디버거가 자동으로 모드를 전환해준다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/86</guid>
      <comments>https://crazyhacker.tistory.com/86#entry86comment</comments>
      <pubDate>Mon, 13 Jun 2022 07:13:06 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] Far와 Near 어셈블리 명령의 차이점</title>
      <link>https://crazyhacker.tistory.com/83</link>
      <description>&lt;figure id=&quot;og_1654015517652&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;[WoW] 32Bit 모드에서 64Bit 모드로 전환하기&quot; data-og-description=&quot;[WoW] 32Bit 응용 프로그램에서의 Kernel 함수 호출 Windows 64Bit에서 32Bit 응용 프로그램을 실행하고 디버거로 커널 함수의 어셈블리를 확인하면 대부분 다음과 같은 형식을 띄게 된다. mov eax, 0x00000026 #&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/82&quot; data-og-url=&quot;https://crazyhacker.tistory.com/82&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eEVnIr/hyOBKtOuo9/vDAWP9ldAF0PuVSvqXKJS1/img.png?width=486&amp;amp;height=104&amp;amp;face=0_0_486_104,https://scrap.kakaocdn.net/dn/AD5cG/hyOBxnKNUv/SFgaGkL2akB8mv2qUBQRpK/img.png?width=486&amp;amp;height=104&amp;amp;face=0_0_486_104,https://scrap.kakaocdn.net/dn/Yi2y6/hyOBIbFHA5/iBzrsDkVdSg6eAnjfbRfcK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/82&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/82&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eEVnIr/hyOBKtOuo9/vDAWP9ldAF0PuVSvqXKJS1/img.png?width=486&amp;amp;height=104&amp;amp;face=0_0_486_104,https://scrap.kakaocdn.net/dn/AD5cG/hyOBxnKNUv/SFgaGkL2akB8mv2qUBQRpK/img.png?width=486&amp;amp;height=104&amp;amp;face=0_0_486_104,https://scrap.kakaocdn.net/dn/Yi2y6/hyOBIbFHA5/iBzrsDkVdSg6eAnjfbRfcK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[WoW] 32Bit 모드에서 64Bit 모드로 전환하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[WoW] 32Bit 응용 프로그램에서의 Kernel 함수 호출 Windows 64Bit에서 32Bit 응용 프로그램을 실행하고 디버거로 커널 함수의 어셈블리를 확인하면 대부분 다음과 같은 형식을 띄게 된다. mov eax, 0x00000026 #&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 jmp far 라고하는 처음보는 형태의 어셈블리를 확인했었다. 그리고 해당 far 어셈블리는 CS 레지스터의 값을 변경하는 어셈블리였으며 32Bit 모드에서 64Bit 모드로 변경하기 위해서는 CS 레지스터의 값을 변경해야 한다는 것도 알았다. 이번 포스팅에서는 Far 어셈블리와 Near 어셈블리의 차이점을 알아보려고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;jmp instruction&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Opcode 0xE9 (Relative jump instruction, Near jump)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Opcode 0xE9를 사용한 상대거리를 이용한 점프 어셈블리 명령이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwf2qA/btrDESxJFim/uh67bHrqEPPmjHzkozxze1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwf2qA/btrDESxJFim/uh67bHrqEPPmjHzkozxze1/img.png&quot; data-alt=&quot;상대 거리를 사용하는 opcode 0xE9 어셈블리 명령어&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwf2qA/btrDESxJFim/uh67bHrqEPPmjHzkozxze1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcwf2qA%2FbtrDESxJFim%2Fuh67bHrqEPPmjHzkozxze1%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;506&quot; height=&quot;137&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상대 거리를 사용하는 opcode 0xE9 어셈블리 명령어&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;opcode인 0xE9가 존재하고 상대거리인 0x00000010이 operand로 들어가 있다. 해당 어셈블리 명령의 동작과정은 EIP(IP)에 operand를 더하는 방식으로 계산된다. (혹시라도 0x77F20FE5 주소로 점프하는지 이해가 안된다면 아래 접은 글을 확인하자)&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EIP는 다음에 실행할 명령의 주소를 갖고 있기 때문에 0x77F20FD0 주소의 명령어를 실행하는 동안의 EIP의 값은 0x77F20FD5가 되기 때문에 해당 주소에 0x00000010을 더한 0x77F20FE5로 점프하게 되는 원리이다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Opcode 0xEA (Static jump and change CS register instruction, Far jump)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Opcode 0xEA를 사용한 점프할 주소의 Code Segment를 지정하고 해당 주소로 점프하는 어셈블리 명령이다.&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/dr5RCE/btrDERli062/Y7BJAhCaDWzIqce2XIuI8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dr5RCE/btrDERli062/Y7BJAhCaDWzIqce2XIuI8k/img.png&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;121&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.7212%; margin-right: 10px;&quot; data-widthpercent=&quot;59.41&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dr5RCE/btrDERli062/Y7BJAhCaDWzIqce2XIuI8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdr5RCE%2FbtrDERli062%2FY7BJAhCaDWzIqce2XIuI8k%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;489&quot; height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdxuBb/btrDGMCMKm7/RvBXt8LMrPdzkeHv0cD9MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdxuBb/btrDGMCMKm7/RvBXt8LMrPdzkeHv0cD9MK/img.png&quot; data-origin-width=&quot;127&quot; data-origin-height=&quot;46&quot; data-is-animation=&quot;false&quot; style=&quot;width: 40.116%;&quot; data-widthpercent=&quot;40.59&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdxuBb/btrDGMCMKm7/RvBXt8LMrPdzkeHv0cD9MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdxuBb%2FbtrDGMCMKm7%2FRvBXt8LMrPdzkeHv0cD9MK%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;127&quot; height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;왼쪽은 어셈블리 명령, 오른쪽은 32Bit 에서의 Segment Register의 값&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;opcode 0xEA(jmp far) 어셈블리 명령은 다른 jmp 어셈블리 명령들과는 큰 차이가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;2개의 Operand를 가진다&lt;/li&gt;
&lt;li&gt;점프(이동)할 주소를 절댓값(static)으로 받는다.&lt;/li&gt;
&lt;li&gt;점프(이동)할 주소가 존재하는 Code Segment를 받는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 위 어셈블리에서 이동할 주소인 0x77F20FE5가 상대적으로 계산되어 있지 않다. 그리고 두번째 Operand로 해당 주소가 존재하는 Code Segment를 받았다. 해당 주소는 CS 0x0023에 존재하는 주소이기 때문에 0x0023으로 설정했다. 위 어셈블리를 실행하게 되면 CS Register의 값이 0x0023으로 변경되고 0x77F20FE5로 EIP가 이동하게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ret instruction&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Opcode 0xC3 (Near Return)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Opcode 0xC3를 사용한 리턴 어셈블리 명령이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;81&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvsfL/btrEzmRHUyZ/V90LkB6Kz8a29IB2fLSOc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvsfL/btrEzmRHUyZ/V90LkB6Kz8a29IB2fLSOc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvsfL/btrEzmRHUyZ/V90LkB6Kz8a29IB2fLSOc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqvsfL%2FbtrEzmRHUyZ%2FV90LkB6Kz8a29IB2fLSOc0%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;486&quot; height=&quot;81&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;81&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ret 어셈블리는 모두가 알다시피 return 하는 어셈블리이다. 기본적으로 현재 스택의 최상단에서 4 Byte를 꺼내 해당 주소로 점프하는 어셈블리이다. ret 어셈블리를 풀어 써보자면 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;pop eip&lt;/li&gt;
&lt;li&gt;jmp eip&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Opcode 0xCB (Change CS register instruction, Far Return)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Opcode 0xCB를 사용하는 리턴 어셈블리이다. 해당 어셈블리는 CS 레지스터를 변경한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;105&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bceXjC/btrEF7S6iTG/0u2OFhd20SakKSMFKUbhLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bceXjC/btrEF7S6iTG/0u2OFhd20SakKSMFKUbhLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bceXjC/btrEF7S6iTG/0u2OFhd20SakKSMFKUbhLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbceXjC%2FbtrEF7S6iTG%2F0u2OFhd20SakKSMFKUbhLk%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;477&quot; height=&quot;105&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;105&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 어셈블리는 똑같이 ret 어셈블리의 기능도 갖고 있으면서 동시에 CS 레지스터의 값을 변경할 수 있다. 그런데 이 CS 레지스터의 값을 변경하는 방식이 기존의 jmp 어셈블리와는 큰 차이가 있다. ret far 어셈블리의 동작 방식은 다음과 같다.&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;스택에서 4Byte를 꺼내 CS 레지스터의 넣는다. (pop cs)&lt;/li&gt;
&lt;li&gt;스택에서 4Byte를 꺼내 ret 한다. (ret 또는 pop eip; jmp eip)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 총 8Byte를 꺼내게 되는데 처음 4Byte는 CS 레지스터에 들어가고 그 다음 4Byte의 주소로 리턴하게 되는 원리이다.&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/83</guid>
      <comments>https://crazyhacker.tistory.com/83#entry83comment</comments>
      <pubDate>Wed, 1 Jun 2022 01:30:51 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] 32Bit 모드에서 64Bit 모드로 전환하기</title>
      <link>https://crazyhacker.tistory.com/82</link>
      <description>&lt;figure id=&quot;og_1652791913900&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;[WoW] 32Bit 응용 프로그램에서의 Kernel 함수 호출&quot; data-og-description=&quot;Windows 64Bit에서 32Bit 응용 프로그램을 실행하고 디버거로 커널 함수의 어셈블리를 확인하면 대부분 다음과 같은 형식을 띄게 된다. mov eax, 0x00000026 # Windows System Call Number mov edx, Wow64SystemSe..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/81&quot; data-og-url=&quot;https://crazyhacker.tistory.com/81&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uUC6h/hyOrhSKuDR/HUAtVwUHlkIDQS6jDlldrK/img.png?width=552&amp;amp;height=64&amp;amp;face=0_0_552_64,https://scrap.kakaocdn.net/dn/cH8Wst/hyOre9yKuN/fVMN7NOP7LDTuoTRn0k5T1/img.png?width=552&amp;amp;height=64&amp;amp;face=0_0_552_64,https://scrap.kakaocdn.net/dn/j53gj/hyOrc4Zkxb/HiwQgHBVKejfYdQAA2hwKk/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/81&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/81&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uUC6h/hyOrhSKuDR/HUAtVwUHlkIDQS6jDlldrK/img.png?width=552&amp;amp;height=64&amp;amp;face=0_0_552_64,https://scrap.kakaocdn.net/dn/cH8Wst/hyOre9yKuN/fVMN7NOP7LDTuoTRn0k5T1/img.png?width=552&amp;amp;height=64&amp;amp;face=0_0_552_64,https://scrap.kakaocdn.net/dn/j53gj/hyOrc4Zkxb/HiwQgHBVKejfYdQAA2hwKk/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[WoW] 32Bit 응용 프로그램에서의 Kernel 함수 호출&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Windows 64Bit에서 32Bit 응용 프로그램을 실행하고 디버거로 커널 함수의 어셈블리를 확인하면 대부분 다음과 같은 형식을 띄게 된다. mov eax, 0x00000026 # Windows System Call Number mov edx, Wow64SystemSe..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이전 포스팅&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RiYaN/btrDyF5RuOb/fxThrxiUbCg7DAaLPtPi5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RiYaN/btrDyF5RuOb/fxThrxiUbCg7DAaLPtPi5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RiYaN/btrDyF5RuOb/fxThrxiUbCg7DAaLPtPi5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRiYaN%2FbtrDyF5RuOb%2FfxThrxiUbCg7DAaLPtPi5K%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;753&quot; height=&quot;60&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;60&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 &lt;code&gt;jmp 0033:wow64cpu.dll+7009&lt;/code&gt; 라고 적힌 처음보는 jmp instrcution을 볼수 있었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 어셈블리를 Cheat Engine이 아닌 일반적인 디버거(&lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;OllyDbg, x64dbg&lt;/span&gt;)에서는 다르게 표시된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ImZZE/btrDE9L00Lw/r8uJ6fczkls3UnzQseVEt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ImZZE/btrDE9L00Lw/r8uJ6fczkls3UnzQseVEt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ImZZE/btrDE9L00Lw/r8uJ6fczkls3UnzQseVEt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FImZZE%2FbtrDE9L00Lw%2Fr8uJ6fczkls3UnzQseVEt0%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;486&quot; height=&quot;104&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;jmp far&lt;/code&gt;라는 instrcution으로 해석되는 것을 확인할 수 있는데 열심히 서치해본 결과 far 류의 어셈블리들은 절대주소 그리고 CS(Code Segment) 레지스터의 값을 변경한다는 사실을 알게 되었다.&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;해당 어셈블리는 CS 레지스터의 값을 변경하고 0x77DF7009의 주소로 점프한다. 그리고 해당 주소의 어셈블리를 확인해보면 &lt;code&gt;jmp qword ptr [r15+0xF8]&lt;/code&gt; 으로 64Bit에서 사용되는 레지스터를 사용하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어셈블리를 분석해봤을 때 CS 레지스터의 값을 0x0033으로 변경하고 64Bit 어셈블리를 실행하는 것으로 보아 CS 레지스터의 값이 0x0033 이라면 64Bit 모드 0x0023 이라면 32Bit 모드 인것으로 생각된다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/82</guid>
      <comments>https://crazyhacker.tistory.com/82#entry82comment</comments>
      <pubDate>Tue, 31 May 2022 23:23:33 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] 32Bit 응용 프로그램에서의 Kernel 함수 호출</title>
      <link>https://crazyhacker.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Windows 64Bit에서 32Bit 응용 프로그램을 실행하고 디버거로 커널 함수의 어셈블리를 확인하면 대부분 다음과 같은 형식을 띄게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1651559374776&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mov    eax, 0x00000026              # Windows System Call Number
mov    edx, Wow64SystemServiceCall  # 64비트 모드 전환 함수
call   edx                          # 모드 전환 함수 호출
ret                                 # 리턴&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 알고 있는 커널 함수의 호출은 syscall 어셈블리를 사용해 커널에 호출하게 된다. 하지만 Windows on Windows로 돌아가고 있는 32Bit 응용 프로그램은 syscall이 아닌 Wow64SystemServiceCall 이라는 함수를 호출하고 있다. 해당 함수는 Windows 64Bit 운영체제의 32Bit용 ntdll.dll에 존재하는 함수로써 32Bit 응용 프로그램이 커널 함수를 호출하면 해당 호출을 가로채게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 응용 프로그램은 32비트이지만 커널은 64비트로 동작하기 때문에 32Bit 응용 프로그램이 직접적으로 커널에 요청하지 못하도록 한다. 대신 Wow64SystemServiceCall 함수를 통하여 64비트 모드로 변경 후에 syscall 수행하고 다시 32비트 모드로 변경해 해당 반환값을 전달해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1651588417093&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;jmp dword ptr ds:[Wow64Transition] # Wow64Transition = wow64cpu.dll + 0x6000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wow64SystemServiceCall은 x86 ntdll.dll의 Wow64Transition이라는 전역변수의 값을 참조하여 wow64cpu.dll의 어느 공간으로 점프한다. 해당 주소는 wow64cpu.dll + 0x6000 주소로 점프한다. 치트엔진으로 해당 주소를 가보면 다음과 같은 어셈블리어를 볼수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/u9kzv/btrDAPTWC7x/mUwFZSOe8Zo4VQi4bY5PvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/u9kzv/btrDAPTWC7x/mUwFZSOe8Zo4VQi4bY5PvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/u9kzv/btrDAPTWC7x/mUwFZSOe8Zo4VQi4bY5PvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fu9kzv%2FbtrDAPTWC7x%2FmUwFZSOe8Zo4VQi4bY5PvK%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;753&quot; height=&quot;60&quot; data-origin-width=&quot;753&quot; data-origin-height=&quot;60&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 어셈블리를 확인해보면 처음보는 jmp insturction과 x64 시스템의 레지스터와 어셈블리어를 사용하는 것을 확인할 수 있었다.&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;이로써 32Bit 응용 프로그램은 64Bit로 모드를 전환하여 무언가를 수행한다는 것을 확인할 수 있었다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/81</guid>
      <comments>https://crazyhacker.tistory.com/81#entry81comment</comments>
      <pubDate>Wed, 4 May 2022 00:35:44 +0900</pubDate>
    </item>
    <item>
      <title>[WoW] WoW64(Windows on Windows 64-Bit)란?</title>
      <link>https://crazyhacker.tistory.com/80</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WoW64란?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WoW64는 Windows 64Bit 운영체제에서 Windows 32Bit 응용 프로그램을 실행할 수 있는 Windows 운영 체제의 하위 시스템이다. 과거 Windows 32Bit 운영체제에서는 Windows 16Bit 와의 호환성을 위해 Windows on Windows 라는 이름으로 등장시켰다. 하지만 현재 Windows 64Bit 운영체제에서는 Windows 16Bit 응용 프로그램은 동작하지 않는다. 해당 이유는 Windows 64Bit의 시스템 핸들의 크기 때문이라고 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;구현 세부 정보&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;wow64.dll - 포인터 및 호출 스택 조작과 32비트와 64비트 호출 간 변환하는 Windows NT 커널에 대한 핵신 인터페이스&lt;/li&gt;
&lt;li&gt;wow64cpu.dll - 32비트 애플리케이션(win32k thunk)에 적절한 진입점을 제공&lt;/li&gt;
&lt;li&gt;wow64win.dll - 프로세서를 32비트에서 64비트 모드로 전환하는 작업을 처리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른거 잘 모르겠고 오래전부터 64비트 운영체제에서 32비트 응용 프로그램이 동작하는 것을 신기하게 생각했고 또 어셈블리 공부를 위해 주로 32비트를 위주로 공부하다보니 64비트 커널 함수와 32비트 커널 함수의 차이점을 발견하게 되었다. 여기서 더 나아가 치트엔진으로 리버싱을 진행하다 32비트 응용 프로그램에서 64비트 레지스터와 어셈블리를 보게 되었고 이를 통해 32비트에서 64비트로 모드를 변경하는 방법이 있다는 것을 깨달았다. 그리고 그것을 Heaven's Gate라고 부르는 것을 알게되었다. 해당 카테고리에는 이 Heaven's Gate (WoW64) 에 대해 서술에 보려고 한다.&lt;/p&gt;</description>
      <category>Windows/Heaven's Gate (Windows on Windows x64)</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/80</guid>
      <comments>https://crazyhacker.tistory.com/80#entry80comment</comments>
      <pubDate>Tue, 3 May 2022 14:34:30 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x64 Step 2</title>
      <link>https://crazyhacker.tistory.com/79</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to patch the top 12 bytes of the API&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 후킹하고 싶은 API의 상위 12 바이트를 패치하는 것만 남았다. 기본적으로 DLL의 함수들은&amp;nbsp;&lt;code&gt;.text&lt;/code&gt;&amp;nbsp;섹션에 존재한다. 해당 섹션의 메모리 보호 옵션은 보통&lt;span&gt;&amp;nbsp;&lt;/span&gt;ER---&lt;span&gt;&amp;nbsp;&lt;/span&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;쓰기 권한이 빠져있다&lt;/span&gt;. 그렇기 때문에 먼저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;쓰기 권한을 부여해야만 한다&lt;/span&gt;. Windows API 중 특정 영역의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;메모리 보호 옵션을 수정하는 함수&lt;/span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;VirtualProtect&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651549935521&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;VirtualProtectEx function (memoryapi.h) - Win32 apps&quot; data-og-description=&quot;Changes the protection on a region of committed pages in the virtual address space of a specified process.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clF1M1/hyOcsOGecd/ZLuigKFfrWcgeEdyaaFgmK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clF1M1/hyOcsOGecd/ZLuigKFfrWcgeEdyaaFgmK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;VirtualProtectEx function (memoryapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Changes the protection on a region of committed pages in the virtual address space of a specified process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1651549935521&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA(&quot;user32.dll&quot;);
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
        hModule = LoadLibraryA(&quot;user32.dll&quot;);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, &quot;MessageBoxA&quot;);
    
    // 원본 메모리 보호 옵션을 저장할 변수
    DWORD OldProtect;
    
    /*
    VirtualProtect 함수를 사용해 MessageBoxA 주소로부터 12바이트 만큼의 메모리 보호 옵션을
    PAGE_EXECUTE_READWRITE(ERW--)로 변경한다.
    */
    if (VirtualProtect(pMessageBoxA, 12, PAGE_EXECUTE_READWRITE, &amp;amp;OldProtect) == FALSE)
    {
        printf(&quot;VirtualProtect Failed\n&quot;);
        return -1;
    }
    
    printf(&quot;Changed the top 12 bytes memory protection option in MessageBoxA to ERW--\n&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1651549935523&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Changed the top 12 bytes memory protection option in MessageBoxA to ERW--&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문자열이 출력되면 정상적으로 MessageBoxA 함수의 상위 12 바이트의 메모리 보호 옵션이 수정된 것이다. 수정된 이후에는 해당 영역의 데이터를 수정할 수 있게 된다. 이제 본격적으로 후킹을 시도해보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Let's try Trampoline Hooking!!&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후킹 함수가 호출되었을 때 원본 함수를 호출하기 위해서는 꼭 다시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;원본 코드로 복원 후 호출해야 하고&lt;/span&gt; 호출이 끝난 후에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;다시 후킹 코드로 패치&lt;/span&gt;해줘야 후킹이 유지될 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1651549935523&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

BYTE HookCode[12] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0 };
BYTE OriginCode[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

int __stdcall NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    // 상위 5 바이트를 원본 코드로 패치
    memcpy(MessageBoxA, OriginCode, 12);
    // lpText 변수를 조작해 함수를 정상적으로 실행
    int ret = MessageBoxA(hWnd, &quot;Hooked..!&quot;, lpCaption, uType);
    // 다시 후킹 코드로 패치
    memcpy(MessageBoxA, HookCode, 12);

    // 반환값 전달
    return ret;
}

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA(&quot;user32.dll&quot;);
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
        hModule = LoadLibraryA(&quot;user32.dll&quot;);

    if (hModule == NULL)
    {
        printf(&quot;[-] user32.dll not found\n&quot;);
        return -1;
    }

    printf(&quot;[+] user32.dll found!\n&quot;);

    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, &quot;MessageBoxA&quot;);
    
    if (pMessageBoxA == NULL)
    {
        printf(&quot;[-] MessageBoxA not found\n&quot;);
        return -1;
    }

    printf(&quot;[+] MessageBoxA found!\n&quot;);

    // 원본 메모리 보호 옵션을 저장할 변수
    DWORD OldProtect;
    
    /*
    VirtualProtect 함수를 사용해 MessageBoxA 주소로부터 5바이트 만큼의 메모리 보호 옵션을
    PAGE_EXECUTE_READWRITE(ERW--)로 변경한다.
    */
    if (VirtualProtect(pMessageBoxA, 12, PAGE_EXECUTE_READWRITE, &amp;amp;OldProtect) == FALSE)
    {
        printf(&quot;VirtualProtect Failed\n&quot;);
        return -1;
    }
    
    printf(&quot;[*] Changed the top 12 bytes memory protection option in MessageBoxA to ERW--\n&quot;);

    // 점프할 주소를 저장
    *(ULONGLONG *)(HookCode + 2) = (ULONGLONG)NewMessageBoxA;

    printf(&quot;[*] Patch code :    &quot;);
    
    for (int i = 0; i &amp;lt; 12; i++)
    	printf(&quot;0x%02X &quot;, HookCode[i]);
    
    putchar('\n');
    
    // 원본 12이트 백업
    memcpy(OriginCode, pMessageBoxA, 12);
    printf(&quot;[*] Original code : &quot;);
    
    for (int i = 0; i &amp;lt; 12; i++)
    	printf(&quot;0x%02X &quot;, OriginCode[i]);

	putchar('\n');

    // 후킹 코드로 패치
    memcpy(pMessageBoxA, HookCode, 12);

    printf(&quot;[+] Trampoline Hooking Success!\n&quot;);
    printf(&quot;Press the any key...&quot;);
    getchar();

    // 후킹된 MessageBoxA 함수 호출
    MessageBoxA(NULL, &quot;Not Hooked...!&quot;, &quot;Trampoline Hook&quot;, 0);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cQIVro/btrA6QOqRKa/tb6ksIESsOenaCL0YxCCRK/Trampoline%20Hook%20x64.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Trampoline Hook x64.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1651549935527&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[+] user32.dll found!
[+] MessageBoxA found!
[*] Changed the top 12 bytes memory protection option in MessageBoxA to ERW--
[*] Patch code :    0x48 0xB8 0x50 0x15 0x40 0x00 0x00 0x00 0x00 0x00 0xFF 0xE0 
[*] Original code : 0x48 0x83 0xEC 0x38 0x45 0x33 0xDB 0x44 0x39 0x1D 0x02 0x61 
[+] Trampoline Hooking Success!
Press the any key...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 실행되었다면 Press the any key가 출력되었을 때 아무 키를 입력하게 되면 코드와 다르게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;code&gt;Not Hooked...!&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;가 아닌&lt;span&gt;&amp;nbsp;&lt;code&gt;Hooked...!&lt;/code&gt;&amp;nbsp;라는&lt;/span&gt; 메시지를 출력한다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/79</guid>
      <comments>https://crazyhacker.tistory.com/79#entry79comment</comments>
      <pubDate>Tue, 3 May 2022 13:02:59 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x64 Step 1</title>
      <link>https://crazyhacker.tistory.com/78</link>
      <description>&lt;figure id=&quot;og_1651549697187&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;[Reversing] Trampoline(Inline) Hooking x86 Step 1&quot; data-og-description=&quot;[Reversing] Trampoline(Inline) Hooking x86 Step 0 Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/75&quot; data-og-url=&quot;https://crazyhacker.tistory.com/75&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bDsWHY/hyOgzkNSvQ/Rnylvk64TmdTGMrzA7D09k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/NovTw/hyOgn5KnI2/J9qQi6c374x49AuasfP16k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/JRxks/hyOfhGahvZ/sPY9pvs7vdK2cNpKYsSvu1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/75&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/75&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bDsWHY/hyOgzkNSvQ/Rnylvk64TmdTGMrzA7D09k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/NovTw/hyOgn5KnI2/J9qQi6c374x49AuasfP16k/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/JRxks/hyOfhGahvZ/sPY9pvs7vdK2cNpKYsSvu1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Reversing] Trampoline(Inline) Hooking x86 Step 1&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[Reversing] Trampoline(Inline) Hooking x86 Step 0 Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 Trampoline Hooking x64 Step 1은 존재하지 않는다. 기존의 Trampoline Hooking x86 Step 1의 내용과 같기 때문에 위 포스팅을 보고 진행하되 64비트 컴파일러를 사용하길 바란다.&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;그럼 Trampoline Hooking x64 Step 2에서 봐요~~~ ㅎㅅㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;포스팅 하나 덜었네...&lt;/s&gt;&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/78</guid>
      <comments>https://crazyhacker.tistory.com/78#entry78comment</comments>
      <pubDate>Tue, 3 May 2022 12:49:56 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x64 Step 0</title>
      <link>https://crazyhacker.tistory.com/77</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글을 읽기 전에 리버싱 또는 후킹에 대한 기본적이 지식이 없으신 분들이라면 아래 글을 모두 숙지 후에 와주세요.&lt;/p&gt;
&lt;figure id=&quot;og_1651547801458&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;[Reversing] Trampoline(Inline) Hooking x86 Step 0&quot; data-og-description=&quot;Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot; data-og-url=&quot;https://crazyhacker.tistory.com/74&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bPWJPH/hyOe5Ml8Lj/QPoDQEC7ZGA3Scp8HDkL51/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/klp8B/hyOgAcVcVv/CtO7CmiSB1QNuKbiv7KG10/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/PHKxz/hyOe56FAND/HKTnsJN7wkkuV3Q48Ee9n1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bPWJPH/hyOe5Ml8Lj/QPoDQEC7ZGA3Scp8HDkL51/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/klp8B/hyOgAcVcVv/CtO7CmiSB1QNuKbiv7KG10/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/PHKxz/hyOe56FAND/HKTnsJN7wkkuV3Q48Ee9n1/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Reversing] Trampoline(Inline) Hooking x86 Step 0&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Trampoline Hooking&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Trampoline Hooking&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때문에 위 설명에서 n바이트라고 하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to Trampoline Hooking from x64 system&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x64 시스템에서의 후킹 방법은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타겟 API의&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;상위 12바이트를 &lt;span style=&quot;color: #ee2323;&quot;&gt;mov&lt;span&gt; and &lt;/span&gt;&lt;/span&gt;jmp 어셈블리로 패치&lt;/span&gt;하여 후킹한다. 여기서 12바이트인 이유는 x64 시스템은 주소체계가 8바이트이기 때문에 기존의 x86의 후킹 방식으로는 &lt;span style=&quot;color: #ee2323;&quot;&gt;4바이트 이상의 범위에 있는 주소로는 점프하지 못한다&lt;/span&gt;는 단점이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 8바이트 주소 체계에서 계산한 상대 주소가 4바이트를 초과한다면&lt;span style=&quot;color: #ee2323;&quot;&gt; 기존의 5바이트를 이용한 jmp 어셈블리로는 타겟 주소까지 이동할 수 없는&lt;/span&gt; 일이 생기게 된다. 그렇기 때문에 x64 시스템에서 안정적으로 후킹을 하기 위해서는&lt;span style=&quot;color: #006dd7;&quot;&gt; 8바이트 주소로 점프할 수 있는 레지스터를 사용한 간접 점프(Indirect jump)를 이용&lt;/span&gt;한다면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to Trampoline Hooking using Indirect Jump from x64 system&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위에서 말했던 것처럼 12바이트를 이용한 mov and jmp 어셈블리 패치를 이용하면 된다. x64 시스템으로 넘어옴에 따라 레지스터도 기존 4바이트에서 8바이트로 드러났음을 알 수 있다. 이를 이용해 레지스터를 이용한 간접 점프를 활용해 x64 시스템에서 안정적인 후킹을 진행할 수 있다. x64 시스템에서의 후킹 방법은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;802&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l8Kzl/btrA6yHCer5/vfK9ndkBeLXUMDLXXy7hL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l8Kzl/btrA6yHCer5/vfK9ndkBeLXUMDLXXy7hL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l8Kzl/btrA6yHCer5/vfK9ndkBeLXUMDLXXy7hL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl8Kzl%2FbtrA6yHCer5%2FvfK9ndkBeLXUMDLXXy7hL1%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;766&quot; height=&quot;802&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;802&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x86 시스템과 다르게 바로 해당 주소로 점프하지 않고 레지스터에 주소를 넣은 후에 점프를 시도한다. (rax 레지스터를 사용하는 이유는 시스템에서 rax 레지스터의 값은 언제든 변경될 수 있기 때문에 중요한 값을 저장하지 않고 해당 값을 보존해 주지 않아도 되기 때문이다.) 또한 &lt;span style=&quot;color: #ee2323;&quot;&gt;점프할 주소까지의 상대거리를 구하지 않아도 된다&lt;/span&gt;는 장점이 존재한다. 다만 후킹하는 코드가 2배 이상 늘어났다...&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번 포스팅에서 x64 시스템의 후킹 방법에 대해서 간단하게 알아봤으며 x86 시스템의 후킹 방법을 채용할 수 없는 이유 또한 설명했다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/77</guid>
      <comments>https://crazyhacker.tistory.com/77#entry77comment</comments>
      <pubDate>Tue, 3 May 2022 12:47:59 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x86 Step 2</title>
      <link>https://crazyhacker.tistory.com/76</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to patch the top 5 bytes of the API&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 후킹하고 싶은 API의 상위 5 바이트를 패치하는 것만 남았다. 기본적으로 DLL의 함수들은 &lt;code&gt;.text&lt;/code&gt; 섹션에 존재한다. 해당 섹션의 메모리 보호 옵션은 보통 &lt;code&gt;ER---&lt;/code&gt; 로 &lt;span style=&quot;color: #ee2323;&quot;&gt;쓰기 권한이 빠져있다&lt;/span&gt;. 그렇기 때문에 먼저 &lt;span style=&quot;color: #ee2323;&quot;&gt;쓰기 권한을 부여해야만 한다&lt;/span&gt;. Windows API 중 특정 영역의 &lt;span style=&quot;color: #ee2323;&quot;&gt;메모리 보호 옵션을 수정하는 함수&lt;/span&gt;는 &lt;code&gt;VirtualProtect&lt;/code&gt; 함수가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651255126320&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;VirtualProtectEx function (memoryapi.h) - Win32 apps&quot; data-og-description=&quot;Changes the protection on a region of committed pages in the virtual address space of a specified process.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clF1M1/hyOcsOGecd/ZLuigKFfrWcgeEdyaaFgmK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clF1M1/hyOcsOGecd/ZLuigKFfrWcgeEdyaaFgmK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;VirtualProtectEx function (memoryapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Changes the protection on a region of committed pages in the virtual address space of a specified process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1651255592846&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA(&quot;user32.dll&quot;);
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
        hModule = LoadLibraryA(&quot;user32.dll&quot;);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, &quot;MessageBoxA&quot;);
    
    // 원본 메모리 보호 옵션을 저장할 변수
    DWORD OldProtect;
    
    /*
    VirtualProtect 함수를 사용해 MessageBoxA 주소로부터 5바이트 만큼의 메모리 보호 옵션을
    PAGE_EXECUTE_READWRITE(ERW--)로 변경한다.
    */
    if (VirtualProtect(pMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &amp;amp;OldProtect) == FALSE)
    {
        printf(&quot;VirtualProtect Failed\n&quot;);
        return -1;
    }
    
    printf(&quot;Changed the top 5 bytes memory protection option in MessageBoxA to ERW--\n&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1651255847389&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Changed the top 5 bytes memory protection option in MessageBoxA to ERW--&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문자열이 출력되면 정상적으로 MessageBoxA 함수의 상위 5바이트의 메모리 보호 옵션이 수정된 것이다. 수정된 이후에는 해당 영역의 데이터를 수정할 수 있게 된다. 이제 본격적으로 후킹을 시도해보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Let's try Trampoline Hooking!!&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후킹 함수가 호출되었을 때 원본 함수를 호출하기 위해서는 꼭 다시 &lt;span style=&quot;color: #ee2323;&quot;&gt;원본 코드로 복원 후 호출해야 하고&lt;/span&gt; 호출이 끝난 후에는 &lt;span style=&quot;color: #ee2323;&quot;&gt;다시 후킹 코드로 패치&lt;/span&gt;해줘야 후킹이 유지될 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1651257064035&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

BYTE HookCode[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
BYTE OriginCode[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };

int __stdcall NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    // 상위 5 바이트를 원본 코드로 패치
    memcpy(MessageBoxA, OriginCode, 5);
    // lpText 변수를 조작해 함수를 정상적으로 실행
    int ret = MessageBoxA(hWnd, &quot;Hooked..!&quot;, lpCaption, uType);
    // 다시 후킹 코드로 패치
    memcpy(MessageBoxA, HookCode, 5);

    // 반환값 전달
    return ret;
}

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA(&quot;user32.dll&quot;);
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
        hModule = LoadLibraryA(&quot;user32.dll&quot;);

    if (hModule == NULL)
    {
        printf(&quot;[-] user32.dll not found\n&quot;);
        return -1;
    }

    printf(&quot;[+] user32.dll found!\n&quot;);

    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, &quot;MessageBoxA&quot;);
    
    if (pMessageBoxA == NULL)
    {
        printf(&quot;[-] MessageBoxA not found\n&quot;);
        return -1;
    }

    printf(&quot;[+] MessageBoxA found!\n&quot;);

    // 원본 메모리 보호 옵션을 저장할 변수
    DWORD OldProtect;
    
    /*
    VirtualProtect 함수를 사용해 MessageBoxA 주소로부터 5바이트 만큼의 메모리 보호 옵션을
    PAGE_EXECUTE_READWRITE(ERW--)로 변경한다.
    */
    if (VirtualProtect(pMessageBoxA, 5, PAGE_EXECUTE_READWRITE, &amp;amp;OldProtect) == FALSE)
    {
        printf(&quot;VirtualProtect Failed\n&quot;);
        return -1;
    }
    
    printf(&quot;[*] Changed the top 5 bytes memory protection option in MessageBoxA to ERW--\n&quot;);

    printf(&quot;[+] Calculate relative jump length\n&quot;);
    // 점프할 상대거리 계산후 변수에 저장
    *(DWORD *)(HookCode + 1) = (ULONG_PTR)NewMessageBoxA - (ULONG_PTR)pMessageBoxA - 5;

    printf(&quot;[*] Patch code :    0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n&quot;, 
        HookCode[0],
        HookCode[1],
        HookCode[2],
        HookCode[3],
        HookCode[4]
    );
    
    // 원본 5 바이트 백업
    memcpy(OriginCode, pMessageBoxA, 5);
    printf(&quot;[*] Original code : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n&quot;,
        OriginCode[0],
        OriginCode[1],
        OriginCode[2],
        OriginCode[3],
        OriginCode[4]
    );

    // 후킹 코드로 패치
    memcpy(pMessageBoxA, HookCode, 5);

    printf(&quot;[+] Trampoline Hooking Success!\n&quot;);
    printf(&quot;Press the any key...&quot;);
    getchar();

    // 후킹된 MessageBoxA 함수 호출
    MessageBoxA(NULL, &quot;Not Hooked...!&quot;, &quot;Trampoline Hook&quot;, 0);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/daHoAc/btrATcX2QYQ/uRvkn62zCUcQZPM5CHTgjK/Trampoline%20Hook%20x86.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Trampoline Hook x86.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1651257101193&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[+] user32.dll found!
[+] MessageBoxA found!
[*] Changed the top 5 bytes memory protection option in MessageBoxA to ERW--
[+] Calculate relative jump length
[*] Patch code :     0xE9 0x1B 0x09 0xAD 0x8A
[*] Original code :  0x8B 0xFF 0x55 0x8B 0xEC
[+] Trampoline Hooking Success!
Press the any key...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 실행되었다면 Press the any key가 출력되었을 때 아무 키를 입력하게 되면 코드와 다르게 &lt;code&gt;Not Hooked...!&lt;/code&gt; 가 아닌 &lt;code&gt;Hooked...!&lt;/code&gt; 라는 메시지를 출력한다.&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/76</guid>
      <comments>https://crazyhacker.tistory.com/76#entry76comment</comments>
      <pubDate>Fri, 29 Apr 2022 22:46:57 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x86 Step 1</title>
      <link>https://crazyhacker.tistory.com/75</link>
      <description>&lt;figure id=&quot;og_1651037993763&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;[Reversing] Trampoline(Inline) Hooking x86 Step 0&quot; data-og-description=&quot;Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때..&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot; data-og-url=&quot;https://crazyhacker.tistory.com/74&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/i3iPG/hyObsAN7Sj/Q5JmMp25spCQcwsi2lKk60/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/dmDUT1/hyOcy0s4ez/1n2x5Iq5b5h25Q22Tc6l9k/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/duP6kj/hyOcuKxyRP/eWGH2CQ1E1BExA6yzJn1NK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/74?category=1019167&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/i3iPG/hyObsAN7Sj/Q5JmMp25spCQcwsi2lKk60/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/dmDUT1/hyOcy0s4ez/1n2x5Iq5b5h25Q22Tc6l9k/img.png?width=800&amp;amp;height=505&amp;amp;face=0_0_800_505,https://scrap.kakaocdn.net/dn/duP6kj/hyOcuKxyRP/eWGH2CQ1E1BExA6yzJn1NK/img.jpg?width=1080&amp;amp;height=1080&amp;amp;face=0_0_1080_1080');&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;[Reversing] Trampoline(Inline) Hooking x86 Step 0&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 포스팅에서 간단히 Trampoline Hooking의 원리에 대해 공부했다. 이번 포스팅부터는 본격적으로 후킹을 하기 위해 사용할 함수들을 알아볼 생각이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to get MessageBoxA address&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651038869057&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    PVOID pMessageBoxA = (PVOID)GetProcAddress(GetModuleHandleA(&quot;user32.dll&quot;), &quot;MessageBoxA&quot;);
    
    // IAT에서 주소를 가져옴
    printf(&quot;MessageBoxA : 0x%p\n&quot;, MessageBoxA);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    printf(&quot;GetProcAddress MessageBoxA : 0x%p\n&quot;, pMessageBoxA);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cvKyNc/btrADSZ2Mso/q7Q0tyO6q64qVRKmEaG9T0/main.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;main.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 소스코드를 컴파일 해 실행해보면 다음과 같은 결과를 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1651039091541&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;MessageBoxA : 0x74E00CA0
GetProcAddress MessageBoxA : 0x74E00CA0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 위 소스코드를 다음과 같이 변경하고 다시 실행해보자&lt;/p&gt;
&lt;pre id=&quot;code_1651039229266&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    PVOID pMessageBoxA = (PVOID)GetProcAddress(GetModuleHandleA(&quot;user32.dll&quot;), &quot;MessageBoxA&quot;);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    printf(&quot;GetProcAddress MessageBoxA : 0x%p\n&quot;, pMessageBoxA);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cK0fNJ/btrADTSb13B/YRG0WB9bH2BYfrvyjkqsQ1/main2.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;main2.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 다음과 같은 결과를 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1651039270699&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GetProcAddress MessageBoxA : 0x00000000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런 경우가 발생할까? &lt;b&gt;GetProcAddress&lt;/b&gt;는 HMODULE을 사용해 함수의 주소를 가져오는 함수이다. 하지만 이번에는 함수의 주소를 정상적으로 가져오지 못했다. 위와 같은 결과가 나오는 원인은 &lt;b&gt;GetModuleHandleA&lt;/b&gt; 함수에 있다. 먼저 GetProcAddress의 문서를 읽어보면 이렇게 설명되어있다.&lt;/p&gt;
&lt;figure id=&quot;og_1651039455600&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;GetProcAddress function (libloaderapi.h) - Win32 apps&quot; data-og-description=&quot;Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Cv9YN/hyObAyQ4Hc/wMKbIcKn3VtsbMhQzQ6Um0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Cv9YN/hyObAyQ4Hc/wMKbIcKn3VtsbMhQzQ6Um0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;GetProcAddress function (libloaderapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;hModule&lt;/b&gt;은 함수 또는 변수를 포함하는 DLL 모듈에 대한 핸들이라고 설명되어 있고 &lt;span style=&quot;color: #006dd7;&quot;&gt;LoadLibrary, GetModuleHandle 등의 함수들이 이 핸들은 반환한다고 한다.&lt;/span&gt; 우리는 여기서 &lt;span style=&quot;color: #ee2323;&quot;&gt;GetModuleHandle 류의 함수&lt;/span&gt;를 사용했다. 이제 해당 함수의 문서를 읽어보자&lt;/p&gt;
&lt;figure id=&quot;og_1651039588197&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;GetModuleHandleA function (libloaderapi.h) - Win32 apps&quot; data-og-description=&quot;Retrieves a module handle for the specified module. The module must have been loaded by the calling process.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/boOGm0/hyOcvo9uy5/uoqxHTbiJFMqokKCKIig0K/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/boOGm0/hyOcvo9uy5/uoqxHTbiJFMqokKCKIig0K/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;GetModuleHandleA function (libloaderapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Retrieves a module handle for the specified module. The module must have been loaded by the calling process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;lpModuleName&lt;/b&gt;으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;로드된 모듈의 이름을 입력받는다.라고&lt;/span&gt; 되어있다. 여기서 공부를 좀 한 사람이라면 눈치를 챘을 것이라고 생각한다. 바로 첫 번째 코드는 MessageBoxA를 정적으로 사용했기 때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;IAT에 user32.dll이 등록되어 있어&lt;/span&gt; 프로세스가 실행됐을 때 user32.dll이 로드되었을 것이다. 그렇기에 GetModuleHandleA 함수를 사용했을 때 정상적으로 호출되었지만, 두 번째 코드에서는 MessageBoxA 함수를 사용하지 않았다. 그렇기 때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;IAT에 user32.dll이 등록되어 있지 않아&lt;/span&gt; 프로세스가 실행됐을 때 &lt;span style=&quot;color: #ee2323;&quot;&gt;user32.dll이 로드되지 않았던 것&lt;/span&gt;이다. 그래서 GetModuleHandleA 함수가 NULL 반환한 것이며 그로인해 GetProcAddress 역시 NULL을 반환한 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to fixed source code?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GetModuleHandleA와 거의 동일한 LoadLibraryA 함수가 존재한다. 해당 함수는 인자로 들어온 &lt;span style=&quot;color: #006dd7;&quot;&gt;DLL이 로드되어 있다면 HMODULE을 반환&lt;/span&gt;하고 &lt;span style=&quot;color: #006dd7;&quot;&gt;로드되어 있지 않다면 해당 DLL을 로드하고 HMODULE을 반환&lt;/span&gt;한다. 이 함수를 사용하면 해당 문제를 해결할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651039980682&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA(&quot;user32.dll&quot;);
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
    	hModule = LoadLibraryA(&quot;user32.dll&quot;);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, &quot;MessageBoxA&quot;);
    
    printf(&quot;GetProcAddress MessageBoxA : 0x%p\n&quot;, pMessageBoxA);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/1ETH7/btrADTkplsS/l934Aod7KSFso8oV68DKpk/main3.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;main3.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 정상적으로 실행된 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1651040036869&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GetProcAddress MessageBoxA : 0x74E00CA0&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이번 포스팅에서는 Trampoline Hooking을 하기위해 해당 함수의 원본(IAT가 아닌) 주소를 구하는 방법을 알아보았다. 다음 포스팅에서는 드디어 Trampoline Hooking의 예제가 나온다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/75</guid>
      <comments>https://crazyhacker.tistory.com/75#entry75comment</comments>
      <pubDate>Wed, 27 Apr 2022 14:49:49 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Trampoline(Inline) Hooking x86 Step 0</title>
      <link>https://crazyhacker.tistory.com/74</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Trampoline Hooking&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Trampoline Hooking&lt;/span&gt; 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때문에 위 설명에서 n바이트라고 하였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to Trampoline Hooking from x86 system&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;x86 시스템에서의 후킹 방법은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타겟 API의 &lt;span style=&quot;color: #ee2323;&quot;&gt;상위 5바이트를 jmp 어셈블리로 패치&lt;/span&gt;하여 후킹한다. 여기서 5바이트인 이유는 x86 시스템은 주소체계가 4바이트이기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;1바이트는 opcode 나머지 4바이트는 점프할 주소&lt;/span&gt;이다. (4바이트 jmp 어셈블리의 opcode는 0xE9 이다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 만약 우리가 점프하고 싶은 주소가 0x11223344 라면 다음과 같이 패치를 한다고 생각할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;795&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/twkE4/btrAxlCO8M8/Xpnk63PiiPhSpXRu9bN7Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/twkE4/btrAxlCO8M8/Xpnk63PiiPhSpXRu9bN7Ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/twkE4/btrAxlCO8M8/Xpnk63PiiPhSpXRu9bN7Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtwkE4%2FbtrAxlCO8M8%2FXpnk63PiiPhSpXRu9bN7Ik%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;1258&quot; height=&quot;795&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;795&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위와 같이 코드 패치를 진행한다면 프로그램은 &lt;span style=&quot;color: #ee2323;&quot;&gt;정상적으로 동작하지 않는다&lt;/span&gt;. 왜냐하면 opcode 0xE9는 jmp 할 &lt;span style=&quot;color: #ee2323;&quot;&gt;주소를 상대 주소로 계산&lt;/span&gt;하기 때문이다. 즉 &lt;span style=&quot;color: #006dd7;&quot;&gt;현재 주소로부터 점프할 주소까지의 상대적인 거리를 구해서 operand를 설정해줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;How to calculate relative address for use opcode 0xE9&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;opcode 0xE9의 operand로 사용되는 상대 주소를 구하는 방법은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;operand = TargetAddress - CurrentAddress - 5&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;혹시라도 왜 5를 빼는지가 궁금하다면 이유는 opcode 0xE9의 총길이가 5바이트이기 때문에 그래서 해당 길이만큼 빼주는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마무리&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이번 포스팅에서는 Trampoline Hooking의 대해서 간단하게 알아봤다. 필자는 IAT Hooking보다 Trampoline Hooking이 훨씬 구현하기 쉬우며 또 알아야 하는 배경지식도 더 적다고 생각한다. &lt;s&gt;그렇기 때문에 필자는 IAT Hooking은 한 번도 해본 적이 없으며 블로그를 쓰기 위해서 처음 공부하고 구현해봤다 ㅋㅋㅋㅋㅋ&lt;/s&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Reversing/Hooking</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/74</guid>
      <comments>https://crazyhacker.tistory.com/74#entry74comment</comments>
      <pubDate>Wed, 27 Apr 2022 01:00:45 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Code Injection + Trampoline(Inline) Hooking x86</title>
      <link>https://crazyhacker.tistory.com/73</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트램펄린(인라인) 후킹이란?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트램펄린 후킹이란 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;이름처럼 점프(뛴다)&lt;/b&gt;&lt;/span&gt;라는 이름에 걸맞은 후킹 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후킹 할 API 함수의 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;상위 5 Byte를 jmp 0x00000000 형태로 패치&lt;/span&gt;&lt;/b&gt;하여 해당 함수가 호출되었을 때 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;EIP(PC)&lt;/span&gt;&lt;/b&gt; 레지스터가 다른 함수의 주소로 변경되어 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;해당 함수로 점프&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;필자가 트램펄린 후킹을 공부했을 때(2019년도)에는 트램펄린 후킹 기술에 대해 검색을 하여도 x86 기반의 설명밖에 찾지 못하였다. 또 &lt;span style=&quot;color: #ee2323;&quot;&gt;x86과 x64 간의 트램폴린 후킹 기술의 구현 방법이 미세하게 다르다&lt;/span&gt;. 하지만 x64 시스템에서의 트램펄린 후킹 기술은 많이 알려지지 않은 것으로 보이며 찾을 수도 없었다. 그렇기에 필자는 독자적으로 방법을 구현하여(아닐 수도 있다) 사용하고 있었다. 그렇기 때문에 트램펄린 후킹에 대한 포스팅은 x86과 x64 2개로 나누기로 했다.&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;color: #ee2323;&quot;&gt; x86과 x64 시스템에서 모두 사용가능&lt;/span&gt;한 방법이며 &lt;span style=&quot;color: #ee2323;&quot;&gt;x64 시스템에서는 약간의 제약&lt;/span&gt;이 걸린다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 인젝션과 트램펄린 후킹의 조합&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드 인젝션은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Fileless&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;형식의 임의의 코드 주입 공격이다. 그리고 트램펄린 후킹은 프로세스의&lt;span&gt; 타겟 함수의 상위 5 바이트를&lt;/span&gt;&amp;nbsp;조작하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;특정 API의 제어권을 가로채는 기법&lt;/b&gt;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 두개의 기법을 적절히 활용하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Fileless 형식의 트램펄린 후킹&lt;/span&gt;&lt;/b&gt;을 할수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예제 코드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;figure id=&quot;og_1650861364764&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Code-Injection: Code Injection + Hooking sample&quot; data-og-description=&quot;Code Injection + Hooking sample. Contribute to jungjin0003/Code-Injection development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Code-Injection&quot; data-og-url=&quot;https://github.com/jungjin0003/Code-Injection&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cg1QgW/hyN9NSldFH/AgkAfLrNXKdcn2aELLdYMk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Code-Injection&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jungjin0003/Code-Injection&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cg1QgW/hyN9NSldFH/AgkAfLrNXKdcn2aELLdYMk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Code-Injection: Code Injection + Hooking sample&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Code Injection + Hooking sample. Contribute to jungjin0003/Code-Injection development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Code Injector&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;소스코드는 아래 더보기에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1650988339127&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;winternl.h&amp;gt;
#include &quot;../Library/Rlibloaderapi.h&quot;

WINBOOL CodePatch(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize)
{
    SIZE_T lpNumberOfBytesWritten = 0;
    return WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, &amp;amp;lpNumberOfBytesWritten) &amp;amp;&amp;amp; nSize == lpNumberOfBytesWritten;
}

PVOID CodeInjection(HANDLE hProcess, PVOID lpBuffer, SIZE_T nSize)
{
    // Allocate memory in target process
    PVOID BufferAddress = VirtualAllocEx(hProcess, NULL, nSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    if (BufferAddress == NULL)
    {
        return NULL;
    }

    SIZE_T NumberOfBytesWritten;

    // Write the lpBuffer in allocated memory
    if (WriteProcessMemory(hProcess, BufferAddress, lpBuffer, nSize, &amp;amp;NumberOfBytesWritten) == FALSE || nSize &amp;gt; NumberOfBytesWritten)
    {
        VirtualFreeEx(hProcess, BufferAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, BufferAddress, 0, MEM_RELEASE);
        return NULL;
    }

    return BufferAddress;
}

DWORD SearchCodePatchOffset(PVOID lpFunctionAddress, SIZE_T FunctionSize)
{
    for (int i = 0; i &amp;lt; FunctionSize - 8; i++)
    {
        // x86
        if (__SIZEOF_POINTER__ == 4 &amp;amp;&amp;amp; *(ULONG_PTR *)((ULONG_PTR)lpFunctionAddress + i) == 0x11223344)
            return i;
        // x64
        else if (__SIZEOF_POINTER__ == 8 &amp;amp;&amp;amp; *(ULONG_PTR *)((ULONG_PTR)lpFunctionAddress + i) == 0x1122334455667788)
            return i;
    }

    return -1;
}

int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    /*
    An error occurs in the following ways:
    return OriMessageBox(hWnd, &quot;Hooked..!&quot;, lpCaption. uType);
    The compiled &quot;Hooked..!&quot; in this code points to a section of the process with a pointer, 
    so another process Occur EXCEPTION_ACCESS_VIOLATION.
    Therefore, you must store all the strings in the stack.
    */
    // All strings should be used as follows
    char Text[] = &quot;Hooked..!&quot;;

    // Top 5 Bytes of MessageBoxA in user32.dll
    BYTE OriginCode[5] = { 
        0x8B, 0xFF, // mov edi, edi
        0x55,       // push ebp
        0x8B, 0xEC  // mov ebp, esp
    };
    
    // Variables to back up hook code
    BYTE HookCode[5];
    
    // 0x11223344 is code patched to original MessageBoxA address after Code Injection
    volatile int (WINAPI *OriMessageBox)(HWND, LPCSTR, LPCSTR, UINT) = 0x11223344;

    for (int i = 0; i &amp;lt; 5; i++)
    {
        // Backup hook code
        HookCode[i] = *(BYTE *)((ULONG_PTR)OriMessageBox + i);
        
        // Overwrite Top 5 Bytes of MessageBoxA to original code.
        // Trampoline(Inline) Hook code to Original code
        *(BYTE *)((ULONG_PTR)OriMessageBox + i) = OriginCode[i];
    }

    // call after Manipulate lpText parameter and save return value
    int ret = OriMessageBox(hWnd, Text, lpCaption, uType);

    // Overwrite with hook code again when function ends
    for (int i = 0; i &amp;lt; 5; i++)
        *(BYTE *)((ULONG_PTR)OriMessageBox + i) = HookCode[i];

    return ret;
}

BOOL Trampoline_Hook(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, PVOID lpNewApiAddress, SIZE_T NewApiSize)
{
    SIZE_T NumberOfBytesRead;

    // Code Injection of NewAPI(HOOK Function)
    PVOID NewApiAddress = CodeInjection(hProcess, lpNewApiAddress, NewApiSize);

    if (NewApiAddress == NULL)
        return FALSE;

    // Find address of target api
    PVOID ProcAddress = GetRemoteProcAddress(hProcess, GetRemoteModuleHandleA(hProcess, lpModuleName), lpProcName);

    if (ProcAddress == NULL)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }

    DWORD OldProtect;

    // Change memory protection option of Top 5 byte of target api (PAGE_EXECUTE_READ to PAGE_EXECUTE_READWRITE)
    if (VirtualProtectEx(hProcess, ProcAddress, 5, PAGE_EXECUTE_READWRITE, &amp;amp;OldProtect) == FALSE)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }

    // Assembly Code
    BYTE JmpCode[5] = { 
        0xE9, 0x00, 0x00, 0x00, 0x00 // jmp 0x00000000 (4Byte Relative jump)
    };

    // Calculate relative jump address
    // Relative Address = Target Address - Hook Address - 5 (5Byte is assembly length)
    // jmp NewApiAddress
    *(DWORD *)(JmpCode + 1) = (ULONG_PTR)NewApiAddress - (ULONG_PTR)ProcAddress - 5; 

    // Code patch 0x11223344 in new api
    if (CodePatch(hProcess, (ULONG_PTR)NewApiAddress + SearchCodePatchOffset(NewMessageBoxA, NewApiSize), &amp;amp;ProcAddress, 4) == FALSE)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }

    // Top 5 bytes code patch of target process
    if (CodePatch(hProcess, ProcAddress, JmpCode, 5) == FALSE)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }

    // Trampline(Inline) Hooking success!!
    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD PID = 0;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    if (Trampoline_Hook(hProcess, &quot;user32.dll&quot;, &quot;MessageBoxA&quot;, NewMessageBoxA, (ULONG_PTR)Trampoline_Hook - (ULONG_PTR)NewMessageBoxA))
        printf(&quot;Trampoline Hooking Success\n&quot;);
    else
        printf(&quot;Trampoline Hooking Failed\n&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/UvWEv/btrAsjSQkpQ/KNBA31fbmclyur9ydM4JOK/main.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;main.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.06MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;타겟 프로그램&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;소스코드는 아래 더보기에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1650988391391&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;windows.h&amp;gt;

#define SHOW_MESSAGEBOX 1

int (WINAPI *lpMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

VOID AddButton(HWND hWnd);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    RECT wr = { 0, 0, 500, 500};

    AdjustWindowRect(&amp;amp;wr, WS_OVERLAPPEDWINDOW, FALSE);

    WNDCLASSA wc = { 0, };

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wc.hInstance = hInstance;
    wc.lpszClassName = &quot;WindowsClass&quot;;
    wc.lpfnWndProc = WndProc;

    if (RegisterClassA(&amp;amp;wc) == 0)
        return -1;

    HWND hWnd = CreateWindowA(&quot;WindowsClass&quot;, &quot;Code Injection&quot;, WS_OVERLAPPEDWINDOW | WS_VISIBLE, GetSystemMetrics(SM_CXSCREEN) / 2 - 250, GetSystemMetrics(SM_CYSCREEN) / 2 - 250, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, NULL, NULL);
    lpMessageBoxA = GetProcAddress(GetModuleHandleA(&quot;user32.dll&quot;), &quot;MessageBoxA&quot;);

    MSG msg = { 0, };

    while (GetMessageA(&amp;amp;msg, NULL, 0, 0))
    {
        TranslateMessage(&amp;amp;msg);
        DispatchMessageA(&amp;amp;msg);
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_COMMAND:
        if (wParam == SHOW_MESSAGEBOX)
            lpMessageBoxA(hWnd, &quot;Not Hooked..!&quot;, &quot;Click Me!&quot;, 0);
    case WM_CREATE:
        AddButton(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
}

VOID AddButton(HWND hWnd)
{
    CreateWindowA(&quot;Button&quot;, &quot;Click Me!&quot;, WS_VISIBLE | WS_CHILD, 200, 225, 100, 50, hWnd, SHOW_MESSAGEBOX, NULL, NULL);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/djAI9Z/btrAx6LyWPV/LMbL3hj4eGCdw9YDyGW7p1/target.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;target.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.05MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과 확인&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/428279640&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/83J59/hyObpXYPan/kXvBlJjxJjLkUICkLrHVR0/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/cmEXX1/hyObzM58qf/ie5nK1bhCZAdKG3pKvDK30/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/428279640?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Reversing</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/73</guid>
      <comments>https://crazyhacker.tistory.com/73#entry73comment</comments>
      <pubDate>Mon, 25 Apr 2022 13:46:32 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Code Injection + IAT Hooking</title>
      <link>https://crazyhacker.tistory.com/72</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 인젝션과 IAT 후킹의 조합&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;코드 인젝션은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Fileless&lt;/b&gt;&lt;/span&gt; 형식의 임의의 코드 주입 공격이다. 그리고 IAT 후킹은 프로세스의 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Import Address Table&lt;/b&gt;&lt;/span&gt;을 조작하여 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;특정 API의 제어권을 가로채는 기법&lt;/b&gt;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이 두개의 기법을 적절히 활용하면 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Fileless 형식의 IAT 후킹&lt;/span&gt;&lt;/b&gt;을 할수 있다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예제 코드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;figure id=&quot;og_1650571641685&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Code-Injection: Code Injection + Hooking sample&quot; data-og-description=&quot;Code Injection + Hooking sample. Contribute to jungjin0003/Code-Injection development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Code-Injection&quot; data-og-url=&quot;https://github.com/jungjin0003/Code-Injection&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bYAe5u/hyN8vpnJfh/t5TfhGamyKp4lWYA7KYiNK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Code-Injection&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jungjin0003/Code-Injection&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bYAe5u/hyN8vpnJfh/t5TfhGamyKp4lWYA7KYiNK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Code-Injection: Code Injection + Hooking sample&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Code Injection + Hooking sample. Contribute to jungjin0003/Code-Injection development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Code Injector&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소스코드는 아래 더보기에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1650568919711&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;winternl.h&amp;gt;

#define IFREE(HeapBase) (RtlFreeHeap(_get_heap_handle(), 0, (HeapBase)) || 1)
#define Upper(s1)       (s1 &amp;gt;= 65 &amp;amp;&amp;amp; s1 &amp;lt;= 90 ? (char)s1 + 32 : s1)

WINBOOL CodePatch(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize)
{
    SIZE_T lpNumberOfBytesWritten = 0;
    return WriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, &amp;amp;lpNumberOfBytesWritten) &amp;amp;&amp;amp; nSize == lpNumberOfBytesWritten;
}

LPVOID FindIATAddress(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName)
{
    PROCESS_BASIC_INFORMATION pbi = { 0, };
    // NtQueryInformationProcess 함수로 타겟 프로세스의 PEB 주소를 구한다.
    NtQueryInformationProcess(hProcess, ProcessBasicInformation, &amp;amp;pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL);
    
    PVOID BaseAddress;
    // PEB 구조체에서 ImageBase를 읽어온다.
    if (ReadProcessMemory(hProcess, (ULONG_PTR)pbi.PebBaseAddress + 0x10, &amp;amp;BaseAddress, sizeof(ULONG_PTR), NULL) == FALSE)
    {
        return NULL;
    }

    IMAGE_DOS_HEADER *DOS = malloc(sizeof(IMAGE_DOS_HEADER));
    // 타겟 프로세스의 IMAGE_DOS_HEADER를 읽어온다.
    if (ReadProcessMemory(hProcess, BaseAddress, DOS, sizeof(IMAGE_DOS_HEADER), NULL) == FALSE &amp;amp;&amp;amp; IFREE(DOS))
    {
        return NULL;
    }

    IMAGE_NT_HEADERS *NT = malloc(sizeof(IMAGE_NT_HEADERS));
    // 타겟 프로세스의 IMAGE_NT_HEADER를 읽어온다.
    if (ReadProcessMemory(hProcess, (ULONG_PTR)BaseAddress + DOS-&amp;gt;e_lfanew, NT, sizeof(IMAGE_NT_HEADERS), NULL) == FALSE &amp;amp;&amp;amp; IFREE(DOS) &amp;amp;&amp;amp; IFREE(NT))
    {
        return NULL;
    }

    free(DOS);

    IMAGE_IMPORT_DESCRIPTOR *IMPORT = malloc(NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size);
    PVOID *FirstImport = IMPORT;
    // NT Header에서 IMAGE_IMPORT_DESCRIPTOR를 읽어온다.
    if (ReadProcessMemory(hProcess, (ULONG_PTR)BaseAddress + NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, IMPORT, NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size, NULL) == FALSE &amp;amp;&amp;amp; IFREE(NT) &amp;amp;&amp;amp; IFREE(IMPORT))
    {
        return NULL;
    }

    free(NT);
    // 타겟 DLL의 IMAGE_IMPORT_DESCRIPTOR를 찾는다.
    for (; IMPORT-&amp;gt;OriginalFirstThunk != NULL; IMPORT++)
    {
        // 현재 IMAGE_IMPORT_DESCRIPTOR의 DLL 이름과 타겟 DLL이름을 비교
        for (char ch, i = 0; ReadProcessMemory(hProcess, (ULONG_PTR)BaseAddress + IMPORT-&amp;gt;Name + i, &amp;amp;ch, 1, NULL); i++)
        {
            if (Upper(ch) != Upper(lpModuleName[i]))
                break;
            else if (ch == NULL &amp;amp;&amp;amp; lpModuleName[i] == NULL)
                goto FOUND_MODULE;
        }
        continue;
FOUND_MODULE:
        break;
    }

    if (IMPORT-&amp;gt;OriginalFirstThunk == NULL)
        return NULL;

    PVOID IATAddress = NULL;

    IMAGE_THUNK_DATA *THUNK = malloc(sizeof(IMAGE_THUNK_DATA));
    // 타겟 API의 IAT 주소를 구한다.
    for (int i = 0; ReadProcessMemory(hProcess, (ULONG_PTR)BaseAddress + IMPORT-&amp;gt;OriginalFirstThunk + i * sizeof(void *), THUNK, sizeof(IMAGE_THUNK_DATA), NULL) &amp;amp;&amp;amp; THUNK-&amp;gt;u1.AddressOfData != NULL; i++)
    {
        if (THUNK-&amp;gt;u1.Ordinal &amp;gt;= 0x80000000)
            continue;
        // Compare api name of current IMPORT-&amp;gt;OriginalFirstThunk to target api name
        for (char ch, j = 0; ReadProcessMemory(hProcess, (ULONG_PTR)BaseAddress + THUNK-&amp;gt;u1.AddressOfData + j + 2, &amp;amp;ch, 1, NULL); j++)
        {
            if (ch != lpProcName[j])
                break;
            else if (ch == NULL &amp;amp;&amp;amp; lpProcName[j] == NULL)
            {
                IATAddress = (ULONG_PTR)BaseAddress + IMPORT-&amp;gt;FirstThunk + i * sizeof(void *);
                goto FOUND_IAT;
            }
        }
    }
FOUND_IAT:
    free(THUNK);
    free(FirstImport);
    return IATAddress;
}

PVOID CodeInjection(HANDLE hProcess, PVOID lpBuffer, SIZE_T nSize)
{
    // 타겟 프로세스의 공간에 메모리 할당
    PVOID BufferAddress = VirtualAllocEx(hProcess, NULL, nSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    if (BufferAddress == NULL)
    {
        return NULL;
    }

    SIZE_T NumberOfBytesWritten;
    // 할당한 공간에 lpBuffer의 데이터를 작성
    if (WriteProcessMemory(hProcess, BufferAddress, lpBuffer, nSize, &amp;amp;NumberOfBytesWritten) == FALSE || nSize &amp;gt; NumberOfBytesWritten)
    {
        VirtualFreeEx(hProcess, BufferAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, BufferAddress, 0, MEM_RELEASE);
        return NULL;
    }

    return BufferAddress;
}

DWORD SearchCodePatchOffset(PVOID lpFunctionAddress, SIZE_T FunctionSize)
{
    for (int i = 0; i &amp;lt; FunctionSize - 8; i++)
    {
        // x86
        if (__SIZEOF_POINTER__ == 4 &amp;amp;&amp;amp; *(ULONG_PTR *)((ULONG_PTR)lpFunctionAddress + i) == 0x11223344)
            return i;
        // x64
        else if (__SIZEOF_POINTER__ == 8 &amp;amp;&amp;amp; *(ULONG_PTR *)((ULONG_PTR)lpFunctionAddress + i) == 0x1122334455667788)
            return i;
    }

    return -1;
}

int WINAPI NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    /*
    다음과 같은 방법으로 호출하면 에러가 발생한다.
    return OriMessageBox(hWnd, &quot;Hooked..!&quot;, lpCaption. uType);
    해당 코드가 컴파일 될때 &quot;Hooked..!&quot; 문자열은 포인터이기 때문에 다른 섹션에 저장되고
    해당 섹션에서 포인터로 파라미터를 전달하기 때문에 다른 프로세스에서
    해당 코드가 실행되면 다음과 같은 오류가 발생한다. EXCEPTION_ACCESS_VIOLATION.
    그렇기 때문에 모든 문자열을 스택에 저장되도록 프로그래밍 해야한다.
    */
    // 모든 문자열은 다음과 같은 방식으로 선언해야 한다.
    char Text[] = &quot;Hooked..!&quot;;
    // 0x1122334455667788은 코드 인젝션 후에 원본 MessageBoxA 주소로 패치된다. 
    volatile int (WINAPI *OriMessageBox)(HWND, LPCSTR, LPCSTR, UINT) = 0x1122334455667788;
    // x86 시스템에서 사용한다면 다음과 같이 선언한다.
    // volatile int (WINAPI *OriMessageBox)(HWND, LPCSTR, LPCSTR, UINT) = 0x11223344; 

    // lpText 변수를 조작하여 함수 실행
    return OriMessageBox(hWnd, Text, lpCaption, uType);
}

BOOL IAT_Hook(HANDLE hProcess, LPCSTR lpModuleName, LPCSTR lpProcName, PVOID lpNewApiAddress, SIZE_T NewApiSize)
{
    SIZE_T NumberOfBytesRead;
    // Code Injection of NewAPI(HOOK Function)
    PVOID NewApiAddress = CodeInjection(hProcess, lpNewApiAddress, NewApiSize);

    if (NewApiAddress == NULL)
        return FALSE;
    // Find IAT address of target api
    PVOID IATAddress = FindIATAddress(hProcess, lpModuleName, lpProcName);

    if (IATAddress == NULL)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }
    
    PVOID OriAPIAddress = NULL;
    // Read original api address from IAT
    if (ReadProcessMemory(hProcess, IATAddress, &amp;amp;OriAPIAddress, sizeof(PVOID), &amp;amp;NumberOfBytesRead) == FALSE || NumberOfBytesRead != 8)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }
    // Code patch 0xFFFFFFFFFFFFFFFF in new api
    if (CodePatch(hProcess, (ULONG_PTR)NewApiAddress + SearchCodePatchOffset(NewMessageBoxA, NewApiSize), &amp;amp;OriAPIAddress, sizeof(ULONG_PTR)) == FALSE)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }
    // IAT code patch of target process
    if (CodePatch(hProcess, IATAddress, &amp;amp;NewApiAddress, sizeof(ULONG_PTR)) == FALSE)
    {
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_DECOMMIT);
        VirtualFreeEx(hProcess, NewApiAddress, 0, MEM_RELEASE);
        return FALSE;
    }
    // IAT Hooking success!!
    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD PID = 0;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    if (IAT_Hook(hProcess, &quot;user32.dll&quot;, &quot;MessageBoxA&quot;, NewMessageBoxA, (ULONG_PTR)IAT_Hook - (ULONG_PTR)NewMessageBoxA))
    {
        printf(&quot;IAT Hooking Success\n&quot;);
    }
    else
    {
        printf(&quot;IAT Hooking Failed\n&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/cJaiEa/btrz349z2gy/OjYMYYDSpuoELp94AmslO0/main.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;main.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.06MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;타겟 프로그램&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소스코드는 아래 더보기에 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1650568998961&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;windows.h&amp;gt;

#define SHOW_MESSAGEBOX 1

VOID AddButton(HWND hWnd);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    RECT wr = { 0, 0, 500, 500};

    AdjustWindowRect(&amp;amp;wr, WS_OVERLAPPEDWINDOW, FALSE);

    WNDCLASSA wc = { 0, };

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wc.hInstance = hInstance;
    wc.lpszClassName = &quot;WindowsClass&quot;;
    wc.lpfnWndProc = WndProc;

    if (RegisterClassA(&amp;amp;wc) == 0)
        return -1;

    HWND hWnd = CreateWindowA(&quot;WindowsClass&quot;, &quot;Code Injection&quot;, WS_OVERLAPPEDWINDOW | WS_VISIBLE, GetSystemMetrics(SM_CXSCREEN) / 2 - 250, GetSystemMetrics(SM_CYSCREEN) / 2 - 250, wr.right - wr.left, wr.bottom - wr.top, NULL, NULL, NULL, NULL);

    MSG msg = { 0, };

    while (GetMessageA(&amp;amp;msg, NULL, 0, 0))
    {
        TranslateMessage(&amp;amp;msg);
        DispatchMessageA(&amp;amp;msg);
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
    case WM_COMMAND:
        if (wParam == SHOW_MESSAGEBOX)
            MessageBoxA(hWnd, &quot;Not Hooked..!&quot;, &quot;Click Me!&quot;, 0);
    case WM_CREATE:
        AddButton(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
}

VOID AddButton(HWND hWnd)
{
    CreateWindowA(&quot;Button&quot;, &quot;Click Me!&quot;, WS_VISIBLE | WS_CHILD, 200, 225, 100, 50, hWnd, SHOW_MESSAGEBOX, NULL, NULL);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/djHrHr/btrz5OdAWUI/6rUh61efIQKcOYgNneXFBk/target.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;target.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.06MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;결과 확인&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;kakaotv&quot; data-video-url=&quot;https://tv.kakao.com/v/428153937&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/o3Nxb/hyN6Uj190t/tXTteEGMpK0Fgw2Dopcwu0/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/o4Mvf/hyN8rAvXDV/PhcNv1nQlfFisRLPfdh781/img.jpg?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-play-service=&quot;daum_tistory&quot;&gt;&lt;iframe src=&quot;https://play-tv.kakao.com/embed/player/cliplink/428153937?service=daum_tistory&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;</description>
      <category>Reversing</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/72</guid>
      <comments>https://crazyhacker.tistory.com/72#entry72comment</comments>
      <pubDate>Fri, 22 Apr 2022 05:07:40 +0900</pubDate>
    </item>
    <item>
      <title>[Nintendo 3DS] hello-world 예제 코드분석(주석설명)</title>
      <link>https://crazyhacker.tistory.com/71</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;hello-world 예제&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;hello-world 예제는&amp;nbsp;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;devkitPro&lt;/span&gt;를 설치하면 함께 다운로드되는 Nintendo 사의 게임기들의 예제 코드(프로젝트)중 하나 이다. 기본적으로 검은색 콘솔 중앙에 &lt;b&gt;'Hello World!'&lt;/b&gt; 를 출력한다. 코드는 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650504654275&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
	Hello World example made by Aurelio Mannara for libctru
	This code was modified for the last time on: 12/12/2014 21:00 UTC+1
*/

#include &amp;lt;3ds.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

int main(int argc, char **argv)
{
	gfxInitDefault();

	//상단 화면을 콘솔 초기화합니다. 두 번째 인자로 NULL을 사용하면 기본 콘솔을 사용합니다.
	consoleInit(GFX_TOP, NULL);

	//커서를 15행과 19열로 이동한 다음 &quot;Hello World!&quot;를 출력합니다.
	//커서를 이동하려면 &quot;\x1b[r;cH&quot;를 출력해야합니다. 여기서 r과 c는
	//각각 커서를 이동할 행과 열입니다.
	//상단 화면에는 30개의 행과 50개의 열이 있습니다.
	//하단 화면에는 30개의 행과 40개의 열이 있습니다.
	printf(&quot;\x1b[16;20HHello World!&quot;);

	printf(&quot;\x1b[30;16HPress Start to exit.&quot;);

	// 메인 루프
	while (aptMainLoop())
	{
		//모든 입력을 스캔합니다. 이 작업은 프레임 마다 한 번 수행해야 합니다.
		hidScanInput();

		//hidKeysDown 은 방금 누른 버튼에 대한 정보를 반환합니다.
		u32 kDown = hidKeysDown();

		if (kDown &amp;amp; KEY_START) break; // 메뉴로 돌아가기 위해 메인 루프를 중단합니다.

		// 프레임 버퍼 플러시 및 스왑
		gfxFlushBuffers();
		gfxSwapBuffers();

		//Wait for VBlank
		gspWaitForVBlank();
	}

	gfxExit();
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Nintendo/3DS</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/71</guid>
      <comments>https://crazyhacker.tistory.com/71#entry71comment</comments>
      <pubDate>Thu, 21 Apr 2022 22:45:23 +0900</pubDate>
    </item>
    <item>
      <title>[Nintendo 3DS] 닌텐도 3DS 예제 컴파일하기</title>
      <link>https://crazyhacker.tistory.com/70</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;닌텐도 3DS 예제 파일&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;닌텐도 3DS의 예제 파일은 우리가 설치한 &lt;b&gt;devkitPro&lt;/b&gt; 폴더에 들어가 있다. 경로는 다음과 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;C:\devkitPro\examples\3ds&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 경로에 들어가면 3DS와 관련된 예제 파일들을 볼수 있다. 우리는 여기서 &lt;b&gt;graphics\printing\hello-world&lt;/b&gt; 경로에 들어가면 예제가 존재한다. cmd를 열고 해당경로로 이동하자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWUlCF/btrzQY13wIA/ZZX5QKMf5gNeKJX3LdE8I0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWUlCF/btrzQY13wIA/ZZX5QKMf5gNeKJX3LdE8I0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWUlCF/btrzQY13wIA/ZZX5QKMf5gNeKJX3LdE8I0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWUlCF%2FbtrzQY13wIA%2FZZX5QKMf5gNeKJX3LdE8I0%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;979&quot; height=&quot;512&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컴파일하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 폴더에 이동했다면 make 명령어를 실행해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mSCyS/btrzUh6956K/2PumBXhrCj6RWKbim1zvD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mSCyS/btrzUh6956K/2PumBXhrCj6RWKbim1zvD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mSCyS/btrzUh6956K/2PumBXhrCj6RWKbim1zvD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmSCyS%2FbtrzUh6956K%2F2PumBXhrCj6RWKbim1zvD1%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;979&quot; height=&quot;512&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 main.c 파일이 컴파일되어 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;hello-world.elf&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;hello-world.smdh&lt;/span&gt;, &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;hello-world.3dsx&lt;/span&gt; 이렇게 3개의 파일이 나오게 된다. 여기서 나오는 3dsx 파일이 citra 에뮬레이터 돌아가는 파일이다. 이 파일은 3ds의 &lt;span style=&quot;color: #333333; background-color: #99cefa;&quot;&gt;Homebrew&lt;/span&gt;라는 써드파티 앱?에서도 돌아가는 파일이다. 하지만 만약 커펌된 3DS가 없다면 citra를 실행해 해당 파일을 불러오면 실행할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;citra에서 3dsx 실행하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;909&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYl4au/btrzRnUO4y4/ZeLkoc5Us4kEmk2muuoK2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYl4au/btrzRnUO4y4/ZeLkoc5Us4kEmk2muuoK2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYl4au/btrzRnUO4y4/ZeLkoc5Us4kEmk2muuoK2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYl4au%2FbtrzRnUO4y4%2FZeLkoc5Us4kEmk2muuoK2k%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;636&quot; height=&quot;666&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;909&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;727&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R6JQB/btrzSgHxAfY/iRLezZNpkPtDT28cuvqNP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R6JQB/btrzSgHxAfY/iRLezZNpkPtDT28cuvqNP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R6JQB/btrzSgHxAfY/iRLezZNpkPtDT28cuvqNP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR6JQB%2FbtrzSgHxAfY%2FiRLezZNpkPtDT28cuvqNP1%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;619&quot; height=&quot;647&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;커펌된 3DS에서 실행하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.&lt;b&gt; 3DS의 SD 카드를 PC와 연결&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnpqyy/btrzSf9G4Ea/cSNMctrV2uVBCyvfPREcek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnpqyy/btrzSf9G4Ea/cSNMctrV2uVBCyvfPREcek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnpqyy/btrzSf9G4Ea/cSNMctrV2uVBCyvfPREcek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbnpqyy%2FbtrzSf9G4Ea%2FcSNMctrV2uVBCyvfPREcek%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;962&quot; height=&quot;490&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. &lt;b&gt;폴더에 3dsx 파일 복사/붙여넣기&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d6qf2W/btrzRWQdBF6/TKK0mooeZrmMQ37LVED0K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d6qf2W/btrzRWQdBF6/TKK0mooeZrmMQ37LVED0K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d6qf2W/btrzRWQdBF6/TKK0mooeZrmMQ37LVED0K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6qf2W%2FbtrzRWQdBF6%2FTKK0mooeZrmMQ37LVED0K0%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;962&quot; height=&quot;496&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. &lt;b&gt;Homebrew 에서 hello-world 실행하기&lt;/b&gt;&lt;/span&gt;&lt;/h4&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/dOe4d1/btrzUiSyGAq/rbZV89HdR7SIf3rPkvaXmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dOe4d1/btrzUiSyGAq/rbZV89HdR7SIf3rPkvaXmK/img.png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;889&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; width=&quot;600&quot; data-widthpercent=&quot;45.3&quot; style=&quot;width: 44.7689%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dOe4d1/btrzUiSyGAq/rbZV89HdR7SIf3rPkvaXmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdOe4d1%2FbtrzUiSyGAq%2FrbZV89HdR7SIf3rPkvaXmK%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;580&quot; height=&quot;889&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yyb9p/btrzQoNIQ1Z/NER68MjRfU0MPb3olu8n50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yyb9p/btrzQoNIQ1Z/NER68MjRfU0MPb3olu8n50/img.png&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;1028&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;54.7&quot; data-filename=&quot;blob&quot; style=&quot;width: 54.0683%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yyb9p/btrzQoNIQ1Z/NER68MjRfU0MPb3olu8n50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyyb9p%2FbtrzQoNIQ1Z%2FNER68MjRfU0MPb3olu8n50%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;810&quot; height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 우리가 기본적인 예제를 컴파일하여 실행해보았다. 다음 포스팅에서는 hello-world의 코드분석을 해볼 예정이다.&lt;/p&gt;</description>
      <category>Nintendo/3DS</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/70</guid>
      <comments>https://crazyhacker.tistory.com/70#entry70comment</comments>
      <pubDate>Wed, 20 Apr 2022 04:07:17 +0900</pubDate>
    </item>
    <item>
      <title>[Nintendo 3DS] 닌텐도 3DS 개발환경 구축하기</title>
      <link>https://crazyhacker.tistory.com/69</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;닌텐도 3DS 개발에 도전하게된 이유&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 &lt;span style=&quot;color: #ee2323;&quot;&gt;없다&lt;/span&gt;. 필자가 지금까지 무언가에 도전하는데에는 큰 이유가 있지 않다. 그냥 단순히 재밌어보이고 해보고 싶기 때문이다. 이번에도 닌텐도 3DS의 시스템에 관심이 생겨 한번 도전하게 되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;닌텐도 3DS 개발환경 구축&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. &lt;b&gt;devkitPro Install&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPJNUY/btrzMvxKE9e/0K7Hbvaw1vAG3rN7kW6BJ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPJNUY/btrzMvxKE9e/0K7Hbvaw1vAG3rN7kW6BJ0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPJNUY/btrzMvxKE9e/0K7Hbvaw1vAG3rN7kW6BJ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPJNUY%2FbtrzMvxKE9e%2F0K7Hbvaw1vAG3rN7kW6BJ0%2Fimg.jpg&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;87&quot; height=&quot;87&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;devkitPro&lt;/span&gt;는 GCC 툴체인 기반의 ARM을 지원하는 컴파일러이다. 닌텐도 3DS는 ARM 기반의 시스템이기 때문에 ARM 컴파일러가 필요하다. 이를 위해 devkiPro를 이용해 &lt;span style=&quot;color: #ee2323;&quot;&gt;크로스 컴파일&lt;/span&gt;(다른 환경의 바이너리로 컴파일 하는 것)을 한다. 다음 링크에서 Installer를 다운한다.&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650300236392&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;Releases &amp;middot; devkitPro/installer&quot; data-og-description=&quot;Contribute to devkitPro/installer development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/devkitPro/installer/releases&quot; data-og-url=&quot;https://github.com/devkitPro/installer/releases&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bOZ9L3/hyN5uLuVL6/bRRoW3scGb4BjPGakV3RA1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/devkitPro/installer/releases&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/devkitPro/installer/releases&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bOZ9L3/hyN5uLuVL6/bRRoW3scGb4BjPGakV3RA1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;Releases &amp;middot; devkitPro/installer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to devkitPro/installer development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/r9BEl/btrzIrYgAvb/jQIIBkiLROhvE6ez2o3ozk/devkitProUpdater-3.0.3.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;devkitProUpdater-3.0.3.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.19MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qOSOZ/btrzL9IBzp5/pCiqkDekD6XT89PBicFjv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qOSOZ/btrzL9IBzp5/pCiqkDekD6XT89PBicFjv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qOSOZ/btrzL9IBzp5/pCiqkDekD6XT89PBicFjv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqOSOZ%2FbtrzL9IBzp5%2FpCiqkDekD6XT89PBicFjv1%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;499&quot; height=&quot;388&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Sy7gV/btrzDN1iuLX/GdkgdjrQuh7XrRUGnrGaI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Sy7gV/btrzDN1iuLX/GdkgdjrQuh7XrRUGnrGaI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Sy7gV/btrzDN1iuLX/GdkgdjrQuh7XrRUGnrGaI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSy7gV%2FbtrzDN1iuLX%2FGdkgdjrQuh7XrRUGnrGaI1%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;492&quot; height=&quot;383&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;383&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;499&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ig4dv/btrzIn17yZD/QQeqdKXFSDWbIiH11BdVT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ig4dv/btrzIn17yZD/QQeqdKXFSDWbIiH11BdVT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ig4dv/btrzIn17yZD/QQeqdKXFSDWbIiH11BdVT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIg4dv%2FbtrzIn17yZD%2FQQeqdKXFSDWbIiH11BdVT0%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;499&quot; height=&quot;388&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;388&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;499&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IH4E1/btrzKsoCECj/AojwrvcgX4aCEGtbElmfL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IH4E1/btrzKsoCECj/AojwrvcgX4aCEGtbElmfL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IH4E1/btrzKsoCECj/AojwrvcgX4aCEGtbElmfL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIH4E1%2FbtrzKsoCECj%2FAojwrvcgX4aCEGtbElmfL1%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;499&quot; height=&quot;388&quot; data-origin-width=&quot;499&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정을 따라오면 3DS 개발용 컴파일러가 설치되고 환경변수도 설정된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.&amp;nbsp;&lt;b&gt;Visual Studio Code 컴파일 설정&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;make를 사용해 컴파일을 할 수도 있지만 나는 따로 설정했다.&lt;/p&gt;
&lt;pre id=&quot;code_1650301558658&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// c_cpp_properties.json
{
    &quot;configurations&quot;: [
        {
            &quot;name&quot;: &quot;Win32&quot;,
            &quot;includePath&quot;: [
                &quot;${workspaceFolder}/**&quot;,
                &quot;C:/devkitPro/libctru/include/**&quot;,
                &quot;C:/devkitPro/devkitARM/arm-none-eabi/include/**&quot;
            ],
            &quot;defines&quot;: [
                &quot;_DEBUG&quot;,
                &quot;UNICODE&quot;,
                &quot;_UNICODE&quot;
            ],
            &quot;compilerPath&quot;: &quot;C:/devkitPro/devkitARM/bin/arm-none-eabi-gcc.exe&quot;
        }
    ],
    &quot;version&quot;: 4
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1650301747284&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// tasks.json
{
    &quot;version&quot;: &quot;2.0.0&quot;,
    &quot;tasks&quot;: [
        {
            &quot;label&quot;: &quot;arm-none-eabi-gcc Nintendo 3DS Compile&quot;,
            &quot;type&quot;: &quot;process&quot;,
            &quot;command&quot;: &quot;cmd&quot;,
            &quot;args&quot;: [
                &quot;/c&quot;,
                &quot;C:\\devkitPro\\devkitARM\\bin\\arm-none-eabi-gcc.exe&quot;,
                &quot;-MMD&quot;,
                &quot;-MP&quot;,
                &quot;-MF&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.d&quot;,
                &quot;-g&quot;,
                &quot;-Wall&quot;,
                &quot;-O2&quot;,
                &quot;-mword-relocations&quot;,
                &quot;-ffunction-sections&quot;,
                &quot;-march=armv6k&quot;,
                &quot;-mtune=mpcore&quot;,
                &quot;-mfloat-abi=hard&quot;,
                &quot;-mtp=soft&quot;,
                &quot;-I&quot;,
                &quot;${fileDirname}&quot;,
                &quot;-I&quot;,
                &quot;C:\\devkitPro\\libctru\\include&quot;,
                &quot;-D__3DS__&quot;,
                &quot;-c&quot;,
                &quot;${file}&quot;,
                &quot;-o&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.o&quot;,
                &quot;&amp;amp;&amp;amp;&quot;,
                &quot;C:\\devkitPro\\devkitARM\\bin\\arm-none-eabi-gcc.exe&quot;,
                &quot;-specs=3dsx.specs&quot;,
                &quot;-g&quot;,
                &quot;-march=armv6k&quot;,
                &quot;-mtune=mpcore&quot;,
                &quot;-mfloat-abi=hard&quot;,
                &quot;-mtp=soft&quot;,
                &quot;-Wl,-Map,${fileDirname}\\${fileBasenameNoExtension}.map&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.o&quot;,
                &quot;-LC:\\devkitPro\\libctru\\lib&quot;,
                &quot;-lctru&quot;,
                &quot;-lm&quot;,
                &quot;-o&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.elf&quot;,
                &quot;&amp;amp;&amp;amp;&quot;,
                &quot;C:\\devkitPro\\devkitARM\\bin\\arm-none-eabi-gcc-nm.exe&quot;,
                &quot;-CSn&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.elf&quot;,
                &quot;&amp;amp;&amp;amp;&quot;,
                &quot;C:\\devkitPro\\tools\\bin\\smdhtool.exe&quot;,
                &quot;--create&quot;,
                &quot;패키지 이름&quot;,
                &quot;프로그램 이름&quot;,
                &quot;제작자&quot;,
                &quot;C:\\devkitPro\\libctru\\default_icon.png&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.smdh&quot;,
                &quot;&amp;amp;&amp;amp;&quot;,
                &quot;C:\\devkitPro\\tools\\bin\\3dsxtool.exe&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.elf&quot;,
                &quot;${fileDirname}\\${fileBasenameNoExtension}.3dsx&quot;,
                &quot;--smdh=${fileDirname}\\${fileBasenameNoExtension}.smdh&quot;
            ],
            &quot;options&quot;: {
                &quot;cwd&quot;: &quot;${workspaceFolder}&quot;
            },
            &quot;group&quot;: &quot;build&quot;,
            &quot;detail&quot;: &quot;컴파일러: arm-none-eabi-gcc&quot;
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 두개의 파일을 각각 저장해 VS Code의 Workspace 폴더 최상위에 .vscode 폴더를 만들어 넣어주면 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. &lt;b&gt;Nintendo 3DS 에뮬레이터 설치&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제로 커펌(커스텀 펌웨어)된 닌텐도 3DS가 없는 경우에는 닌텐도 3DS 개발을 하더라도 해당 바이너리를 실행시킬 수 없다. 그렇기에 다음과 같이 에뮬레이터를 설치해주자&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650388548346&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Download Citra &amp;middot; Citra&quot; data-og-description=&quot;The nightly build of Citra contains already reviewed and tested features. If you require support with the installation or use of Citra, or you want to report bugs you should use this version. This version is still in development, so expect crashes and bugs&quot; data-og-host=&quot;citra-emu.org&quot; data-og-source-url=&quot;https://citra-emu.org/download/&quot; data-og-url=&quot;https://citra-emu.org/download/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bH3Ul8/hyN5u6F1xs/7lFoCXmiefLHQIQurTtly0/img.png?width=646&amp;amp;height=250&amp;amp;face=0_0_646_250&quot;&gt;&lt;a href=&quot;https://citra-emu.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://citra-emu.org/download/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bH3Ul8/hyN5u6F1xs/7lFoCXmiefLHQIQurTtly0/img.png?width=646&amp;amp;height=250&amp;amp;face=0_0_646_250');&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;Download Citra &amp;middot; Citra&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The nightly build of Citra contains already reviewed and tested features. If you require support with the installation or use of Citra, or you want to report bugs you should use this version. This version is still in development, so expect crashes and bugs&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;citra-emu.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/benbXl/btrzQn84LhJ/DrKL1gQmP2WsmgjDrxNCnK/citra-setup-windows.exe?attach=1&amp;amp;knm=tfile.exe&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;citra-setup-windows.exe&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;18.79MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1877&quot; data-origin-height=&quot;971&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IX7JH/btrzRW3Knwp/i4p2kS3bVZ0m0Adg6zI5R0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IX7JH/btrzRW3Knwp/i4p2kS3bVZ0m0Adg6zI5R0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IX7JH/btrzRW3Knwp/i4p2kS3bVZ0m0Adg6zI5R0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIX7JH%2FbtrzRW3Knwp%2Fi4p2kS3bVZ0m0Adg6zI5R0%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;1877&quot; height=&quot;971&quot; data-origin-width=&quot;1877&quot; data-origin-height=&quot;971&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;1020&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rUjII/btrzQYnsx2I/b34MzCG6fe14jeGnV7icI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rUjII/btrzQYnsx2I/b34MzCG6fe14jeGnV7icI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rUjII/btrzQYnsx2I/b34MzCG6fe14jeGnV7icI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrUjII%2FbtrzQYnsx2I%2Fb34MzCG6fe14jeGnV7icI1%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;1908&quot; height=&quot;1020&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1908&quot; data-origin-height=&quot;1020&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. &lt;b&gt;셋팅 확인&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLT7Uw/btrzJ2i3Hgo/1LwavhiEjnQIPZZ8NjstXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLT7Uw/btrzJ2i3Hgo/1LwavhiEjnQIPZZ8NjstXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLT7Uw/btrzJ2i3Hgo/1LwavhiEjnQIPZZ8NjstXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLT7Uw%2FbtrzJ2i3Hgo%2F1LwavhiEjnQIPZZ8NjstXK%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;979&quot; height=&quot;512&quot; data-origin-width=&quot;979&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 cmd를 열고 where make 명령어를 했을 때 정상적으로 잡히면 성공이다. 잡히지 않는다면 따로 환경변수 셋팅을 해주도록 하자.&lt;/p&gt;</description>
      <category>Nintendo/3DS</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/69</guid>
      <comments>https://crazyhacker.tistory.com/69#entry69comment</comments>
      <pubDate>Tue, 19 Apr 2022 02:16:57 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Code Injection Step 2</title>
      <link>https://crazyhacker.tistory.com/68</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;해당 포스팅은 이전 포스팅에서 이어집니다.&lt;/blockquote&gt;
&lt;figure id=&quot;og_1649171909453&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;[Reversing] Code Injection Step 1&quot; data-og-description=&quot;Code Injection 기법은 사실상 ShellCode Injection 이라고 불러도 될 만큼 동작 방식이 매우 비슷하다. 하지만 우리는 주입할 코드를 ShellCode가 아닌 C언어 함수로 작성해 주입할 것이다. 1. 주입할 함수 작&quot; data-og-host=&quot;crazyhacker.tistory.com&quot; data-og-source-url=&quot;https://crazyhacker.tistory.com/67&quot; data-og-url=&quot;https://crazyhacker.tistory.com/67&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d3kVTH/hyNVQn2wQN/k0ekQRIzkLCmpKmV0JU1j1/img.png?width=800&amp;amp;height=465&amp;amp;face=0_0_800_465,https://scrap.kakaocdn.net/dn/uUcgs/hyNVNSmF9w/nvDKklsfoJSnas2KuTpW6K/img.png?width=800&amp;amp;height=465&amp;amp;face=0_0_800_465,https://scrap.kakaocdn.net/dn/f0hq0/hyNVHdF4dy/JB3FKRTjVUOtL2alVnhCyk/img.png?width=1935&amp;amp;height=1125&amp;amp;face=0_0_1935_1125&quot;&gt;&lt;a href=&quot;https://crazyhacker.tistory.com/67&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://crazyhacker.tistory.com/67&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d3kVTH/hyNVQn2wQN/k0ekQRIzkLCmpKmV0JU1j1/img.png?width=800&amp;amp;height=465&amp;amp;face=0_0_800_465,https://scrap.kakaocdn.net/dn/uUcgs/hyNVNSmF9w/nvDKklsfoJSnas2KuTpW6K/img.png?width=800&amp;amp;height=465&amp;amp;face=0_0_800_465,https://scrap.kakaocdn.net/dn/f0hq0/hyNVHdF4dy/JB3FKRTjVUOtL2alVnhCyk/img.png?width=1935&amp;amp;height=1125&amp;amp;face=0_0_1935_1125');&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;[Reversing] Code Injection Step 1&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Code Injection 기법은 사실상 ShellCode Injection 이라고 불러도 될 만큼 동작 방식이 매우 비슷하다. 하지만 우리는 주입할 코드를 ShellCode가 아닌 C언어 함수로 작성해 주입할 것이다. 1. 주입할 함수 작&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;crazyhacker.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;Why did the error occur?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #333333;&quot;&gt;에러가 발생되는 원인은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;835&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwj3fT/btryHFVMij8/HJz9LxLVVBeXOcFlt1Ma00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwj3fT/btryHFVMij8/HJz9LxLVVBeXOcFlt1Ma00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwj3fT/btryHFVMij8/HJz9LxLVVBeXOcFlt1Ma00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwj3fT%2FbtryHFVMij8%2FHJz9LxLVVBeXOcFlt1Ma00%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;1424&quot; height=&quot;835&quot; data-origin-width=&quot;1424&quot; data-origin-height=&quot;835&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주입된 어셈블리(코드)를 확인해보면 0x1E54A422AB0를 첫번째 인자로 넘기고 &lt;span style=&quot;background-color: #ffc1c8; color: #000000;&quot;&gt;0x1E54A426D8C에서 WinExec의 주소를 rax로 가져와 call&lt;/span&gt; 하게 된다. 하지만 해당 2개의 주소는 존재하지(사용되지) 않는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nXksh/btryHLO5jSu/7MwxkmaeYB2kL8zLR6fCU0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nXksh/btryHLO5jSu/7MwxkmaeYB2kL8zLR6fCU0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nXksh/btryHLO5jSu/7MwxkmaeYB2kL8zLR6fCU0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnXksh%2FbtryHLO5jSu%2F7MwxkmaeYB2kL8zLR6fCU0%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;1613&quot; height=&quot;325&quot; data-origin-width=&quot;1613&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0x1E54A422AB0는 &quot;calc.exe&quot; 문자열을 가르킨다. 그리고 &lt;span style=&quot;color: #333333;&quot;&gt;0x1E54A426D8C에는 WinExec의 주소가 들어있다. 하지만 타겟 프로세스의 공간에는 해당 문자열(&quot;calc.exe&quot;)과 IAT(WinExec의 주소)가 존재하지 않는다. 따라서 우리는 타겟 프로세스에 인자로 들어가는 문자열(실행시킬 프로그램 이름)과 WinExec의 주소를 전달해줘야한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;소스코드 수정&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1649338535929&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef UINT (*WINAPI WINEXEC)(LPCSTR, UINT);

typedef struct _INJECT_DATA
{
    WINEXEC pWinExec; // WinExec 함수의 주소를 담을 함수 포인터
    char string[12];  // 실행시킬 프로그램 이름
} INJECT_DATA;

// 인자의 유형을 INJECT_DATA의 포인터로 변경
DWORD WINAPI ThreadProc(INJECT_DATA *lpParameter)
{
    lpParameter-&amp;gt;pWinExec(lpParameter-&amp;gt;string, SW_SHOW);
    // WinExec(&quot;calc.exe&quot;, SW_SHOW);
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1649338626120&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BOOL CodeInjection(DWORD PID)
{
    // 타겟 프로세스의 핸들 획득 
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

    if (hProcess == NULL)
    {
        printf(&quot;OpenProcess Failed!\n&quot;);
        return FALSE;
    }

    // 주입할 함수의 사이즈를 계산
    SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;

    // 타겟 프로세스에 공간 할당
    PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    PVOID InjectDataAddress = VirtualAllocEx(hProcess, NULL, sizeof(INJECT_DATA), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // 할당된 공간에 ThreadProc 함수 작성
    if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return FALSE;
    }

    // 구조체 생성
    INJECT_DATA InjectData;
    // WinExec API는 Kernel32.dll에 존재한다. GetProcAddress와 GetModuleHandle API를 이용하여 함수의 주소를 알아낼 수 있다.
    InjectData.pWinExec = (WINEXEC)GetProcAddress(GetModuleHandleA(&quot;kernel32.dll&quot;), &quot;WinExec&quot;);
    // INJECT_DATA 구조체의 string에 실행시킬 파일의 문자열을 입력한다.
    strcpy(InjectData.string, &quot;calc.exe&quot;);

    // 할당된 공간에 InjectData 작성
    if (WriteProcessMemory(hProcess, InjectDataAddress, (LPCVOID)&amp;amp;InjectData, sizeof(INJECT_DATA), NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return FALSE;
    }

    // 쓰레드 생성 및 실행
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, (LPVOID)InjectDataAddress, 0, NULL);

    if (hThread == NULL)
    {
        printf(&quot;CreateRemoteThread Failed\n&quot;);
        return FALSE;
    }

    printf(&quot;Code Injection Success!\n&quot;);
    return TRUE;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;완성된 코드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1649338669404&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

typedef UINT (*WINAPI WINEXEC)(LPCSTR, UINT);

typedef struct _INJECT_DATA
{
    WINEXEC pWinExec;
    char string[12];
} INJECT_DATA;

// 인자의 유형을 INJECT_DATA의 포인터로 변경
DWORD WINAPI ThreadProc(INJECT_DATA *lpParameter)
{
    lpParameter-&amp;gt;pWinExec(lpParameter-&amp;gt;string, SW_SHOW);
    // WinExec(&quot;calc.exe&quot;, SW_SHOW);
}
int AtherFunc() {}

BOOL CodeInjection(DWORD PID)
{
    // 타겟 프로세스의 핸들 획득 
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

    if (hProcess == NULL)
    {
        printf(&quot;OpenProcess Failed!\n&quot;);
        return FALSE;
    }

    // 주입할 함수의 사이즈를 계산
    SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;

    // 타겟 프로세스에 공간 할당
    PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    PVOID InjectDataAddress = VirtualAllocEx(hProcess, NULL, sizeof(INJECT_DATA), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // 할당된 공간에 ThreadProc 함수 작성
    if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return FALSE;
    }

    // 인자로 전달할 데이터 셋팅
    INJECT_DATA InjectData;
    InjectData.pWinExec = (WINEXEC)GetProcAddress(GetModuleHandleA(&quot;kernel32.dll&quot;), &quot;WinExec&quot;);
    strcpy(InjectData.string, &quot;calc.exe&quot;);

    // 할당된 공간에 InjectData 작성
    if (WriteProcessMemory(hProcess, InjectDataAddress, (LPCVOID)&amp;amp;InjectData, sizeof(INJECT_DATA), NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return FALSE;
    }

    // 쓰레드 생성 및 실행
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, (LPVOID)InjectDataAddress, 0, NULL);

    if (hThread == NULL)
    {
        printf(&quot;CreateRemoteThread Failed\n&quot;);
        return FALSE;
    }

    printf(&quot;Code Injection Success!\n&quot;);
    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD PID = 0;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);

    CodeInjection(PID);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;빌드 후에 프로그램을 실행해 타겟 프로세스의 PID를 입력한다. 그럼 정상적으로 계산기 프로그램이 실행되는 것을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ezgif-2-adc9a51421.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6OAdk/btryIqspEhs/s6ukeJoX2BQZinNDg4Gesk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6OAdk/btryIqspEhs/s6ukeJoX2BQZinNDg4Gesk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6OAdk/btryIqspEhs/s6ukeJoX2BQZinNDg4Gesk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/6OAdk/btryIqspEhs/s6ukeJoX2BQZinNDg4Gesk/img.gif&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;800&quot; height=&quot;450&quot; data-filename=&quot;ezgif-2-adc9a51421.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Reversing/Code Injection</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/68</guid>
      <comments>https://crazyhacker.tistory.com/68#entry68comment</comments>
      <pubDate>Thu, 7 Apr 2022 22:59:01 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Code Injection Step 1</title>
      <link>https://crazyhacker.tistory.com/67</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Code Injection 기법은 사실상 ShellCode Injection 이라고 불러도 될 만큼 동작 방식이 매우 비슷하다. 하지만 우리는 주입할 코드를 ShellCode가 아닌 C언어 함수로 작성해 주입할 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.&lt;b&gt; 주입할 함수 작성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1649142719319&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
주입되는 코드는 CreateRemoteThread API를 통해 실행되기 때문에
아래와 같은 형식을 반드시 지켜줘야 한다. (함수명은 관계 없음)
*/
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    // 계산기를 실행
    WinExec(&quot;calc.exe&quot;, SW_SHOW);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.&lt;b&gt; 코드 인젝션 함수 작성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1649147137150&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BOOL CodeInjection(DWORD PID)
{
    // 타겟 프로세스의 핸들 획득 
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

    if (hProcess == NULL)
    {
        printf(&quot;OpenProcess Failed!\n&quot;);
        return FALSE;
    }

    // 주입할 함수의 사이즈를 계산
    SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;

    // 타겟 프로세스에 공간 할당
    PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // 할당된 공간에 ThreadProc 함수 작성
    if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return -1;
    }

    // 쓰레드 생성 및 실행
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, NULL, 0, NULL);

    if (hThread == NULL)
    {
        printf(&quot;CreateRemoteThread Failed\n&quot;);
        return FALSE;
    }

    printf(&quot;Code Injection Success!\n&quot;);
    return TRUE;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;완성된 코드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1649147255566&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

/*
주입되는 코드는 CreateRemoteThread API를 통해 실행되기 때문에
아래와 같은 형식을 반드시 지켜줘야 한다. (함수명은 관계 없음)
*/
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
    // 계산기를 실행
    WinExec(&quot;calc.exe&quot;, SW_SHOW);
}
int AtherFunc() {} // ThreadProc 함수의 사이즈를 구하기 위해 아무런 기능을 하지 않는 함수를 정의

BOOL CodeInjection(DWORD PID)
{
    // 타겟 프로세스의 핸들 획득 
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

    if (hProcess == NULL)
    {
        printf(&quot;OpenProcess Failed!\n&quot;);
        return FALSE;
    }

    // 주입할 함수의 사이즈를 계산
    SIZE_T ThreadProcSize = (ULONGLONG)AtherFunc - (ULONGLONG)ThreadProc;

    // 타겟 프로세스에 공간 할당
    PVOID ThreadProcAddress = VirtualAllocEx(hProcess, NULL, ThreadProcSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // 할당된 공간에 ThreadProc 함수 작성
    if (WriteProcessMemory(hProcess, ThreadProcAddress, (LPCVOID)ThreadProc, ThreadProcSize, NULL) == FALSE)
    {
        printf(&quot;WriteProcessMemory Failed!\n&quot;);
        return -1;
    }

    // 쓰레드 생성 및 실행
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProcAddress, NULL, 0, NULL);

    if (hThread == NULL)
    {
        printf(&quot;CreateRemoteThread Failed\n&quot;);
        return FALSE;
    }

    printf(&quot;Code Injection Success!\n&quot;);
    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD PID = 0;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);

    CodeInjection(PID);
}&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;위 코드를 빌드하기 전 다음과 같은 설정을 해준다.&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;li&gt;Release 모드로 빌드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드 후에 프로그램을 실행해 타겟 프로세스의 PID를 입력한다. 그럼 계산기가 뜨지 않고 타겟 프로세스가 오류를 띄우며 종료된다. 그게 정상이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1935&quot; data-origin-height=&quot;1125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFyTiE/btryuVZRJHH/vKnNwIgqGZFWUvVRV7pkZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFyTiE/btryuVZRJHH/vKnNwIgqGZFWUvVRV7pkZK/img.png&quot; data-alt=&quot;타겟 프로세스로 삼은 메모장이 EXCEPTION_ACCESS_VIOLATION 에러를 띄우며 디버거를 띄운 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFyTiE/btryuVZRJHH/vKnNwIgqGZFWUvVRV7pkZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFyTiE%2FbtryuVZRJHH%2FvKnNwIgqGZFWUvVRV7pkZK%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;1935&quot; height=&quot;1125&quot; data-origin-width=&quot;1935&quot; data-origin-height=&quot;1125&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;타겟 프로세스로 삼은 메모장이 EXCEPTION_ACCESS_VIOLATION 에러를 띄우며 디버거를 띄운 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런 현상이 발생할까? 그 이유는 다음 포스팅에서 알아보자&lt;/p&gt;</description>
      <category>Reversing/Code Injection</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/67</guid>
      <comments>https://crazyhacker.tistory.com/67#entry67comment</comments>
      <pubDate>Tue, 5 Apr 2022 17:44:31 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing] Code Injection Step 0</title>
      <link>https://crazyhacker.tistory.com/66</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 인젝션 (Code Injection) 정의&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Code Injection이란 실행 가능한 코드를 대상 메모리 영역으로 삽입하여 실행하는 것을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 인젝션 활용 영역&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;API 후킹&lt;/li&gt;
&lt;li&gt;일반 응용 프로그램에 특별한 목적의 코드를 추가&lt;/li&gt;
&lt;li&gt;악성코드에서의 활용&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;코드 인젝션 주요 동작 흐름&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Windows API / Kernel Function&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;프로세스 권한 획득 : OpenProcess() / NtOpenProcess()&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;메모리 공간 할당 : VirtualAllocEx() / NtAllocateVirtualMemory()&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;코드 삽입 : WriteProcessMemory() / NtWriteVirtualMemory()&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;코드 실행 : CreateRemoteThread() / NtCreateThreadEx()&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;코드 인젝션 관련 주요 API&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;figure id=&quot;og_1649134880840&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;OpenProcess function (processthreadsapi.h) - Win32 apps&quot; data-og-description=&quot;Opens an existing local process object.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bVN9Xz/hyNVUcc8jm/WroCBQEh1YUJbRzt9AIWWK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bVN9Xz/hyNVUcc8jm/WroCBQEh1YUJbRzt9AIWWK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;OpenProcess function (processthreadsapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Opens an existing local process object.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1649134926318&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;VirtualAllocEx function (memoryapi.h) - Win32 apps&quot; data-og-description=&quot;Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5u3kY/hyNVUXBeu9/kzKjRfZh1TLWl4KPtvSlq0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5u3kY/hyNVUXBeu9/kzKjRfZh1TLWl4KPtvSlq0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;VirtualAllocEx function (memoryapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process. The function initializes the memory it allocates to zero.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1649134953030&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;VirtualProtectEx function (memoryapi.h) - Win32 apps&quot; data-og-description=&quot;Changes the protection on a region of committed pages in the virtual address space of a specified process.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ji15W/hyNVJ9BRN4/gP0kHTjIrOKi3UpxAVuHD0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotectex&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ji15W/hyNVJ9BRN4/gP0kHTjIrOKi3UpxAVuHD0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;VirtualProtectEx function (memoryapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Changes the protection on a region of committed pages in the virtual address space of a specified process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1649134984921&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;WriteProcessMemory function (memoryapi.h) - Win32 apps&quot; data-og-description=&quot;Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/polip/hyNVPoq1u9/bTqXQLlk43YYs622uQhikk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/polip/hyNVPoq1u9/bTqXQLlk43YYs622uQhikk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;WriteProcessMemory function (memoryapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1649135027739&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;CreateRemoteThread function (processthreadsapi.h) - Win32 apps&quot; data-og-description=&quot;Creates a thread that runs in the virtual address space of another process.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/reMVw/hyNVUQQsrm/fgX7kjmUp9Tz9JTMsf1J9K/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/reMVw/hyNVUQQsrm/fgX7kjmUp9Tz9JTMsf1J9K/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&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;CreateRemoteThread function (processthreadsapi.h) - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Creates a thread that runs in the virtual address space of another process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;공격 원리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;850&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WgW1q/btryowlJb3T/o5Z09qdrEMmSQpmd74HCUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WgW1q/btryowlJb3T/o5Z09qdrEMmSQpmd74HCUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WgW1q/btryowlJb3T/o5Z09qdrEMmSQpmd74HCUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWgW1q%2FbtryowlJb3T%2Fo5Z09qdrEMmSQpmd74HCUk%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;1408&quot; height=&quot;850&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;850&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Reversing/Code Injection</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/66</guid>
      <comments>https://crazyhacker.tistory.com/66#entry66comment</comments>
      <pubDate>Mon, 4 Apr 2022 18:52:00 +0900</pubDate>
    </item>
    <item>
      <title>[C] Rlibloaderapi.h - GetRemoteModuleFileName</title>
      <link>https://crazyhacker.tistory.com/65</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetModuleFileName&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;GetModuleFileName 함수는 인자로 들어온 HMODULE의 전체 경로를 반환해주는 함수이다. 즉 HMODULE(ImageBase)는 가지고 있지만 해당 HMODULE이 어떤 DLL인지 모를때 사용하면 유용한 함수이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetRemoteModuleFileName&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645082093637&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DWORD GetRemoteModuleFileNameA(HANDLE ProcessHandle, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
{
    ZeroMemory(lpFilename, nSize);
    wchar_t Filename[MAX_PATH];
    DWORD Size = GetRemoteModuleFileNameW(ProcessHandle, hModule, Filename, MAX_PATH);
    int FilenameLength = WideCharToMultiByte(CP_ACP, 0, Filename, -1, NULL, 0, NULL, NULL);
    WideCharToMultiByte(CP_ACP, 0, Filename, -1, lpFilename, FilenameLength &amp;lt;= nSize ? FilenameLength : nSize, NULL, NULL);
    return FilenameLength &amp;lt;= nSize ? FilenameLength : nSize;
}

DWORD GetRemoteModuleFileNameW(HANDLE ProcessHandle, HMODULE hModule, LPWSTR lpFilename, DWORD nSize)
{
#ifdef _WIN64
    BOOL bWow64Process;
    IsWow64Process(ProcessHandle, &amp;amp;bWow64Process);
    size_t SizeOfPointer = bWow64Process ? 4 : 8;
#else
    size_t SizeOfPointer = 4;
#endif
    nSize -= 2;
    DWORD Size = 0;
    PVOID PebBaseAddress = GetRemotePeb(ProcessHandle);

    if (PebBaseAddress == NULL)
        return Size;

    PVOID PebLdrData = NULL;

    if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
            (ULONG_PTR)PebBaseAddress + (bWow64Process ? Peb_LdrOffset32 : Peb_LdrOffset64), 
#else
            (ULONG_PTR)PebBaseAddress + Peb_LdrOffset32,
#endif
            &amp;amp;PebLdrData, 
            SizeOfPointer, 
            NULL) == FALSE)
        return hModule;

#ifdef _WIN64
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64);
#else
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32;
#endif

    for (; ReadProcessMemory(ProcessHandle, LdrDataTableEntry, &amp;amp;LdrDataTableEntry, SizeOfPointer, NULL) 
            &amp;amp;&amp;amp; 
#ifdef _WIN64
            (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64) != LdrDataTableEntry
#else
            (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32 != LdrDataTableEntry
#endif
        ;)
    {
        PVOID DllBase;

        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDataTableEntry_DllBase32 : LdrDataTableEntry_DllBase64),
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDataTableEntry_DllBase32, 
#endif
                &amp;amp;DllBase, 
                SizeOfPointer, 
                NULL) == FALSE)
            return Size;
        
        if (DllBase != hModule)
            continue;

#ifdef _WIN64
        size_t SizeOfUnicodeString = bWow64Process ? sizeof(UNICODE_STRING32) : sizeof(UNICODE_STRING64);
#else
        size_t SizeOfUnicodeString = sizeof(UNICODE_STRING);
#endif
        BYTE *UnicodeString = calloc(1, SizeOfUnicodeString);

        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDatatableEntry_FullDllName32 : LdrDatatableEntry_FullDllName64), 
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDatatableEntry_FullDllName32, 
#endif
                UnicodeString, 
                SizeOfUnicodeString, 
                NULL) == FALSE)
            return Size;

        ZeroMemory(lpFilename, nSize + 2);

        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Buffer : ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Buffer, 
                lpFilename, 
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Length &amp;lt;= nSize ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Length : nSize : ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Length &amp;lt;= nSize ? ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Length : nSize, // UnicodeString.Length &amp;lt;= nSize ? UnicodeString.Length : nSize, 
#else
                ((UNICODE_STRING *)UnicodeString)-&amp;gt;Buffer,
                lpFilename,
                ((UNICDOE_STRING *)UnicodeString)-&amp;gt;Length &amp;lt;= nSize ? ((UNICDOE_STRING *)UnicodeString)-&amp;gt;Length : nSize,
#endif
                &amp;amp;Size) == FALSE &amp;amp;&amp;amp; (RtlFreeHeap(_get_heap_handle(), 0, UnicodeString) || 1))
            return Size;

        free(UnicodeString);
        break;
    }

    return Size;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645082198033&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &quot;Rlibloaderapi.h&quot;

int main()
{
    DWORD PID;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf(&quot;OpenProcess Failed\n&quot;);
        printf(&quot;GetLastError : %d\n&quot;, GetLastError());
        return -1;
    }
    
    char buffer[MAX_PATH];
    
    HMODULE hModule = GetRemoteModuleHandleA(hProcess, &quot;kernel32.dll&quot;);
    GetRemoteModuleFileNameA(hProcess, hModule, buffer, MAX_PATH);
    
    printf(&quot;%s\n&quot;, buffer);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C/Remote libloaderapi.h</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/65</guid>
      <comments>https://crazyhacker.tistory.com/65#entry65comment</comments>
      <pubDate>Thu, 17 Feb 2022 16:16:47 +0900</pubDate>
    </item>
    <item>
      <title>[C] Rlibloaderapi.h - GetRemoteProcAddress</title>
      <link>https://crazyhacker.tistory.com/64</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetProcAddress&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;GetProcAddress 함수는 kernel32.dll에 정의되어 있는 함수이다. 인자로 HMODULE과 함수의 이름을 주고 호출하게되면 해당 DLL에서 Export 하는 함수들 중 인자로 넣은 함수의 이름과 같은 이름의 함수의 주소를 반환해준다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;이 함수도 마찬가지로 현재 프로세스를 기준으로 하게된다. 하지만 굳이 이 함수까지 구현한 이유는 DLL Injection과 같은 기술을 사용할 때 혹시라도 kernel32.dll의 ImageBase가 다르거나 특정 함수의 주소를 알아야할 때가 있을 것같아 해당 함수도 Remote 버전을 구현하게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetRemoteProcAddress&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645073753252&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;FARPROC GetRemoteProcAddress(HANDLE ProcessHandle, HMODULE hModule, LPCSTR lpProcName)
{
#ifdef _WIN64
    BOOL bWow64Process;
    IsWow64Process(ProcessHandle, &amp;amp;bWow64Process);
    size_t SizeOfPointer = bWow64Process ? 4 : 8;
#else
    size_t SizeOfPointer = 4;
#endif
    FARPROC Proc = NULL;
    ULONG_PTR ImageBase = hModule;
    IMAGE_DOS_HEADER DOS;

    if (ReadProcessMemory(ProcessHandle, hModule, &amp;amp;DOS, sizeof(IMAGE_DOS_HEADER), NULL) == FALSE)
        return Proc;
#ifdef _WIN64
    BYTE *NT = malloc(bWow64Process ? sizeof(IMAGE_NT_HEADERS32) : sizeof(IMAGE_NT_HEADERS64));
#else
    IMAGE_NT_HEADERS32 *NT = malloc(sizeof(IMAGE_NT_HEADERS32));
#endif

    if (ReadProcessMemory(ProcessHandle, ImageBase + DOS.e_lfanew, NT, _msize(NT), NULL) == FALSE &amp;amp;&amp;amp; IFREE(NT))
        return Proc;

    if (
#ifdef _WIN64
        (bWow64Process ? 
        ((IMAGE_NT_HEADERS32 *)NT)-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 
        :
        ((IMAGE_NT_HEADERS64 *)NT)-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) 
#else
        NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
#endif
         == NULL &amp;amp;&amp;amp; IFREE(NT))
        return Proc;

    IMAGE_EXPORT_DIRECTORY EXPORT;

    if (ReadProcessMemory(ProcessHandle, 
            ImageBase 
            + 
#ifdef _WIN64
            (bWow64Process ? 
            ((IMAGE_NT_HEADERS32 *)NT)-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 
            :
            ((IMAGE_NT_HEADERS64 *)NT)-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress), 
#else
            NT-&amp;gt;OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, 
#endif
            &amp;amp;EXPORT, 
            sizeof(IMAGE_EXPORT_DIRECTORY), 
            NULL) == FALSE &amp;amp;&amp;amp; IFREE(NT))
        return Proc;

    free(NT);

    for (DWORD i = 0; i &amp;lt; EXPORT.NumberOfNames; i++)
    {
        ULONG64 FunctionName = 0;
        char ch;

        if (ReadProcessMemory(ProcessHandle, ImageBase + EXPORT.AddressOfNames + i * 4, &amp;amp;FunctionName, 4, NULL) == FALSE)
            return Proc;
        
        FunctionName += ImageBase;

        for (DWORD j = 0; ReadProcessMemory(ProcessHandle, FunctionName + j, &amp;amp;ch, 1, NULL); j++)
        {
            if (ch != *(lpProcName + j))
                break;

            if (ch == NULL &amp;amp;&amp;amp; *(lpProcName + j) == NULL)
            {
                WORD Ordinal;
                if (ReadProcessMemory(ProcessHandle, ImageBase + EXPORT.AddressOfNameOrdinals + i * 2, &amp;amp;Ordinal, sizeof(WORD), NULL) == FALSE)
                    return Proc;

                if (ReadProcessMemory(ProcessHandle, ImageBase + EXPORT.AddressOfFunctions + Ordinal * 4, &amp;amp;Proc, SizeOfPointer, NULL) == FALSE)
                    return Proc;

                Proc += ImageBase;
                break;
            }
            else if (ch == NULL || *(lpProcName + j) == NULL)
                break;
        }

        if (Proc)
            break;
    }

    return Proc;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645073889976&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &quot;Rlibloaderapi.h&quot;

int main()
{
    DWORD PID;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf(&quot;OpenProcess Failed\n&quot;);
        printf(&quot;GetLastError : %d\n&quot;, GetLastError());
        return -1;
    }
    
    HMODULE hModule = GetRemoteModuleHandleA(hProcess, &quot;kernel32.dll&quot;);
    FARPROC pLoadLibraryA = GetRemoteProcAddress(hProcess, hModule, &quot;LoadLibraryA&quot;);
    
    printf(&quot;LoadLibraryA : %p\n&quot;, pLoadLibraryA);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1645074043281&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &quot;Rlibloaderapi.h&quot;

int main()
{
    DWORD PID;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf(&quot;OpenProcess Failed\n&quot;);
        printf(&quot;GetLastError : %d\n&quot;, GetLastError());
        return -1;
    }
    
    char Modulename[MAX_PATH];
    char Functionname[64];
    
    printf(&quot;Module name : &quot;);
    scanf(&quot;%s&quot;, Modulename);
    
    HMODULE hModule = GetRemoteModuleHandleA(hProcess, Modulename);
    
    if (hModule == NULL)
    {
    	printf(&quot;%s not found!\n&quot;);
        return -1;
    }
    
    printf(&quot;Function name : &quot;);
    scanf(&quot;%s&quot;, Function);
    
    FARPROC Functions = GetRemoteProcAddress(hProcess, hModule, Function);
    
    printf(&quot;%s : %p\n&quot;, Function, Functions);
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C/Remote libloaderapi.h</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/64</guid>
      <comments>https://crazyhacker.tistory.com/64#entry64comment</comments>
      <pubDate>Thu, 17 Feb 2022 14:00:47 +0900</pubDate>
    </item>
    <item>
      <title>[C] Rlibloaderapi.h - GetModuleHandle</title>
      <link>https://crazyhacker.tistory.com/63</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GetModuleHandle&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GetModuleHandle 함수는 kernel32.dll와 kernelbase.dll에 정의되어있는 함수이다. 해당 함수는 현재 프로세스에 로드된 DLL 중 인자로 넣은 &lt;span style=&quot;color: #ee2323;&quot;&gt;DLL 이름의 HMODULE을 반환&lt;/span&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;&lt;span style=&quot;color: #000000;&quot;&gt;HMODULE은 과거 윈도우에서 다른 용도로 만들어졌지만 &lt;span style=&quot;color: #ee2323;&quot;&gt;현재 윈도우에서는 DLL의 ImageBase를 담는 자료형&lt;/span&gt;이 되었다. 실제로 GetModuleHandle 함수를 이용해 특정 DLL의 HMODULE을 반환 받으면 해당 값은 해당 DLL의 ImageBase 인 것을 확인할 수 있다. 이 또한 현재 프로세스가 아닌 다른 프로세스에 로드된 DLL의 ImageBase를 구하기 위해 Remote 버전을 구현하게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GetRemoteModuleHandle&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645072711998&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;HMODULE GetRemoteModuleHandleA(HANDLE ProcessHandle, LPCSTR lpModuleName)
{
    HMODULE hModule = NULL;
    LPWSTR ModuleName = NULL;
    int ModuleNameLength = MultiByteToWideChar(CP_ACP, 0, lpModuleName, -1, NULL, 0);
    ModuleName = calloc(ModuleNameLength, sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, lpModuleName, -1, ModuleName, ModuleNameLength);
    hModule = GetRemoteModuleHandleW(ProcessHandle, ModuleName);
    free(ModuleName);
    return hModule;
}

HMODULE GetRemoteModuleHandleW(HANDLE ProcessHandle, LPCWSTR lpModuleName)
{
#ifdef _WIN64
    BOOL bWow64Process;
    IsWow64Process(ProcessHandle, &amp;amp;bWow64Process);
    size_t SizeOfPointer = bWow64Process ? 4 : 8;
#else
    size_t SizeOfPointer = 4;
#endif
    
    HMODULE hModule = NULL;
    PVOID PebBaseAddress = GetRemotePeb(ProcessHandle);

    if (PebBaseAddress == NULL)
        return hModule;

    PVOID PebLdrData = NULL;

    if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
            (ULONG_PTR)PebBaseAddress + (bWow64Process ? Peb_LdrOffset32 : Peb_LdrOffset64), 
#else
            (ULONG_PTR)PebBaseAddress + Peb_LdrOffset32,
#endif
            &amp;amp;PebLdrData, 
            SizeOfPointer, 
            NULL) == FALSE)
        return hModule;

#ifdef _WIN64
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64);
    size_t SizeOfUnicodeString = bWow64Process ? sizeof(UNICODE_STRING32) : sizeof(UNICODE_STRING64);
#else
    PVOID LdrDataTableEntry = (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32;
    size_t SizeOfUnicodeString = sizeof(UNICODE_STRING);
#endif

    BYTE *UnicodeString = calloc(1, SizeOfUnicodeString);

    for (LPWSTR ModuleName = NULL; ReadProcessMemory(ProcessHandle, LdrDataTableEntry, &amp;amp;LdrDataTableEntry, SizeOfPointer, NULL) 
            &amp;amp;&amp;amp; 
#ifdef _WIN64
            (ULONG_PTR)PebLdrData + (bWow64Process ? PebLdrData_LOMLOffset32 : PebLdrData_LOMLOffset64) != LdrDataTableEntry
#else
            (ULONG_PTR)PebLdrData + PebLdrData_LOMLOffset32 != LdrDataTableEntry
#endif
        ; free(ModuleName))
    {
        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDataTableEntry_BaseDllName32 : LdrDataTableEntry_BaseDllName64), 
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDataTableEntry_BaseDllName32,
#endif
                UnicodeString, 
                SizeOfUnicodeString, 
                NULL) == FALSE)
            return hModule;

#ifdef _WIN64
        ModuleName = malloc(bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Length + 2 : ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Length + 2);
#else
        ModuleName = malloc(sizeof(UNICODE_STRING));
#endif
        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Buffer : ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Buffer, 
                ModuleName,
                bWow64Process ? ((UNICODE_STRING32 *)UnicodeString)-&amp;gt;Length + 2 : ((UNICODE_STRING64 *)UnicodeString)-&amp;gt;Length + 2,
#else
                ((UNICODE_STRING *)UnicodeString)-&amp;gt;Buffer,
                ModuleName, 
                ((UNICODE_STRING *)UnicodeString)-&amp;gt;Length,
#endif
                NULL) == FALSE)
            return hModule;

        if (wcsicmp(lpModuleName, ModuleName))
            continue;

        if (ReadProcessMemory(ProcessHandle, 
#ifdef _WIN64
                (ULONG_PTR)LdrDataTableEntry + (bWow64Process ? LdrDataTableEntry_DllBase32 : LdrDataTableEntry_DllBase64), 
#else
                (ULONG_PTR)LdrDataTableEntry + LdrDataTableEntry_DllBase32,
#endif
                &amp;amp;hModule, 
                SizeOfPointer, // sizeof(HMODULE), 
                NULL) == FALSE &amp;amp;&amp;amp; (RtlFreeHeap(_get_heap_handle(), 0, ModuleName) || TRUE))
            return hModule;

        free(ModuleName);
        break;
    }

    free(UnicodeString);
    return hModule;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645072829506&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &quot;Rlibloaderapi.h&quot;

int main()
{
    DWORD PID;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf(&quot;OpenProcess Failed\n&quot;);
        printf(&quot;GetLastError : %d\n&quot;, GetLastError());
        return -1;
    }
    
    char Modulename[MAX_PATH];
    printf(&quot;Module name : &quot;);
    scanf(&quot;%s&quot;, Modulename);
    
    printf(&quot;%s : 0x%p&quot;, Modulename, GetRemoteModuleHandleA(hProcess, Modulename));
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C/Remote libloaderapi.h</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/63</guid>
      <comments>https://crazyhacker.tistory.com/63#entry63comment</comments>
      <pubDate>Thu, 17 Feb 2022 13:40:53 +0900</pubDate>
    </item>
    <item>
      <title>[C] Rlibloaderapi.h - GetRemotePeb</title>
      <link>https://crazyhacker.tistory.com/62</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;RtlGetCurrentPeb&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;RtlGetCurrentPeb 함수는 ntdll.dll의 함수이다. 해당 함수는 현재 프로세스의 PEB 구조체의 주소를 반환해준다. 해당 함수 또한 현재 프로세스의 PEB 주소만 구할 수 있고 다른 프로세스의 PEB 구조체의 주소를 구하기 위해서는 &lt;b&gt;NtQueryInformationProcess&lt;/b&gt; 라고 하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;커널 함수&lt;/span&gt;를 사용해야한다. (물론 해당 커널 함수를 사용해 PEB 구조체의 주소를 구해주는 다른 WINAPI도 존재한다. 하지만 내부적으로는 대부분 해당 커널 함수를 사용한다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론 여기까지 윈도우 시스템에 대해서 공부한 사람이랑 그냥 커널 함수를 쓰고 말겠지만 해당 커널 함수를 사용하면 다른 정보도 같이 구해지기 때문에 불필요한 공간을 사용하게 된다. 그렇기에 해당 함수를 사용하여 정확하게 PEB 구조체의 주소만 구해주는 함수를 제작하였다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GetRemotePeb&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645072110803&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PVOID GetRemotePeb(HANDLE ProcessHandle)
{
    PROCESS_BASIC_INFORMATION pbi = { 0, };
    NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &amp;amp;pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL);
#ifdef _WIN64
    BOOL bWow64Process;
    IsWow64Process(ProcessHandle, &amp;amp;bWow64Process);
    return bWow64Process ? (ULONG_PTR)pbi.PebBaseAddress + 0x1000 : pbi.PebBaseAddress;
    // WOW64로 돌아가는 32bit 프로세스의 PEB 구조체의 주소는 0x1000을 더해줘야 한다. 원인은 모르겠다.
#else
    return pbi.PebBaseAddress;
#endif
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1645072328371&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &quot;Rlibloaderapi.h&quot;

int main()
{
    DWORD PID;
    printf(&quot;PID : &quot;);
    scanf(&quot;%d&quot;, &amp;amp;PID);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    
    if (hProcess == NULL)
    {
    	printf(&quot;OpenProcess Failed\n&quot;);
        printf(&quot;GetLastError : %d\n&quot;, GetLastError());
        return -1;
    }
    
    printf(&quot;PEB : 0x%p&quot;, GetRemotePeb(hProcess));
    
    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>C/Remote libloaderapi.h</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/62</guid>
      <comments>https://crazyhacker.tistory.com/62#entry62comment</comments>
      <pubDate>Thu, 17 Feb 2022 13:33:12 +0900</pubDate>
    </item>
    <item>
      <title>[C] Remote libloaderapi.h 는 무엇인가...</title>
      <link>https://crazyhacker.tistory.com/61</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libloaderapi.h&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Remote liblaoderapi.h&lt;/b&gt; 를 설명하기 전에&amp;nbsp;&lt;b&gt;libloaderapi.h&lt;/b&gt;가 무엇인지 알아야한다. 아래 링크는 MSDN 공식 설명이다.&lt;/p&gt;
&lt;figure id=&quot;og_1645067237722&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Libloaderapi.h header - Win32 apps&quot; data-og-description=&quot;Table of contents Article 11/23/2021 3 minutes to read Is this page helpful? In this article --&amp;gt; This header is used by multiple technologies. For more information, see: libloaderapi.h contains the following programming interfaces: Functions &amp;nbsp; AddDllDirec&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/&quot; data-og-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Libloaderapi.h header - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Table of contents Article 11/23/2021 3 minutes to read Is this page helpful? In this article --&amp;gt; This header is used by multiple technologies. For more information, see: libloaderapi.h contains the following programming interfaces: Functions &amp;nbsp; AddDllDirec&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 설명해서 마이크로소프트의 libloaderapi.h 파일은&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/_intl/&quot; data-linktype=&quot;relative-path&quot;&gt;Windows 응용 프로그램의 국제화&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/_menurc/&quot; data-linktype=&quot;relative-path&quot;&gt;메뉴 및 기타 리소스&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/_base/&quot; data-linktype=&quot;relative-path&quot;&gt;시스템 서비스&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 관련된 프로그래밍 인터페이스(API)가 정의되어 있다. 이 중 시스템 서비스에 해당하는 함수들은 다음과 같다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;libloaderapi.h의 시스템 서비스 함수&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-adddlldirectory&quot;&gt;AddDllDirectory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-disablethreadlibrarycalls&quot;&gt;DisableThreadLibraryCalls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary&quot;&gt;FreeLibrary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibraryandexitthread&quot;&gt;FreeLibraryAndExitThread&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamea&quot;&gt;GetModuleFileNameA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew&quot;&gt;GetModuleFileNameW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea&quot;&gt;GetModuleHandleA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexa&quot;&gt;GetModuleHandleExA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw&quot;&gt;GetModuleHandleExW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew&quot;&gt;GetModuleHandleW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress&quot;&gt;GetProcAddress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya&quot;&gt;LoadLibraryA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa&quot;&gt;LoadLibraryExA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw&quot;&gt;LoadLibraryExW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw&quot;&gt;LoadLibraryW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-removedlldirectory&quot;&gt;RemoveDllDirectory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-setdefaultdlldirectories&quot;&gt;SetDefaultDllDirectories&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수들 중 대부분의 함수들은 현재 프로세스의 DLL과 관련되어 있는 함수들이다. 예를 들어 &lt;span style=&quot;color: #ee2323;&quot;&gt;GetModuleHandleA는 로드된 DLL들 중 특정 DLL의 HMODULE을 반환하는 함수&lt;/span&gt;이다. 하지만 여기있는 모든 함수들은 현재 프로세스(&lt;span style=&quot;color: #ee2323;&quot;&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;필자는 여기서 &lt;span style=&quot;color: #ee2323;&quot;&gt;다른 프로세스에 로드되어 있는 DLL들의 정보&lt;/span&gt;를 가져오고 싶었다. 물론 해당 동작을 해주는 함수들이 공식적으로 존재하지만 함수들의 동작방식이나 호출 방법 등이 마음에 들지 않아서 위의 몇몇 함수들을 직접 Remote 버전 즉 다른 프로세스를 대상으로 같은 기능을 하는 함수들을 구현하기로 결정했다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Rlibloaderapi.h (Remote libloaderapi.h)&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1645068445434&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - jungjin0003/Remote-libloaderapi: This library is a remote version of Windows API libloaderapi.h&quot; data-og-description=&quot;This library is a remote version of Windows API libloaderapi.h - GitHub - jungjin0003/Remote-libloaderapi: This library is a remote version of Windows API libloaderapi.h&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jungjin0003/Remote-libloaderapi&quot; data-og-url=&quot;https://github.com/jungjin0003/Remote-libloaderapi&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/EDP7U/hyNrKt6jcy/YZOzNAo1sRoertK6IUDjX0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/jungjin0003/Remote-libloaderapi&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jungjin0003/Remote-libloaderapi&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/EDP7U/hyNrKt6jcy/YZOzNAo1sRoertK6IUDjX0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - jungjin0003/Remote-libloaderapi: This library is a remote version of Windows API libloaderapi.h&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This library is a remote version of Windows API libloaderapi.h - GitHub - jungjin0003/Remote-libloaderapi: This library is a remote version of Windows API libloaderapi.h&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Rmote 버전이 구현된 libloaderapi.h의 시스템 서비스 함수&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GetModuleHandleA -&amp;gt; GetRemoteModuleHandleA&lt;/li&gt;
&lt;li&gt;GetModuleHandleW -&amp;gt; GetRemoteModuleHandleW&lt;/li&gt;
&lt;li&gt;GetModuleFileNameA -&amp;gt; GetRemoteModuleFileNameA&lt;/li&gt;
&lt;li&gt;GetModuleFileNameW -&amp;gt; GetRemoteModuleFileNameW&lt;/li&gt;
&lt;li&gt;GetProcAddress -&amp;gt; GetRemoteProcAddress&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;그 외 구현한 함수&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RtlGetCurrentPeb -&amp;gt; GetRemotePeb&lt;/li&gt;
&lt;li&gt;GetModuleBaseNameA -&amp;gt; GetRemoteModuleBaseNameA&lt;/li&gt;
&lt;li&gt;GetModuleBaseNameW -&amp;gt; GetRemoteModuleBaseNameW&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 카테고리에서는 이렇게 새롭게 구현한 함수들의 사용 예시를 올릴 예정이다.&lt;/p&gt;</description>
      <category>C/Remote libloaderapi.h</category>
      <author>미친해커</author>
      <guid isPermaLink="true">https://crazyhacker.tistory.com/61</guid>
      <comments>https://crazyhacker.tistory.com/61#entry61comment</comments>
      <pubDate>Thu, 17 Feb 2022 12:23:19 +0900</pubDate>
    </item>
  </channel>
</rss>