<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>commanderjjm 님의 블로그</title>
    <link>https://commanderjjm.tistory.com/</link>
    <description>commanderjjm 님의 블로그 입니다.</description>
    <language>ko</language>
    <pubDate>Thu, 10 Sep 2026 16:12:46 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>commanderjjm</managingEditor>
    <image>
      <title>commanderjjm 님의 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/8947914/attach/e3a37ba2f714499eba2e8536a13f8c6d</url>
      <link>https://commanderjjm.tistory.com</link>
    </image>
    <item>
      <title>VPN(Virtual Private Network)</title>
      <link>https://commanderjjm.tistory.com/9</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 VPN에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;VPN의 개념 자체는 그다지 어렵지 않지만, 파고들 수록 헷갈리고 어려운 개념이 많이 보이는 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 VPN에 대해서 기초적인 지식들을 알아보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;배경이야기&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;잠시 VPN 같은 사설망들이 등장하게된 계기에 대해서 이야기 해보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;여러분은 Internet이 어떻게 탄생했는지 아시나요?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1960년대 미국에는 대형 컴퓨터의 수가 적었고, 가격이 수백만 달러였습니다. 멀리 떨어진 대학의 연구원들이 이를 사용하려면 직접 가거나번거로운 과정을 거쳐야했죠. 이 컴퓨터들을 네트워크로 묶어 &quot;멀리서도 원격으로 접속해서 같이 사용하자&quot;는 목적으로 국방부와 대학에서 개발된 것이 ARPANET입니다. 현재 Internet의 모체가 되는 것이죠.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;고성능 컴퓨팅 성능을 공유하기 위해 개발된 ARPANET은 한정된 장소와 한정된 사람들만 사용하는 네트워크로 개발되었기 때문에, 암호화 기술이 적용되지 않았습니다. 이를 모체로하는 Internet의 IP 또한 통신 프로토콜의 목적일 뿐, 암호화 기능을 제공하지 않습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그렇기 때문에, 비밀통신이 필요한 사람들이 인터넷 상에서 통신하기 위해 개발된 것들이 VPN 같은 암호화 기능을 제공하는 것들입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;사설망과 전용 회선의 등장&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;IPv4의 32자리 주소 공간은 많다면 많지만, 적다면 적은 그런 숫자입니다. 인터넷의 폭발적인 수요로 인해 주소 공간이 부족해졌고, 이를 보완하기 위해 등장한 것이 사설망입니다. 사설망은 IPv4의 주소 대역 중 일부를 Private IP(이하 사설 IP)로 지정하여, 가정, 기업, 기관 등 근거리 통신망(LAN)을 구성할 수 있게합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;1068&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tIVbk/dJMcac5wZta/eaNbNBWkj0OJOmHkxpq6V0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tIVbk/dJMcac5wZta/eaNbNBWkj0OJOmHkxpq6V0/img.png&quot; data-alt=&quot;https://ko.wikipedia.org/wiki/사설망&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tIVbk/dJMcac5wZta/eaNbNBWkj0OJOmHkxpq6V0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtIVbk%2FdJMcac5wZta%2FeaNbNBWkj0OJOmHkxpq6V0%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;1068&quot; height=&quot;242&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://ko.wikipedia.org/wiki/사설망&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;사설 IP로 LAN을 구성함으로써, 격리된 망을 만들어낼 수 있습니다. 이 때 외부망과의 연결지점이 되는 것이 일반적으로 공유기입니다. NAT 프로토콜을 이용하여 LAN 내부 장치와 외부 네트워크와의 통신을 지원하죠.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;사설IP와 공인 IP에 대해서 한번 짚고 가겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;예를들어, @@시 @@구 @@동 **아파트 ##동 ##호가 있다고 합시다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아파트 명은 중복될 수 있기 때문에, @@시 @@구 @@동까지가 공인 IP가 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이후에 **아파트 ##동 ##호는 사설 IP가 되겠지요. 이처럼 공인 IP는 인터넷 상에서 &quot;유일&quot;하게 식별되어야하며, 중복될 수 없습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;반면에, 사설 IP는 여러 지역에서 동일한 이름으로 사용될 수 있지만, 같은 지역 내에서는 유일하게 식별되는 아파트/동/호수와 비슷한 개념입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다양한 사설망들이 구성되면서, 멀리 떨어진 사설망들과 공인IP가 아닌, 사설 IP를 통한 연결에 대한 필요성이 점점 증가합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;주로 기업들에 의한 수요였죠. 이를 위해 등장한 것이 전용회선(Leased Line)이 되겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;전용회선(Leased Line)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_pwmf7cpwmf7cpwmf.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v9nbC/dJMcadDcQyv/rTPJoGcpq9PsT6XbZMgqyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v9nbC/dJMcadDcQyv/rTPJoGcpq9PsT6XbZMgqyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v9nbC/dJMcadDcQyv/rTPJoGcpq9PsT6XbZMgqyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv9nbC%2FdJMcadDcQyv%2FrTPJoGcpq9PsT6XbZMgqyk%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_pwmf7cpwmf7cpwmf.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;전용 회선이란, 특정 고객이 인터넷 서비스 제공자(ISP)에게 비용을 지불하고, 회선의 일부를 전용으로 임대해서 사용하는 통신회선입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 기업들이 본사와 지사 네트워크의 사설망을 서로 연결하기 위해 할당받습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;ISP의 대역폭 일부를 완전히 독점하여 사용하기 때문에, 내부 트래픽이 아니면 접근할 수 없어 데이터의 안전이 보장되며, 사설 IP로 두 망이 연결됩니다. 그러나 대역폭 사용량 만큼 값을 치루기 때문에, 비용이 매우 비싸다는 단점이 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;결국 전용회선보다 저렴하고, IP의 데이터 암호화 문제를 해결하기 위해 등장한 것이 VPN입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;VPN(Virtual Private Network)&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이름에서 알 수 있 듯이, 공인 IP를 이용하여 다른 사람들에게 보이지 않도록 통신하기 위한 기술을 논리적으로 구현한 것입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;구현 방식은 간단하게 설명하면 아래와 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1. VPN 장비는 각 종단의 VPN 장비끼리 데이터 암호화 및 인증 방식에 대해서 협상을 진행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2. 협상이 완료되면, 두 사설망 사이에 연결 고리가 생기는데 이를 터널이 뚫렸다고 표현한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;3. 이후 암호화 및 캡슐화가 적용된 패킷이 오고간다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 기술을 터널링이라고 표현하며, 여기에 사용된 프로토콜들을 터널링 프로토콜(Tunneling Protocol)이라고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 과정에 VPN 장비끼리 주고받는 패킷은 모두 VPN 서버를 거치게 되고, 목적지 서버에 찍히는 로그는 사용자의 IP가 아닌, VPN 서버의 IP가 찍히게 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 VPN은 공인 인터넷을 경로로 사용하기 때문에, 전용회선보다 더 넓은 대역폭을 저렴한 비용으로 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 보안 수준은 대역폭을 독점하는 전용회선보다는 약하다는 단점이 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 대역폭을 보장해주는 전용회선과 달리, 공인 인터넷 대역폭을 사용하기 때문에, 인터넷 망에 문제가 생기면, 터널이 끊어지거나 패킷이 제대로 전달되지 않을 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;VPN의 분류와 구현, 차이&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;VPN의 종류는 접속 방식, 터널링 프로토콜, 통신 계층(OSI 7 계층 기반), 운용 주체 등 기준에 따라 아래와 같이 나뉩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;접속 방식: Site to Site/ Client to Site&lt;/li&gt;
&lt;li&gt;터널링 프로토콜: PPTP/L2TP, IPSec, SSL 기반&lt;/li&gt;
&lt;li&gt;통신 계층:L2/L3/L4 기반&lt;/li&gt;
&lt;li&gt;운용 주체: Core/CPE 기반&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위 분류에 따라 하나씩 조합하여 특정 기능을 수행하는 VPN을 만들 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;실제로 다양한 유형과 종류의 VPN이 만들어지고 있고, 사용되고 있으므로 대표적인 유형의 두가지 VPN을 살펴보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;1. IPSec VPN&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Site to Site 기반의 접속 방식을 채택한 IPSec 프로토콜의 VPN입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;기업의 본사 네트워크와 지사 네트워크를 연결하는 용도로 주로 사용됩니다. IPSec 프로토콜을 통해 터널링을 수행하며, 이는 L3(Network Layer)에서 수행됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;IP의 약점과 패킷의 보안 취약성을 해결하는 데 중점을 둡니다. 또한 엔드 포인트에서 직접 VPN을 설치하는게 아니라 라우터와 라우터끼리 설정을 하는 방식입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;IPSec 프로토콜의 상세한 내용은 다음에 기회가 되면 다루어 보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HPSEb/dJMcagUrm6P/9yU7aYYi7D0kzmaZY0d2r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HPSEb/dJMcagUrm6P/9yU7aYYi7D0kzmaZY0d2r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HPSEb/dJMcagUrm6P/9yU7aYYi7D0kzmaZY0d2r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHPSEb%2FdJMcagUrm6P%2F9yU7aYYi7D0kzmaZY0d2r1%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;1076&quot; height=&quot;624&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;실제 구현 흐름은 아래와 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;Phase 1(IKE SA): 양쪽 방화벽이 서로를 인증하고, 관리용 보안 채널을 만드는 단계, 양쪽에서 IKE 버전과 인증 방식, 암호화/해시 알고리즘이 정확히 일치해야한다.&lt;/li&gt;
&lt;li&gt;Phase2(IPSec SA): Phase 1에서 만든 보안 채널 위에서 실제 데이터 트래픽을 암호화할 터널의 파라미터를 협상하는 단계이다. 어떤 서브넷 간의 트래픽을 보호할지, 암호화 알고리즘, SA 수명 등을 합의한다. 이후 실제 데이터 트래픽은 Phase1에서 만든 보안 채널을 사용하지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 과정에 사용되는 장비나 도구는 CIsco ASA/IOS, pfSense/OPNsense 등이 있다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2. SSL VPN&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;원격 액세스 VPN이라고도 하며, 주로 Client to Site 방식으로 사용되어 사용자가 어느 장소에서든 기업의 사설 네트워크로 접속할 수 있도록 지원합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;우리가 일반적으로 생각하는 VPN 유형이죠.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;SSL 프로토콜을 사용하여 터널링을 수행하며, L4(Transport Layer)에서 실시됩니다. 이 또한 IP의 약점, 패킷의 보안 취약성을 해결하는데 중점을 둡니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;1060&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baumcl/dJMcaixZVYw/Zu450O6Kg93gTeFXOVCdBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baumcl/dJMcaixZVYw/Zu450O6Kg93gTeFXOVCdBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baumcl/dJMcaixZVYw/Zu450O6Kg93gTeFXOVCdBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaumcl%2FdJMcaixZVYw%2FZu450O6Kg93gTeFXOVCdBk%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;1060&quot; height=&quot;418&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Open VPN을 예로 들어 실제 구현 흐름을 살펴보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;서버에 Open VPN 설치 -&amp;gt; PKI 구성&amp;nbsp; -&amp;gt; 서버 설정 파일 작성(리스닝 포트, 암호화 스위트) -&amp;gt; 방화벽에서 해당 포트 오픈 및 NAT 설정 -&amp;gt; 클라이언트에 .ovpn 설정 파일 배포 -&amp;gt; 클라이언트가 인증서 + 계정으로 접속&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;PKI: CA 인증서, 서버 인증서, 클라이언트 인증서 발급/ 인증서와 공개키를 이용해서 서버와 클라이언트의 신원을 인증하는 체계&lt;/li&gt;
&lt;li&gt;암호화 스위트: 통신에 사용할 암호화/인증 알고즘 조합, 클라이언트에 할당할 IP 대역, 푸시할 라우팅 정보&lt;/li&gt;
&lt;li&gt;.ovpn 설정 파일: 클라이언트가 VPN 서버에 접속하기 위한 설정 정보&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 때 주로 사용되는 장비와 도구는 서버쪽은 IPSec과 거의 동일하지만, 클라이언트는 단말기에 전용 VPN 클라이언트를 설치해야합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Site to Site는 항시 뚫려있는 터널인 반면, Client to Site는 사용자가 필요할 때 연결하고 끊는 온디맨드 터널입니다. 그래서 인증 체계가 훨신 중요하고,&amp;nbsp; 동시 접속자 수 관리, 클라이언트 배포/업데이트 관리 같은 운영 이슈가 추가 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;마찬가지로 SSL 프로토콜&amp;nbsp; 또한 다음에 기회가 되면 다루어 보겠습니다. 프로토콜 깊이가 만만치 않네요;;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다음으로, Proton VPN을 이용하여 VPN 적용 전후의 IP 변화를 살펴보는 실습을 진행했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;VPN 적용 전:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-09-07 오후 4.38.44.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHQhOX/dJMcabem5mx/6IykycArkwIs5vO3OsQHM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHQhOX/dJMcabem5mx/6IykycArkwIs5vO3OsQHM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHQhOX/dJMcabem5mx/6IykycArkwIs5vO3OsQHM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHQhOX%2FdJMcabem5mx%2F6IykycArkwIs5vO3OsQHM1%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;1060&quot; height=&quot;234&quot; data-filename=&quot;스크린샷 2026-09-07 오후 4.38.44.png&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;VPN 적용 후:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tPbvO/dJMcaa7Qg6J/jAeSzphDMYWuV6k7wds8pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tPbvO/dJMcaa7Qg6J/jAeSzphDMYWuV6k7wds8pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tPbvO/dJMcaa7Qg6J/jAeSzphDMYWuV6k7wds8pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtPbvO%2FdJMcaa7Qg6J%2FjAeSzphDMYWuV6k7wds8pk%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;1054&quot; height=&quot;406&quot; data-origin-width=&quot;1054&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2로 시작하던 제 공인 IP가 VPN 적용 후 Proton에서 운영하는 IP 주소 대역으로 바뀐 것을 확인할 수 있었습니다. 이러한 VPN 서비스를 제공하는 회사들의 대역은 악성 사용자들 때문에, 이를 차단한 사이트가 많다고 하네요.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;최근에는 VPN의 보안 조치가 부족하다는 판단에 따라, 제로 트러스트(Zero Trust) 모델이 활발하게 사용되고 있다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;기존 VPN은 터널 내에 들어오기만 하면, 신뢰하는 구조였는데, 제로 트러스트는 내부에서도 매 요청마다 검증하는 방식을 채택한다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 이렇게 VPN에 대한 기초 지식을 살펴보았습니다. 읽어 주셔서 감사합니다.&lt;/p&gt;</description>
      <category>개념 정리/네트워크</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/9</guid>
      <comments>https://commanderjjm.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 7 Sep 2026 16:44:08 +0900</pubDate>
    </item>
    <item>
      <title>About Proxy</title>
      <link>https://commanderjjm.tistory.com/8</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;들어가기 앞서&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 앞으로의 제 블로그 방향성을 조금 정립해보고자 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;지난주에 기업 대표님의 강연을 들었는데, 기술 블로그는 진지하게 작성해야 한다는 말씀을 듣고 앞으로는 잡설과 주제에 어긋난 이미지는 제외하고 오로지 제가 공부한 내용만 정리해보려고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;앞선 글도 일부 새로운 방향성에 맞춰 수정은 해놓긴했는데, 그건 그냥 놔두고 앞으로 방향성에 맞춰 잘 쓰기로 했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘 정리할 Proxy에 대한 내용은 적절한 관련 시각 자료를 찾기 힘들어서, AI의 그림을 이용했습니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;Proxy란 무엇일까?&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 말하자면, 클라이언트와 서버가 통신할 때, 중간에서 &quot;중계 역할을 수행하는 서버&quot;를 말합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by7lIb/dJMcahMvaFp/fAgBQZuSKiikexuBEykaU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by7lIb/dJMcahMvaFp/fAgBQZuSKiikexuBEykaU1/img.png&quot; data-alt=&quot;리버스 프록시의 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by7lIb/dJMcahMvaFp/fAgBQZuSKiikexuBEykaU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby7lIb%2FdJMcahMvaFp%2FfAgBQZuSKiikexuBEykaU1%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;1064&quot; height=&quot;540&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리버스 프록시의 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위 이미지와 같은 구조로 구성되어 중간에서 클라이언트와 서버의 상호작용을 중계해줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 종류에 따라 프록시의 위치가 달라집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;Proxy 서버가 수행하는 역할&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 다수의 클라이언트가 서버에 연결을 시도하게되므로, 클라이언트가 많을 수록 서버의 부담이 커지게 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;1. 보안 및 익명성&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_qyphjuqyphjuqyph.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DVfA7/dJMcafH396W/K2RaJyHxamm7qLxx6ozKaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DVfA7/dJMcafH396W/K2RaJyHxamm7qLxx6ozKaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DVfA7/dJMcafH396W/K2RaJyHxamm7qLxx6ozKaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDVfA7%2FdJMcafH396W%2FK2RaJyHxamm7qLxx6ozKaK%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_qyphjuqyphjuqyph.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Proxy 서버는 클라이언트와 서버 사이에 간접적인 연결을 제공하므로, 사용자의 IP를 숨겨 개인정보를 보호합니다&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;참고로 여기서 사용자의 IP를 숨기는 대상은 Origin 서버 측이 아닙니다. 경우에 따라 Origin 서버는 사용자의 IP가 필요한 일이 많으므로, Origin 서버에게 숨겨선 안됩니다. IP를 숨기는 대상은 외부 공격자가 됩니다. 프록시 서버를 거쳐가는 패킷을 공격자가 탈취한다면, 공격자에게는 프록시 서버의 IP만 보일 뿐, 사용자 IP는 보이지 않습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이를 이해하기 위한 &quot;익명 프록시&quot;에 대한 개념은 후술하도록 하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;2. 성능 최적화&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_izirgxizirgxizir.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv2Qzg/dJMcadja28e/S8vhdRk26w8Iwas6Q0w7x0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv2Qzg/dJMcadja28e/S8vhdRk26w8Iwas6Q0w7x0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv2Qzg/dJMcadja28e/S8vhdRk26w8Iwas6Q0w7x0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv2Qzg%2FdJMcadja28e%2FS8vhdRk26w8Iwas6Q0w7x0%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_izirgxizirgxizir.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;자주 요청되는 데이터를 프록시 서버가 캐시하였다가 동일한 데이터를 요청 받았을 때, Origin 서버를 거치지 않고 바로 제공합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이를 통해 Origin 서버의 부하를 줄일 수 있고, 클라이언트는 더 빠른 응답을 받을 수 있게됩니다. 오리진 서버에서는 DB에서 데이터를 찾고, 로직을 계산하는 등 무거운 작업을 많이 해야하지만, 프록시는 오직 캐시된 데이터를 보여줄 뿐이므로, 프록시 서버에게 가해지는 부담도 적은 편입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;3. 필터링&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_bctclxbctclxbctc.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5S7EW/dJMcaaNuFWE/eknpoNx6SFPcXjhp1N7G11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5S7EW/dJMcaaNuFWE/eknpoNx6SFPcXjhp1N7G11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5S7EW/dJMcaaNuFWE/eknpoNx6SFPcXjhp1N7G11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5S7EW%2FdJMcaaNuFWE%2FeknpoNx6SFPcXjhp1N7G11%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_bctclxbctclxbctc.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프록시에게 들어온 요청들을 정책에 따라 방화벽처럼 일부 차단할 수 있습니다. 국가별/IP별로 차단이 가능하며, 필터링 요청을 로그로 기록하여 분석에도 용이하게 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;4. 부하 분산&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_9lkkpq9lkkpq9lkk.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HYZ4N/dJMcabZYiVl/n4jIAM65tYlabig2LCYItK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HYZ4N/dJMcabZYiVl/n4jIAM65tYlabig2LCYItK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HYZ4N/dJMcabZYiVl/n4jIAM65tYlabig2LCYItK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHYZ4N%2FdJMcabZYiVl%2Fn4jIAM65tYlabig2LCYItK%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_9lkkpq9lkkpq9lkk.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;클라이언트로부터 온 다수의 요청을 알고리즘에 따라 여러 오리진 서버로 나누어서 요청을 전송합니다. 물론 그 전에 캐시로 처리할 수 있는 요청이면 프록시 선에서 처리하게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;5. 암호화 처리&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_owc74dowc74dowc7.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbtLRD/dJMcagUrhXY/4mOWJMWXfnhtF0c4p09Gb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbtLRD/dJMcagUrhXY/4mOWJMWXfnhtF0c4p09Gb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbtLRD/dJMcagUrhXY/4mOWJMWXfnhtF0c4p09Gb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbtLRD%2FdJMcagUrhXY%2F4mOWJMWXfnhtF0c4p09Gb1%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_owc74dowc74dowc7.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;클라이언트와 서버가 주고받는 암호화된 트래픽을 프록시가 대신 복호화합니다. 암호화와 복호화는 수학적으로 매우 복잡한 연산이기 때문에, 고성능 프록시가 이를 대신 수행하여, 오리진 서버의 부담을 줄여줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;6. 로깅 및 모니터링&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Gemini_Generated_Image_6kpytx6kpytx6kpy.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvBHDf/dJMcagz5AmR/NOuBeRK9EprPyZJiaWG5K0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvBHDf/dJMcagz5AmR/NOuBeRK9EprPyZJiaWG5K0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvBHDf/dJMcagz5AmR/NOuBeRK9EprPyZJiaWG5K0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvBHDf%2FdJMcagz5AmR%2FNOuBeRK9EprPyZJiaWG5K0%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;2816&quot; height=&quot;1536&quot; data-filename=&quot;Gemini_Generated_Image_6kpytx6kpytx6kpy.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프록시 서버는 모든 통과하는 패킷의 명세를 로그로 기록합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;종합적으로 살펴보자면, 프록시 서버의 주된 목적은 오리진 서버의 부하 분산과 캐싱을 통한 클라이언트에 대한 빠른 응답이 주목적이 되겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;프록시 서버의 종류&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프록시 서버의 종류는 크게 두가지로 나뉩니다. Forward-Proxy와 Reverse-Proxy인데요. 자세히 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;1. Forward-Proxy&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;포워드 프록시란 클라이언트와 서버 사이에서 클라이언트의 요청을 대신 전달하는 프록시입니다. 단순히 설명만 보면, 보편적인 프록시의 설명과 뭐가 다른지 헷갈릴 수 있는데, 먼저 그림을 살펴보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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;1060&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/94Nrc/dJMcagNLfka/1PDM2knH7X20jrhoOwikB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/94Nrc/dJMcagNLfka/1PDM2knH7X20jrhoOwikB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/94Nrc/dJMcagNLfka/1PDM2knH7X20jrhoOwikB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F94Nrc%2FdJMcagNLfka%2F1PDM2knH7X20jrhoOwikB0%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;1060&quot; height=&quot;574&quot; data-origin-width=&quot;1060&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위 그림과 같이 구성된 프록시를 포워드 프록시라고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;포워드 프록시는 개인정보 보호에 대한 성격이 강한 편인데, 사내 컴퓨터나 교내 컴퓨터에서 외부 네트워크에 접속할 때&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;포워드 프록시만을 거쳐서 나가게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이를 통해 개인 PC의 IP도 보호가 가능하고, 클라이언트가 금지된 사이트에 접속하는 것을 방지할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2. Reverse-Proxy&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 떠올리는 프록시 유형입니다. 포워드 프록시와는 달리 서버를 보호하기 위한 프록시입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8n8U0/dJMcadccwRw/I5C5KLX6n6CxaS6XKlC5Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8n8U0/dJMcadccwRw/I5C5KLX6n6CxaS6XKlC5Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8n8U0/dJMcadccwRw/I5C5KLX6n6CxaS6XKlC5Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8n8U0%2FdJMcadccwRw%2FI5C5KLX6n6CxaS6XKlC5Gk%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;1058&quot; height=&quot;536&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;처음 프록시에 대해서 언급할 때 보여드렸던 이미지입니다. 프록시 서버는 오리진 서버의 앞단에 위치하게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;먼저, 악성 클라이언트가 웹페이지 주소를 통해 IP를 알아내려하는 경우를 살펴보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;클라이언트의 패킷은 프록시를 거쳐서 오리진 서버에 전달되기 때문에, 악성 클라이언튼느 프록시 서버의 IP만 보이게됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 외부 공격이나 악성 봇들로부터 서버를 보호하고, 클라이언트의 요청을 여러 서버에 분산하는 역할을 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이를 로드밸런싱이라고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;보통 인터넷 상에서는 한 가지 유형의 프록시만으로 구성되지 않고, 둘 다 섞어서 사용합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이걸 Proxy chaining이라고합니다.&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;1066&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfJ6Zr/dJMcabFuYbN/IpmUdYcXHF1d7t1mYIl1fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfJ6Zr/dJMcabFuYbN/IpmUdYcXHF1d7t1mYIl1fK/img.png&quot; data-alt=&quot;프록시 체이닝의 예시&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfJ6Zr/dJMcabFuYbN/IpmUdYcXHF1d7t1mYIl1fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfJ6Zr%2FdJMcabFuYbN%2FIpmUdYcXHF1d7t1mYIl1fK%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;1066&quot; height=&quot;308&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프록시 체이닝의 예시&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 어떤 목적의 프록시로 사용함에 따라 나눌 수도 있습니다. HTTP, VPN, DNS, Socket 등 다양한 용도에 프록시를 사용할 수 있으며, 결국 중계와 보호의 목적은 동일하다고 볼 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이제 앞서 언급한 &quot;익명성 프록시&quot;에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;익명성 프록시&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;익명성 프록시는 레벨에 따라 클라이언트 IP 및 프록시 사용 여부를 얼마나 드러낼지 결정하여 오리진 서버에게 요청을 전달할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;설명만 들으면 무슨 말인지 이해하기 어려우니 HTTP를 예시로 든 아래 표를 한번 살펴보겠습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100.93%; height: 74px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 22.3502%; text-align: center; height: 19px;&quot;&gt;익명성 등급&lt;/td&gt;
&lt;td style=&quot;width: 27.6498%; text-align: center; height: 19px;&quot;&gt;X-Forward-For&lt;/td&gt;
&lt;td style=&quot;width: 17.9724%; text-align: center; height: 19px;&quot;&gt;Via 헤더&lt;/td&gt;
&lt;td style=&quot;width: 32.9578%; text-align: center; height: 19px;&quot;&gt;Origin 서버가 아는 정보&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 22.3502%; text-align: center; height: 19px;&quot;&gt;Level 3. 투명 프록시&lt;/td&gt;
&lt;td style=&quot;width: 27.6498%; text-align: center; height: 19px;&quot;&gt;사용자 실제 IP 포함&lt;/td&gt;
&lt;td style=&quot;width: 17.9724%; text-align: center; height: 19px;&quot;&gt;프록시 정보 포함&lt;/td&gt;
&lt;td style=&quot;width: 32.9578%; text-align: center; height: 19px;&quot;&gt;프록시를 썼고, 클라이언트의 IP는 X임&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 22.3502%; text-align: center; height: 18px;&quot;&gt;Level 2. 익명 프록시&lt;/td&gt;
&lt;td style=&quot;width: 27.6498%; text-align: center; height: 18px;&quot;&gt;사용자 실제 IP 삭제&lt;/td&gt;
&lt;td style=&quot;width: 17.9724%; text-align: center; height: 18px;&quot;&gt;프록시 정보 포함&lt;/td&gt;
&lt;td style=&quot;width: 32.9578%; text-align: center; height: 18px;&quot;&gt;프록시를 썼지만, 클라이언트의 IP는 모름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 22.3502%; text-align: center; height: 18px;&quot;&gt;Level 1. 엘리트 프록시&lt;/td&gt;
&lt;td style=&quot;width: 27.6498%; text-align: center; height: 18px;&quot;&gt;완전 삭제(또는 프록시 IP로 덮어씀)&lt;/td&gt;
&lt;td style=&quot;width: 17.9724%; text-align: center; height: 18px;&quot;&gt;완전 삭제&lt;/td&gt;
&lt;td style=&quot;width: 32.9578%; text-align: center; height: 18px;&quot;&gt;프록시 사용 여부, 사용자 IP 모두 모름&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위 표와 같이 익명성 레벨에 따라 서버에게 공개되는 정보가 다릅니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;익명성 레벨은 자유롭게 설정이 가능하며, 사용 중에 유연하게 변경할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;X-Forward-For는 HTTP 프로토콜의 헤더이며, 프록시가 이 필드에 클라이언트의 IP를 작성합니다. HTTP는 평문으로 전송되기 떄문에, 외부 공격자로부터 보호하기 위해서는 HTTPS로 보내게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Via 헤더는 HTTP 메시지가 최종 목적지에 도달하기까지 어떤 프록시와 게이트웨이를 거쳐왔는지 경로를 기록하는 헤더입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;HTTP 프로토콜을 예시로 익명성 프록시를 살펴보았지만, DNS/VPN 등 다양한 용도에 적용되는 프록시에 따라, 익명성 보장 기법과 보호하고자하는 대상이 다릅니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 이렇게 Proxy의 정의와 원리, 유형에 대해서 알아보았습니다. 감사합니다.&lt;/p&gt;</description>
      <category>개념 정리/네트워크</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/8</guid>
      <comments>https://commanderjjm.tistory.com/8#entry8comment</comments>
      <pubDate>Mon, 7 Sep 2026 15:23:22 +0900</pubDate>
    </item>
    <item>
      <title>x86-64 Architecture</title>
      <link>https://commanderjjm.tistory.com/7</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;반갑습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 몇 주전에 정리해놓은 x86 아키텍처에 대해서 정리해보려고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;1.&amp;nbsp; x86-64의 분류&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일단 학부 컴퓨터 구조 강의 시간에 RISC 구조와 CISC 구조에 대해서 배웠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 정리하자면 RISC는 Reduced Instruction Set Computer의 약자로, 매우 간단하고 짧은 최소한의 CPU 명령어만을 가집니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이는 CPU 활용률을 최대한 올리기 위한 파이프라이닝 구현에 적합하죠. 그러나 복잡한 명령어의 기능을 수행하기 위해선, 여러 명령어를 조합해야되기 때문에, 오버헤드가 발생한다는 단점이 있습니다.&lt;br /&gt;반대로 CISC는 Complex Instruction Set Computer의 약자로, RISC보다 더욱 복잡하고 가변적인 길이의 CPU 명령어 셋을 가집니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;같은 기능을 수행하기 위해 RISC보다 적은 명령어 수를 사용하지만, 현대 컴퓨터 성능의 핵심 역할을 하는 파이프라이닝을 구현하는 것에 한계가 있다는 단점이 있습니다. 최근 대부분의 컴퓨터 아키텍처들은 RISC 구조를 채택합니다만, CISC의 일부 장점을 조합하여 구현한다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;x86-64 아키텍처 또한 RISC와 CISC의 명령어를 내부 하드웨어 디코더가 변환하여 RISC 명령어로 해석해주는 구조를 갖는다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 관례적으로 x86을 교육용으로 많이 사용해왔기 때문에, 리버싱을 공부하는 사람들에게 중요하게 다뤄진다고 하네요.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100.812%; height: 140px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;분류&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;의미&lt;/td&gt;
&lt;td style=&quot;width: 11.2745%; height: 19px;&quot;&gt;파이프라이닝&lt;/td&gt;
&lt;td style=&quot;width: 39.5395%; height: 19px;&quot;&gt;특징&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 58px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 58px;&quot;&gt;RISC&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 58px;&quot;&gt;Reduced Instruction Set Computer&lt;/td&gt;
&lt;td style=&quot;width: 11.2745%; height: 58px;&quot;&gt;가능&lt;/td&gt;
&lt;td style=&quot;width: 39.5395%; height: 58px;&quot;&gt;간단한 CPU 명령어 셋, 그러나 고정된 길이와 정해진 명령어만 수행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 63px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 63px;&quot;&gt;CISC&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 63px;&quot;&gt;Complex Instruction Set Computer&lt;/td&gt;
&lt;td style=&quot;width: 11.2745%; height: 63px;&quot;&gt;불가능&lt;/td&gt;
&lt;td style=&quot;width: 39.5395%; height: 63px;&quot;&gt;복잡하고 가변적인 CPU 명령어 셋, 그러나 파이프라이닝을 구현하지 못함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;2. x86-64의 레지스터 종류&lt;/h2&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2-1. 범용 레지스터&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;x86에는 총 16개의 범용 레지스터가 존재합니다. 각 레지스터는 하위 비트에 대한 부분적인 접근이 가능하며, 기본적으로 데이터 저장의 역할을 합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 98.8372%; height: 381px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;64비트&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;32비트&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;16비트&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;LSB 8비트&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;MSB 8비트&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;의미&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;주요 용도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RAX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;EAX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;AX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;AL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;AH&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Accumulator&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;산술 연산 결과, 함수 리턴값 등을 저장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RBX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;EBX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;BX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;BL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;BH&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Base&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;범용, Callee-Saved 규약을 따름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RCX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;ECX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;CX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;CL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;CH&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Counter&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;루프 카운터, 시프트 연산의 횟수를 지정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RDX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;EDX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;DX&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;DL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;DH&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Data&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;곱셈/나눗셈에서 RAX와 연계되어 확장된 데이터를 표현, 함수 호출 시 인자 전달 역할&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RSI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;ESI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;SI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;SIL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Source Index&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;문자열/메모리 복사의 소스 주소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RDI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;EDI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;DI&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;DIL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Destination Index&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;문자열/메모리의 목적지 주소&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RBP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;EBP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;BP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;BPL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Base Pointer&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;스택 프레임의 베이스 주소/로컬 변수/인자/참조 기준점 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;RSP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;ESP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;SP&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;SPL&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;Stack Pointer&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;스택의 최상단 주소, PUSH/POP 또는 기계어 CALL/RET에 의해 계속 변경&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;R8-R15&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;R8D~R15D&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;R8W~R15W&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;R8B~R15B&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;번호&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;각 레지스터 이름에는 나름의 의미가 존재합니다. 과거 x86-32 시절부터 존재하던 레지스터들은 레지스터 크기가 커지는 과정에서 R,E 등이 붙게되었죠. 이러한 패턴이 보이지 않는 Rn번대 레지스터들은 이후에 새로 생긴 레지스터들이라서 작명이 다르게 붙었다고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 RDX와 EDX같이 동일 종류의 레지스터들은 별개로 존재하는 레지스터가 아닙니다. 같은 레지스터를 몇 비트로 잘라서 보느냐에 따라 이름이 달라집니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3rzFy/dJMcahZWKMa/6dNqI2qksUx7TX58Tko2MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3rzFy/dJMcahZWKMa/6dNqI2qksUx7TX58Tko2MK/img.png&quot; data-alt=&quot;이런 느낌으로 봐주시면 될 것 같네요&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3rzFy/dJMcahZWKMa/6dNqI2qksUx7TX58Tko2MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3rzFy%2FdJMcahZWKMa%2F6dNqI2qksUx7TX58Tko2MK%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;1208&quot; height=&quot;650&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이런 느낌으로 봐주시면 될 것 같네요&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2.2 명령어 포인터&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;RIP(Instruction Register)란 다음으로 실행할 명령어의 주소가 저장되는 레지스터입니다. 즉, Program Counter(PC)가 이 곳에 저장되겠죠. 이 레지스터는 악의적인 수정 방지를 위해 mov로 직접 수정이 불가능합니다. 또한 명령어의 위치를 계산할 때는 RIP-relative addressing, 즉 RIP + offset이 기본 주소 지정 방식이 됩니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2.3 플래그 레지스터&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;비교,&amp;nbsp; 조건, 분기 명령어가 등장했을 때, CPU가 결과를 확인하기 위해 참고하는 비트들을 flag라고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 플래그들은 x86-64에서는 하나의 64비트짜리 RFLAGS라는 레지스터의 각 자리를 차지합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;비트에 따라 레지스터 이름도 바뀌고, 빈자리는 또 다른걸 의미하고... 여러 가지로 복잡해지니 이번 포스팅에서는 리버싱을 진행할 때 도움되는 flag 자체의 의미를 정리하겠습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 152px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;플래그&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;이름&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;ZF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;ZeroFlag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;연산 결과가 0이면 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 39px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;SF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;SignFlag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;연산결과의 최상위 비트를 저장. 음수 판단 여부에 사용됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 39px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;CF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;CarryFlag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 39px;&quot;&gt;unsigned 연산에서 올림/빌림 발생 시 1을 저장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;OF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;OverflowFlag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;signed 연산에서 오버플로 발생 시 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;DF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;Direction Flag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 18px;&quot;&gt;문자열 연산 방향. 0이면 앞 -&amp;gt; 뒤 / 1이면 뒤 -&amp;gt; 앞으로 연산&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;PF&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;ParityFlag&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;결과의 하위 바이트에서 1인 비트 수가 짝수면 1(짝수 패리티)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 중에서도 중점적으로 살펴볼 것은 ZF,SF,CF,OF가 되겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;비교,분기 명령어들이 이를 참고하는 이유는 기본적으로 컴퓨터에서의 숫자 비교는 좌항에서 우항을 뺐을 때, 음수인지, 0인지, 양수인지에 따라 판단하기 때문입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;특히 CF 같은 경우는 왜 참고하는지 헷갈릴 수도 있는데, 예를 들자면 unsigned 연산에서 3과 5를 비교할 때, 3-5를 수행합니다. 그런데, unsigned 연산이므로 빌림(borrow)가 발생하기 때문에, CF가 1로 설정됩니다. 그럼 JB 같은 명령어들은 이 CF로 빌림이 발생했는지 안했는지 확인하고 숫자의 크기를 판단하는 것이죠.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2.4 함수 호출 규약(Calling Convention)&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Calling Convention 또한 컴퓨터 구조 시간에 배운 기억이 나는군요. 당시에 교수님께서 중요하게 다루시면서 시험 문제까지 나왔던 기억이 납니다. 다시 보니 감회가 새롭네요...&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;Calling Covention이란?&lt;/h4&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;함수 A(Caller)가 실행 도중에 함수 B(Callee)를 호출해야하는 상황을 가정해봅시다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;A는 자신이 작업 중이던 정보를 스택에 저장하고 자신이 사용하던 레지스터를 B가 사용할 수 있게 정리해주어야합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;물론 Caller는 자신이 복귀 했을 때, 계속 필요한 정보가 있고, 더 이상 필요없는 정보가 존재하게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 때&amp;nbsp; Caller가 복귀했을 때 필요한 정보를 저장할 책임이 누구에게 있냐에 따라 Caller-Saved, Callee-Saved로 나뉘게 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Caller-Saved는 Callee에게 주도권을 넘겨주기 전에, 자신이 복귀 후에 필요한 정보를 스택에 저장하고 주도권을 넘겨줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Callee-Saved는 Caller에게 주도권을 넘겨받고 레지스터에 값을 쓰기 전에, Caller가 필요한 정보를 스택에 보존해두었다가, 주도권을 반환할 때, 동일한 레지스터에 데이터를 복구하고 돌려줍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;시각적으로 표현하면 아래와 같이 표현할 수 있겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Caller-Saved&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biagzG/dJMcagfHZJe/Hki0szJkEFwmiVqCxeuvwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biagzG/dJMcagfHZJe/Hki0szJkEFwmiVqCxeuvwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biagzG/dJMcagfHZJe/Hki0szJkEFwmiVqCxeuvwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiagzG%2FdJMcagfHZJe%2FHki0szJkEFwmiVqCxeuvwK%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;950&quot; height=&quot;602&quot; data-origin-width=&quot;950&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Callee-Saved&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqfTS5/dJMcagGTHOB/SKb9wx0rqIXzgCavAILkZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqfTS5/dJMcagGTHOB/SKb9wx0rqIXzgCavAILkZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqfTS5/dJMcagGTHOB/SKb9wx0rqIXzgCavAILkZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqfTS5%2FdJMcagGTHOB%2FSKb9wx0rqIXzgCavAILkZk%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;1058&quot; height=&quot;1022&quot; data-origin-width=&quot;1058&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2.4.1 정수/포인터 인자를 Callee에게 넘기기 위해 저장하는 순서&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;main 함수 내부에서 foo라는 함수를 호출한다고 가정해봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1788264432856&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;foo(1,2,3)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;위와 같은 형태로 인자를 넘기려고 합니다. Caller(main)과 Callee(foo)는 서로 어떤 레지스터에 몇번째 인자를 저장할 것인지 합의를 봐야합니다. 그래야 Callee가 Caller가 의도한대로 인자를 받아들이겠죠. 그것이 아래 표입니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;순서&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;레지스터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;RDI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;DSI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;RDX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;RCX&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;R8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;R9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;7~&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;Caller의 스택에 저장&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;마찬가지로 부동 소수점 인자를 넘기는 방법 또한 아래와 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;XXX은 128비트 크기의 레지스터이며, 부동 소수점 연산에 사용됩니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;6&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;8&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;XMM7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;스택에 저장&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;또한 함수 호출이 끝나고 반환값은 RAX에 저장되게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;함수 호출 규약이란 정확하게 Caller-Saved,Callee-Saved를 포함해 더 많은 규약을 포괄하지만, 일단은 Caller/Callee-Saved만 알아둡시다. 이 포스트에서는 편하게 호출 규약 = Caller/Callee-Saved로 표현하겠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;x86은 레지스터의 종류에 따라 적용되는 호출 규약이 다릅니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;Callee-Saved&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;Caller-Saved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;RBX,RBP,R12~R15&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;RAX,RCX,RDX,RSI,RDI,R8~R11&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 이렇게 리버싱에서 자주 등장하는 x86-64 아키텍처의 기본 지식들을 알아보았습니다. 사실 어셈블리 명령어도 같이 정리했는데, 분량이 너무 길어져서 다음에 작성하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;제가 아키텍처를 공부하면서 느낀건 이렇게 정리한 내용만으로는 한번에 머리에 들어오지 않는다는 것입니다. 이 글을 읽고 계신 여러분 중 누군가도 이 시점에는 앞 내용이 잘 기억나지 않으시겠죠? 이 내용을 두번 정리한 저도 마찬가지 입니다 하하..&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그렇지만, 리버싱 도중 마주했을 때, 대략적인 정체를 기억해낼 수 있고, 다시 찾아봤을 때, 기억해낼 정도면 충분하다고 생각합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이후에는 리버싱을 반복하다보면 외우기 싫어도 외워지겠죠. 아무튼 여러분도 리버싱 공부 화이팅 하시길 바랍니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;긴 글 읽어주셔서 감사합니다.&lt;/p&gt;</description>
      <category>개념 정리/리버싱</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/7</guid>
      <comments>https://commanderjjm.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 1 Sep 2026 21:40:32 +0900</pubDate>
    </item>
    <item>
      <title>[pwnable] GDB 기초 사용법</title>
      <link>https://commanderjjm.tistory.com/6</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GDB란 무엇인가?&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: Noto Serif KR;&quot;&gt;GDB(GNU debugger)는 리눅스에서 사용되는 표준 디버거이며, GNU 프로젝트에서 제작된 소프트웨어 시스템을 위한 표준 디버거이다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;자유소프트웨어를 만들고 보급하기 위한 GNU에서 제작된 다양한 소프트웨어들이 연결된 구조에서 사용되는 디버거라고 합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;리버싱 과정에서 동적 분석이 필요할 때 많이 사용됩니다. 프로그램을 조금씩 실행시키면서 레지스터 값의 변화를 추적하는 데 용이하기 때문이죠.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GDB 명령어를 알아보자&lt;/h2&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;1. file(example)&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;example 파일을 디버깅 대상으로 지정하는 명령어입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E2PgB/dJMcaf8Lpsg/UkKbSJMN5tQvoL75WBIL80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E2PgB/dJMcaf8Lpsg/UkKbSJMN5tQvoL75WBIL80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E2PgB/dJMcaf8Lpsg/UkKbSJMN5tQvoL75WBIL80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE2PgB%2FdJMcaf8Lpsg%2FUkKbSJMN5tQvoL75WBIL80%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;1122&quot; height=&quot;200&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;gdb에 진입한 이후 file 명령어로 relativity를 지정한 모습입니다. 그러나 gdb 진입 전에 gdb ./relativity를 입력하면 gdb에 진입함과 동시에 디버깅 대상으로 지정하므로 file 명령어를 잘 쓸 일은 없을 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;참고로 리눅스 자체 명령어인 file과 헷갈리지 않도록 합시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/30xNb/dJMcafHRVXH/BUb25PWlXJg2X4ZZ9rc6t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/30xNb/dJMcafHRVXH/BUb25PWlXJg2X4ZZ9rc6t1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/30xNb/dJMcafHRVXH/BUb25PWlXJg2X4ZZ9rc6t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F30xNb%2FdJMcafHRVXH%2FBUb25PWlXJg2X4ZZ9rc6t1%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;1064&quot; height=&quot;232&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;file 명령어를 통해 해당 파일의 정보를 볼 수 있습니다. 일반적으로 확인할 것은 x86-64와 stripped입니다. x86-64는 해당 프로그램이 x86 아키텍처로 만들어진 바이너리라는 뜻이고, stripped는 ELF에 심볼 테이블이 존재하지 않는다고 보시면 되겠습니다. ELF와 심볼 등에 관한 내용은 포스트 마지막에 정리하겠습니다.&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;2. run &amp;lt;프로그램 인자&amp;gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vJsaI/dJMcahlouS9/4Inscg1CkfHwIGcP6pdta0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vJsaI/dJMcahlouS9/4Inscg1CkfHwIGcP6pdta0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vJsaI/dJMcahlouS9/4Inscg1CkfHwIGcP6pdta0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvJsaI%2FdJMcahlouS9%2F4Inscg1CkfHwIGcP6pdta0%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;1012&quot; height=&quot;304&quot; data-origin-width=&quot;1012&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프로그램을 실행하는 명령어입니다. 이미지는 debugee라는 파일을 실행하는 과정입니다. 이 명령어 또한 이미 디버깅 대상으로 지정한 파일에 대해서는 run만 입력해도 됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;3. info file&lt;/h3&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;현재 로드된 바이너리의 섹션 정보를 보여주는 명령어입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eESyaC/dJMcagNyTg8/pioIfHJvW5VOEtkqGetDnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eESyaC/dJMcagNyTg8/pioIfHJvW5VOEtkqGetDnk/img.png&quot; data-alt=&quot;info file을 통해 다양한 정보를 확인할 수 있습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eESyaC/dJMcagNyTg8/pioIfHJvW5VOEtkqGetDnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeESyaC%2FdJMcagNyTg8%2FpioIfHJvW5VOEtkqGetDnk%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;1034&quot; height=&quot;690&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;info file을 통해 다양한 정보를 확인할 수 있습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대상 바이너리 파일의 경로&lt;/li&gt;
&lt;li&gt;파일에 적용된 아키텍처의 종류&lt;/li&gt;
&lt;li&gt;엔트리 포인트&lt;/li&gt;
&lt;li&gt;각 섹션의 메모리 주소 범위&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 프로그램을 시작하는 과정은 다음과 같습니다.&lt;/p&gt;
&lt;div id=&quot;code_1788146421801&quot; data-ke-type=&quot;html&quot; data-source=&quot;프로그램 실행
    &amp;darr;
Entry Point (_start)
    &amp;darr;
C Runtime 초기화
    &amp;darr;
__libc_start_main
    &amp;darr;
main()
    &amp;darr;
프로그램 코드&quot;&gt;프로그램 실행 &amp;darr; Entry Point (_start) &amp;darr; C Runtime 초기화 &amp;darr; __libc_start_main &amp;darr; main() &amp;darr; 프로그램 코드&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;main에 브레이크 포인트를 걸게되면, 사전 작업을 건너뛰고 바로 main에 멈추게되지만, 엔트리 포인트에 브레이크 포인트를 걸면 위와 같은 과정을 시작하기 직전에 멈추게 됩니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;4. break&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;특정 주소에 중단점을 설정하는 명령어입니다. 이후 프로그램을 실행하면 지정한 포인트에서 멈추게됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UwpGF/dJMcagmqLa9/y7PN9GNgG4RKJRDr4tJKq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UwpGF/dJMcagmqLa9/y7PN9GNgG4RKJRDr4tJKq1/img.png&quot; data-alt=&quot;EP(Entry Point)에 브레이크 포인트를 설정한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UwpGF/dJMcagmqLa9/y7PN9GNgG4RKJRDr4tJKq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUwpGF%2FdJMcagmqLa9%2Fy7PN9GNgG4RKJRDr4tJKq1%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;544&quot; height=&quot;264&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;EP(Entry Point)에 브레이크 포인트를 설정한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;레지스터의 변화를 관찰하고 싶은 부분의 시작점에 break point를 걸어주고 continue, ni 등의 명령어로 자세하게 변화를 관찰할 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;5. continue&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다음 브레이크 포인트나 프로그램 종료까지 중단된 프로그램을 계속 실행시킵니다. 만약 멈춰야할 어떤 이유가 있다면 그 지점에서 다시 멈추게됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OHfXc/dJMcagUkIEk/FKq6Bpg3cwhxeISXvi2jq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OHfXc/dJMcagUkIEk/FKq6Bpg3cwhxeISXvi2jq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OHfXc/dJMcagUkIEk/FKq6Bpg3cwhxeISXvi2jq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOHfXc%2FdJMcagUkIEk%2FFKq6Bpg3cwhxeISXvi2jq0%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;978&quot; height=&quot;162&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;여러 BP(Break Point)를 건너뛰고 싶을 때는 continue/c &amp;lt;숫자&amp;gt;를 이용해 여러번 건너뛸 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;992&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dduhoN/dJMcagND3hv/uKZttaCzwPboZu7hhymZxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dduhoN/dJMcagND3hv/uKZttaCzwPboZu7hhymZxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dduhoN/dJMcagND3hv/uKZttaCzwPboZu7hhymZxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdduhoN%2FdJMcagND3hv%2FuKZttaCzwPboZu7hhymZxk%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;1426&quot; height=&quot;992&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;992&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;bp를 설정한 후 run을 실행한 화면입니다. 여기서 레지스터들의 상태, 실행 중인 어셈블리 명령어와 그 주변 명령어들을 확인할 수 있습니다. 이를 통해 레지스터의 값을 수정하거나 프로세스의 정보를 얻어낼 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;6. entry&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;RIP 레지스터에 EP를 설정하는 명령어입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;RIP 레지스터란 x86 아키텍처의 레지스터로, CPU가 다음으로 실행할 명령어인 PC가 저장되는 레지스터입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;entry 명령어는 RIP에 EP가 들어올 때까지 프로그램을 실행시키는 명령어입니다. 이후 RIP에 EP가 들어오면 멈춥니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K0dUq/dJMcafVs0l6/KqKGy6rE9PsQCqU4ZNR8L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K0dUq/dJMcafVs0l6/KqKGy6rE9PsQCqU4ZNR8L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K0dUq/dJMcafVs0l6/KqKGy6rE9PsQCqU4ZNR8L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK0dUq%2FdJMcafVs0l6%2FKqKGy6rE9PsQCqU4ZNR8L1%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;1430&quot; height=&quot;580&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;만약 프로그램 실행 도중에 entry를 실행하면, 현재 실행 상태를 모두 버리고 처음으로 돌아가 EP에 멈추는 메커니즘입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;7. start&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;main의 시작점에 임시 bp를 걸고 프로그램을 실행하여 임시 bp에서 프로그램을 멈춥니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;참고로 바이너리가 stripped 상태여서 심볼 정보가 존재하지 않는다면 main을 찾을 수 없기 때문에, 이 경우에는 entry와 동일하게 동작합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;1150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxf8YW/dJMcagfGBO4/D9jXGmAKeRWRPkxcPxP4v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxf8YW/dJMcagfGBO4/D9jXGmAKeRWRPkxcPxP4v1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxf8YW/dJMcagfGBO4/D9jXGmAKeRWRPkxcPxP4v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxf8YW%2FdJMcagfGBO4%2FD9jXGmAKeRWRPkxcPxP4v1%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;1416&quot; height=&quot;1150&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;1150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;stripped 바이너리에서 start를 실행한 모습입니다. 정상적으로 작동한 모습을 볼 수 있는데 왜 그럴까요?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이는 GDB가 __libc_start_main의 호출 규약을 따르기 때문입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;__libc_start_main은 앞서 언급한 프로그램 시작 과정에 실행되는 함수입니다. 이 함수는 ELF의 dysym이라는 섹션에 저장되는 동적 심볼이기 때문에, strip되어도 남아있게 되는데, 이 함수의 첫번째 인자가 main의 주소입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 내부적으로 __libc_start_main에 bp를 걸고 run하여 멈춘 시점의 첫번째 인자(RDI)의 값을 확인하여 main의 주소를 유추해내도록 작동하게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;8. 명령어를 분석할 때 사용하는 명령어&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUKqHc/dJMcagmqSE0/SEbTKouVAfTqGTik9YSpI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUKqHc/dJMcagmqSE0/SEbTKouVAfTqGTik9YSpI1/img.png&quot; data-alt=&quot;printf에 bp를 설정한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUKqHc/dJMcagmqSE0/SEbTKouVAfTqGTik9YSpI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUKqHc%2FdJMcagmqSE0%2FSEbTKouVAfTqGTik9YSpI1%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;1436&quot; height=&quot;730&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;printf에 bp를 설정한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1. ni(next instruction): 함수 호출(call)을 만났을 때, 해당 함수 전체를 실행하고 다음 줄로 넘어갑니다.(=step over) 함수 내부의 동작을 살펴볼 때는 적절하지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn49zZ/dJMcahyVFrD/pqmOoNk95DHJrIPfwi11ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn49zZ/dJMcahyVFrD/pqmOoNk95DHJrIPfwi11ik/img.png&quot; data-alt=&quot;ni를 실행하여 printf 다음 명령어인 0x5555555573b3으로 이동한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn49zZ/dJMcahyVFrD/pqmOoNk95DHJrIPfwi11ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn49zZ%2FdJMcahyVFrD%2FpqmOoNk95DHJrIPfwi11ik%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;1418&quot; height=&quot;800&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ni를 실행하여 printf 다음 명령어인 0x5555555573b3으로 이동한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2. si(step instruction): call을 만났을 때, 함수 안으로 들어갑니다(step in) 함수 내부의 동작을 살펴볼 때 적절합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDGmn5/dJMcaamaic7/4OeTE2uQhMkkFiZbf7bJK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDGmn5/dJMcaamaic7/4OeTE2uQhMkkFiZbf7bJK0/img.png&quot; data-alt=&quot;si를 통해 printf 내부로 진입한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDGmn5/dJMcaamaic7/4OeTE2uQhMkkFiZbf7bJK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDGmn5%2FdJMcaamaic7%2F4OeTE2uQhMkkFiZbf7bJK0%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;1422&quot; height=&quot;548&quot; data-origin-width=&quot;1422&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;si를 통해 printf 내부로 진입한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;3. finish: 함수의 끝까지 한번에 실행하는 명령어입니다. si를 통해 함수 내부를 살펴보다가 더 이상 살펴볼 필요가 없다고 판단되면, finish로 함수를 끝낼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;758&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0nvPc/dJMcaa7I5bh/6obqnZbW7T7f7QNbDnUdT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0nvPc/dJMcaa7I5bh/6obqnZbW7T7f7QNbDnUdT0/img.png&quot; data-alt=&quot;finish를 통해 printf를 끝내고 다음 명령어로 넘어간 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0nvPc/dJMcaa7I5bh/6obqnZbW7T7f7QNbDnUdT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0nvPc%2FdJMcaa7I5bh%2F6obqnZbW7T7f7QNbDnUdT0%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;1418&quot; height=&quot;758&quot; data-origin-width=&quot;1418&quot; data-origin-height=&quot;758&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;finish를 통해 printf를 끝내고 다음 명령어로 넘어간 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;참고로 PIE 바이너리를 IDA와 gdb를 모두 사용하여 정적/동적 분석을 동시에 수행하는 경우, IDA의 주소를 기반으로 gdb에서 bp를 걸려고 한다면, 제대로 걸리지 않습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이유는 ASLR이 런타임에 베이스 주소를 랜덤으로 재배치하는데, IDA는 ELF에 저장된 0x0 베이스 주소를 기반의 오프셋으로 보여주기 때문입니다. 그리하여 gdb에서 IDA의 오프셋을 활용하려면 ASLR이 배치한 베이스 주소에 IDA 오프셋을 더해주어야합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;9. info registers(i r)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;축약형 i r로 사용할 수 있습니다. 실행 중 현 시점의 모든 범용 레지스터의 값을 한번에 보여주는 명령어입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4c6hR/dJMcagGShTl/7Dm0LTwFdP4SFitLS81L5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4c6hR/dJMcagGShTl/7Dm0LTwFdP4SFitLS81L5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4c6hR/dJMcagGShTl/7Dm0LTwFdP4SFitLS81L5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4c6hR%2FdJMcagGShTl%2F7Dm0LTwFdP4SFitLS81L5k%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;1198&quot; height=&quot;1142&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;1142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;10. b *$(레지스터 명)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;레지스터 내부의 값을 주소로 해석하여 그 주소에 bp를 거는 명령어입니다.&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;660&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/behzzH/dJMcacLfeoG/qfC4Z4wcwuGZ9XUyh15Y0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/behzzH/dJMcacLfeoG/qfC4Z4wcwuGZ9XUyh15Y0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/behzzH/dJMcacLfeoG/qfC4Z4wcwuGZ9XUyh15Y0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbehzzH%2FdJMcacLfeoG%2FqfC4Z4wcwuGZ9XUyh15Y0K%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;660&quot; height=&quot;162&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;11. bp 관련 명령어들&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1. info break points: 현재 걸려있는 모든 bp의 정보를 알려주는 명령어입니다. 참고로 bp의 번호는 순서대로 매겨지며, 앞 번호의 bp를 지워도 bp 번호가 갱신되지는 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CAL0Y/dJMcaiq099j/evkSIuBhFunYkkEki1bGp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CAL0Y/dJMcaiq099j/evkSIuBhFunYkkEki1bGp1/img.png&quot; data-alt=&quot;1,2,4번 bp를 제거해도 1,2로 갱신되지 않습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CAL0Y/dJMcaiq099j/evkSIuBhFunYkkEki1bGp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCAL0Y%2FdJMcaiq099j%2FevkSIuBhFunYkkEki1bGp1%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;1200&quot; height=&quot;252&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1,2,4번 bp를 제거해도 1,2로 갱신되지 않습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2. disable(bp 번호): bp를 제거하지 않고 일시적으로 비활성화하는 명령어입니다. enable로 다시 활성화 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lwWWM/dJMcadJYfys/zztZa2GmJMlAVBXFD40Vf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lwWWM/dJMcadJYfys/zztZa2GmJMlAVBXFD40Vf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lwWWM/dJMcadJYfys/zztZa2GmJMlAVBXFD40Vf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlwWWM%2FdJMcadJYfys%2FzztZa2GmJMlAVBXFD40Vf1%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;1210&quot; height=&quot;250&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;enb 항목을 보면 3번 bp가 n으로 표기되어 비활성화 됐음을 알 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;3. delete(bp 번호): bp를 영구적으로 삭제합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddE9Ei/dJMcacqVAwK/vjp5VsXkf3XrsZdv7e7C41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddE9Ei/dJMcacqVAwK/vjp5VsXkf3XrsZdv7e7C41/img.png&quot; data-alt=&quot;3번 bp를 삭제한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddE9Ei/dJMcacqVAwK/vjp5VsXkf3XrsZdv7e7C41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddE9Ei%2FdJMcacqVAwK%2Fvjp5VsXkf3XrsZdv7e7C41%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;220&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;3번 bp를 삭제한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;12. disassemble&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;함수 전체 또는 특정 주소 범위의 기계어를 어셈블리 코드로 변환해서 보여주는 명령어입니다. 축약형은 disas입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8laD4/dJMcahFDEsv/DajkXiuGuvSEqm8G3vStF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8laD4/dJMcahFDEsv/DajkXiuGuvSEqm8G3vStF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8laD4/dJMcahFDEsv/DajkXiuGuvSEqm8G3vStF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8laD4%2FdJMcahFDEsv%2FDajkXiuGuvSEqm8G3vStF0%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;1200&quot; height=&quot;228&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;u/nearpc/pdisas: 현재 위치 주변의 몇 줄만 보여주는 명령어입니다. 또는 주소를 인자로 넘겨주면 해당 주소 주변의 몇 줄을 디스어셈블하여 보여줍니다. 다른 작업 중에 특정 주소 영역을 확인하고 싶을 때 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;13. x(examine)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;특정 메모리 주소의 내용을 원하는 형식으로 출력하는 명령어입니다.&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;포맷 종류&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;크기 종류&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;x -&amp;gt; 16 진수&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;b -&amp;gt; 1byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;d -&amp;gt; 10진수&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;h -&amp;gt; 2byte(half word)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;s -&amp;gt; 문자열&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;w -&amp;gt; 4byte(word)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;i -&amp;gt; 명령어(디스어셈블)&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;g -&amp;gt; 8byte(giant)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;c -&amp;gt; 문자(char)&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;t -&amp;gt; 2진수&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;f -&amp;gt; float&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;o -&amp;gt; 8진수&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;a -&amp;gt; 주소&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;기본 형식은 x/[개수][포맷][크기]입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTlpjl/dJMcagGSjY5/nNrSf1vMKKRWlMhdb1nwI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTlpjl/dJMcagGSjY5/nNrSf1vMKKRWlMhdb1nwI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTlpjl/dJMcagGSjY5/nNrSf1vMKKRWlMhdb1nwI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTlpjl%2FdJMcagGSjY5%2FnNrSf1vMKKRWlMhdb1nwI1%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;1220&quot; height=&quot;198&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;rsp 레지스터의 주소로부터 8 * 5 = 40바이트를 16진수로 8바이트씩 보여주는 모습입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNs1Np/dJMcacROSGr/jw5HK0QczFAMUkMFcCCrdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNs1Np/dJMcacROSGr/jw5HK0QczFAMUkMFcCCrdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNs1Np/dJMcacROSGr/jw5HK0QczFAMUkMFcCCrdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNs1Np%2FdJMcacROSGr%2Fjw5HK0QczFAMUkMFcCCrdK%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;1186&quot; height=&quot;776&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;두 케이스는 각각 rsp의 주소부터 문자열 10개를 출력, 5개의 어셈블리 코드를 출력하는 명령어입니다. 문자열이나 명령어와 같이 가변적인 포맷들은 크기 지정자가 무시됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;14. telescope&amp;lt;주소&amp;gt;[개수]&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;tele로 축약할 수 있습니다. 이 명령어는 지정한 주소에서 지정한 개수만큼의 메모리 값을 보여주고, 값이 포인터면 자동으로 따라가서 최종값까지 체인으로 보여주는 명령어입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O7mZc/dJMcacEt1n7/HF2B8ALGlSYDGUoKYrfB5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O7mZc/dJMcacEt1n7/HF2B8ALGlSYDGUoKYrfB5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O7mZc/dJMcacEt1n7/HF2B8ALGlSYDGUoKYrfB5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO7mZc%2FdJMcacEt1n7%2FHF2B8ALGlSYDGUoKYrfB5K%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;1206&quot; height=&quot;848&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;화살표(-&amp;gt;)가 존재하는 값들은 포인터 값으로, 해당 포인터가 가르키는 값을 체인으로 보여주는 모습입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Q. 어떻게 포인터인지 구분할까요?&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;A. 실제 주소로 존재하는 값으로, 접근이 가능하며 포인터로 판단하고, 접근이 불가능하다면 일반 정수로 판단합니다. 그래서 간혹 정수로 판단해야하는데, 포인터로 해석되어 잘못 표현될 때도 있다고 합니다. 개인적으로 포인터 체인 값이 이상하게 나온다면 의심해볼만 한 것 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;15. bt(k)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;backtrace의 약자로, 현재 시점까지의 함수 호출 스택(call stack)을 보여주는 명령어입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;call stack이란 함수가 호출된 순서를 스택으로 쌓아놓은 자료구조 입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;bt를 사용하면 낯선 주소에서 멈췄을 때, 어떤 흐름으로 호출됐는지 판단할 때, 특정 함수에 전달된 인자에 문제가 발생해서 버그가 유발됐다면, 이 인자가 어떤 함수로부터 왔는지 확인할 때 유용하게 사용됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqowwj/dJMcaaGEP2L/esdypqjakyrwmxmZp6jPq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqowwj/dJMcaaGEP2L/esdypqjakyrwmxmZp6jPq0/img.png&quot; data-alt=&quot;main 함수 내부의 특정 함수에 bp를 걸고 bt를 한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqowwj/dJMcaaGEP2L/esdypqjakyrwmxmZp6jPq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdqowwj%2FdJMcaaGEP2L%2FesdypqjakyrwmxmZp6jPq0%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;1196&quot; height=&quot;408&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;main 함수 내부의 특정 함수에 bp를 걸고 bt를 한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;스택 자료구조이므로 아래에서 위로 읽으면 함수가 호출된 순서입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;16.f(프레임 숫자)&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;콜 스택의 특정 프레임으로 이동해서 해당 시점의 컨텍스트를 볼 수 있는 명령어입니다. 인자를 넘기지 않으면 현재 어느 프레임에 있는지를 보여줍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpafcp/dJMcablfvwV/iOR9JVX87skCYUCYCulLV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpafcp/dJMcablfvwV/iOR9JVX87skCYUCYCulLV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpafcp/dJMcablfvwV/iOR9JVX87skCYUCYCulLV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpafcp%2FdJMcablfvwV%2FiOR9JVX87skCYUCYCulLV1%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;1204&quot; height=&quot;354&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2번 프레임의 함수 실행 시점의 레지스터, 로컬 변수, 소스 위치 등을 확인할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;단, 해당 시점의 값만 확인하는 것이기 때문에, 실행 위치까지 2번 프레임으로 바뀌는 것이 아닙니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;telescope와 조합하여 사용하면, 문제가 발생한 함수 부근에서 구체적인 값들을 확인할 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;17. 추가적인 명령어들&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1. dump memory[파일명][시작주소][끝주소]: 특정 메모리 범위의 내용을 저장합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;2.vmmap: 현재 실행 중인 프로세스의 셋녀들이 가상 메모리에 어떤 위치에 어떤 권한으로 매핑되어있는지를 보여주는 명령어입니다.&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;1172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k0GGO/dJMcaamanWl/cGKX9EsWO48SnUKaBT0kEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k0GGO/dJMcaamanWl/cGKX9EsWO48SnUKaBT0kEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k0GGO/dJMcaamanWl/cGKX9EsWO48SnUKaBT0kEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk0GGO%2FdJMcaamanWl%2FcGKX9EsWO48SnUKaBT0kEK%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;1172&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;1172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;vmmap을 이용하여 데이터 영역의 주소 범위를 계산하여 데이터 영역을 파일로 저장한 모습입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;3. context(ctx): 주요 메모리들의 상태를 가독성 있는 인터페이스로 보여줍니다. 프로그램이 실행되다가 bp에 도달하면 자동으로 실행되며, 별도 실행 또한 가능합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;1222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RkQYi/dJMcacxCmf6/fsZ42GgivEF7NmPFeKZuY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RkQYi/dJMcacxCmf6/fsZ42GgivEF7NmPFeKZuY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RkQYi/dJMcacxCmf6/fsZ42GgivEF7NmPFeKZuY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRkQYi%2FdJMcacxCmf6%2FfsZ42GgivEF7NmPFeKZuY1%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;1064&quot; height=&quot;1222&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;1222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;context 실행 시 보여지는 4 개의 영역입니다&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;REGISTERS&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;레지스터의 상태 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;DISASM&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;rip부터 여러 줄에 걸쳐 디스어셈블된 결과 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;STACK&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;rsp로부터 여러 줄에 걸쳐 스택 값을 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;BACKTRACE&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;현재 rip에 도달할 때까지 어떤 함수들이 중첩되어 호출되었는지 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;4. set&amp;lt;주소/레지스터&amp;gt; = &amp;lt;변경할 값&amp;gt;: 특정 주소나 레지스터의 값을 원하는 값으로 변경하는 명령어입니다. 값을 조작하여 결과를 관찰할 때 유용합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;추가적인 몇 가지 팁과 정보&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;일단 저는 M1 Mac 환경에서 실습 중입니다. 많이 경험해보진 않았지만, 제가 겪은 드림핵 리버싱 문제들은 모두 stripped 바이너리였어요. 그리고 gdb를 처음 실행하고 나면, 매 명령어 실행마다 디버깅 심볼 다운로드 실행을 실행하기 때문에 실습에 큰 지장이 가는 문제가 있었습니다. 그래서 저는 디버깅 심볼 다운로드를 하지 않도록 하는 명령어를 입력하고 리버싱을 시작합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uk35F/dJMcagfGOcH/Q3p39281YFAySzrdwh3qN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uk35F/dJMcagfGOcH/Q3p39281YFAySzrdwh3qN0/img.png&quot; data-alt=&quot;이 명령어를 입력하고나면 디버깅 심볼을 다운로드 하지 않습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uk35F/dJMcagfGOcH/Q3p39281YFAySzrdwh3qN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuk35F%2FdJMcagfGOcH%2FQ3p39281YFAySzrdwh3qN0%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;686&quot; height=&quot;130&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이 명령어를 입력하고나면 디버깅 심볼을 다운로드 하지 않습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;디버깅 심볼에 대해서 알아보며 알게된 ELF 관련 정보입니다. 먼저 ELF란 OS의 로더와 링커가 읽고 해석할 수 있도록, 바이너리 파일을 구조화하는 포맷입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;간략하게 표현하자면 ELF의 구조는 아래와 같습니다.&lt;/p&gt;
&lt;div id=&quot;code_1788153917294&quot; data-ke-type=&quot;html&quot; data-source=&quot;ELF
|
|-----심볼 테이블
|          |
|          |_____main, 함수 이름 정보 등
|
|
|______디버깅 정보
     |_____ 소스 파일, 줄 번호, 변수 정보 등&quot;&gt;ELF | |-----심볼 테이블 | | | |_____main, 함수 이름 정보 등 | | |______디버깅 정보 |_____ 소스 파일, 줄 번호, 변수 정보 등&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;stripped 바이너리는 심볼 테이블에 .symtab 세션이 제거된 바이너리 입니다. 해당 세션에 사용자 정의 함수명이 존재하기 때문에 stripped 바이너리에서 b main이 통하지 않게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아래는 ELF 바이너리의 주요 섹션입니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.text&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;실제 실행되는 기계어 코드가 존재하는 섹션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.init/fini&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;프로그램의 시작과 끝에 실행되는 초기화 및 정리 코드가 존재하는 섹션&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.data&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;초기값이 있는 정적/전역 변수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.bss&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;초기값이 없거나 0으로 초기화된 정적/전역 변수 -&amp;gt; 파일에는 크기 정보만 존재하고 실제 데이터는 없어서 바이너리 크기를 줄여줌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.rodata&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;읽기 전용 데이터, 문자열 리터럴이나 const 상수가 저장됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.plt/.got&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;외부 라이브러리 함수를 호출할 때, 사용하는 동적 링킹 테이블&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.dynsym/.dynstr&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;동적 심볼 이름과 문자열 정보&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.interp&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;동적 링커의 경로를 지정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.symtab/.strtab&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;심볼 테이블과 문자열 테이블. stripped되면 이 섹션이 제거됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;.debug&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;디버그 정보&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;리버싱을 할 때 주로 .text /.data/.rodata, .plt/.got 등을 참고하게됩니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;몇 주전에 정리한 내용인데, 어쩌다보니 이제 글을 작성하게 되었네요.. 스압이 좀 있지만, 끝까지 읽어주셔서 감사합니다! 개강하고 나면 더 열심히 달려보겠습니다.&lt;/p&gt;</description>
      <category>개념 정리/리버싱</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/6</guid>
      <comments>https://commanderjjm.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 31 Aug 2026 14:35:53 +0900</pubDate>
    </item>
    <item>
      <title>theori of relativity</title>
      <link>https://commanderjjm.tistory.com/5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 오늘은 theori of relativity 문제를 리뷰해보도록 하겠습니다. 왜 갑자기 격식체를 쓰느냐? 그냥 뭔가 그래야할 것 같아서요.. 앞으로는 격식체로 글을 작성해보겠습니다.&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;시작하기 앞서, 정답은 적어놓지 않겠습니다. 제 추론 과정을 토대로 문제 접근 방식을 리뷰할 예정이니, 참고만 해주시면 감사하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 일단, 어셈블리부터 살펴보기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBbpiB/dJMcag7xl87/f9hRYK5wL0uBYiqclhLKKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBbpiB/dJMcag7xl87/f9hRYK5wL0uBYiqclhLKKK/img.png&quot; data-alt=&quot;아무래도 리버싱을 하다보면, 매일 마주치는게 어셈블리 코드인데, 용어나 문법 구조들은 한번 정리해야할 것 같습니다. 조만간 정리해서 한편 작성해보겠습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBbpiB/dJMcag7xl87/f9hRYK5wL0uBYiqclhLKKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBbpiB%2FdJMcag7xl87%2Ff9hRYK5wL0uBYiqclhLKKK%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;2226&quot; height=&quot;410&quot; data-origin-width=&quot;2226&quot; data-origin-height=&quot;410&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아무래도 리버싱을 하다보면, 매일 마주치는게 어셈블리 코드인데, 용어나 문법 구조들은 한번 정리해야할 것 같습니다. 조만간 정리해서 한편 작성해보겠습니다.&lt;/figcaption&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;h2 data-ke-size=&quot;size26&quot;&gt;2. main을 디컴파일 해보자&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;596&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxK41S/dJMcabkYyGY/mOg7wMH0jYCU8vVKC25Yvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxK41S/dJMcabkYyGY/mOg7wMH0jYCU8vVKC25Yvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxK41S/dJMcabkYyGY/mOg7wMH0jYCU8vVKC25Yvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxK41S%2FdJMcabkYyGY%2FmOg7wMH0jYCU8vVKC25Yvk%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;1592&quot; height=&quot;596&quot; data-origin-width=&quot;1592&quot; data-origin-height=&quot;596&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fgets의 구조를 살펴봤는데, 딱히 얻어낼건 없었습니다. 그리고 라이브러리 함수 같아서 넘겼어요(C 표준 라이브러리 함수라고 합니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if문을 살펴보니 s와 배열 a1을 인자로 주고 sub_3298의 리턴 값에 따라 다른 문구가 출력되는 것 같군요. s가 플래그의 핵심인걸까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. sub_3298()을 살펴보자&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CZy7j/dJMcaaTOTzP/rBZUtcvhGvysUpvK94ChV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CZy7j/dJMcaaTOTzP/rBZUtcvhGvysUpvK94ChV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CZy7j/dJMcaaTOTzP/rBZUtcvhGvysUpvK94ChV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCZy7j%2FdJMcaaTOTzP%2FrBZUtcvhGvysUpvK94ChV0%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;552&quot; height=&quot;435&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 작성되는 for문과는 조금 다른 구조를 하고 있었습니다. 이 for문은 탈출조건이 특이하게 생겼습니다. __popcnt(v5) == 0을 만족해야 탈출할 수 있습니다. __popcnt(a)는 a의 이진수 비트에서 1의 개수를 세어주는 시스템 함수라고 하네요. 그럼 for문을 탈출하려면 v5가 0이 되어야 탈출할 수 있다는걸까요? 이번에는 sub_3298의 인자로 들어올 a1을 살펴봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4.&amp;nbsp; byte_6020&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;986&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7yCNm/dJMcaa7rtTM/kul78aBRPhIvfXR1M5Qaa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7yCNm/dJMcaa7rtTM/kul78aBRPhIvfXR1M5Qaa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7yCNm/dJMcaa7rtTM/kul78aBRPhIvfXR1M5Qaa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7yCNm%2FdJMcaa7rtTM%2Fkul78aBRPhIvfXR1M5Qaa1%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;673&quot; height=&quot;417&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;986&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 byte_6020의 값이 0x77h 하나라고 생각했습니다. 그런데 아래 나열된 값들도 관련이 있어보여서 AI한테 물어보니 시작점부터 다른 심볼이 나오기 직전까지가 6020이 선언된 범위라고 설명해줬습니다. 그렇다면 6020이 가진 값들이 좀 많네요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. gdb를 이용해 동적 분석으로 접근해보자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDA로 살펴보니 정보량이 너무 많아 어지러웠습니다. 그래서 gdb로 sub_3298을 실행해서 s값을 알아내보겠습니다. sub_3298에 브레이크 포인트를 걸어보려고 했는데, AI에게 조언을 받았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4kcuB/dJMcaiRS03N/f6kOn4vkiUuBMHbhMPDO10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4kcuB/dJMcaiRS03N/f6kOn4vkiUuBMHbhMPDO10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4kcuB/dJMcaiRS03N/f6kOn4vkiUuBMHbhMPDO10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4kcuB%2FdJMcaiRS03N%2Ff6kOn4vkiUuBMHbhMPDO10%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;1446&quot; height=&quot;112&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PIE 바이너리일 수 있어서 베이스 주소를 찾고 브레이크 포인트를 걸어야한다고 합니다. 그럼 PIE가 뭘까요?&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: Noto Serif KR;&quot;&gt;PIE(Position Independant Executable)이란 메모리 어디에 로드되든 정상 동작하도록 컴파일된 실행 파일이다. &lt;br /&gt;이는 코드 내부의 주소가 전부 베이스 주소로부터의 오프셋으로 표현되어있어서 베이스 주소만 결정된다면 나머지는 오프셋에 의해 자동으로 결정된다&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약간 OS의&amp;nbsp; 메모리 적재 위치에 구애받지 않고 실행 시킬 수 있도록하는 실행 시간 바인딩과 유사해보입니다. PIE는 컴파일러가 내부 코드를 베이스 주소를 기준으로한 상대 주소로 컴파일 해주는 듯 합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;베이스 주소가 매번 바뀌는 이유는 ASLR(Address Space Layout Randomization) 때문이라고 하는데,이는 OS가 프로그램을 시작할 때마다 의도적으로 로드 주소를 랜덤하게 배치한다고 합니다. 이 과정은 전부 프로세스의 가상 메모리에서 적용되는 것이라 페이징 기법과는 다른 계층의 이야기라고 하네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 ASLR가 없다면 공격자가 고정된 시작 주소를 기준으로 원하는 주소로 점프하는 익스플로잇 등을 작성할 수 있기 때문에, 보안 차원에서 적용하는 기법이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 sub_3298에 어떻게 브레이크 포인트를 걸어야할까요?&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1786257628099&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;b main
run
info proc mapping&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 명령어는 현재 실행 중인 프로세스의 메모리 매핑 상태를 보여주는 명령어 입니다. 위 순서대로 명령어를 적용하면 아래와 같이 출력됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MiLka/dJMcaixBoCW/JdfwZhpHkWi5ZE26prjPrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MiLka/dJMcaixBoCW/JdfwZhpHkWi5ZE26prjPrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MiLka/dJMcaixBoCW/JdfwZhpHkWi5ZE26prjPrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMiLka%2FdJMcaixBoCW%2FJdfwZhpHkWi5ZE26prjPrk%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;904&quot; height=&quot;234&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 베이스 주소는 가장 위에 있는 Start Addr입니다. 즉, &lt;span&gt;0x5555555540를 기준으로 다른 데이터들이 오프셋으로 매핑되는 구조입니다.&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&gt;알아낸 베이스 주소에 3298을 더해서 브레이크 포인트를 걸어주면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1786257856781&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;b *(0x55555555400 + 0x3298)&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;이제 브레이크 포인트를 걸었으니 s 값을 알아내러 가보겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PmvON/dJMcabZz5yi/VNt9IcKuuyt9ipg4jtyJHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PmvON/dJMcabZz5yi/VNt9IcKuuyt9ipg4jtyJHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PmvON/dJMcabZz5yi/VNt9IcKuuyt9ipg4jtyJHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPmvON%2FdJMcabZz5yi%2FVNt9IcKuuyt9ipg4jtyJHk%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;298&quot; height=&quot;90&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;90&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 key 값을 입력하라고 하는데, AI는 &quot;fgets 때문에 입력값을 받는 것이니 아무 값이나 입력해도 될 것이다.&quot;라고 하길래 아무거나 쳤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 finish를 입력해서 sub_3298을 끝내고 s값을 확인해보았습니다. 이 때까지만해도 플래그가 나올거라고 생각하고 있었어요.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bncCn2/dJMcaazzz86/WqAbMBR8pNGeJkhU9lxKQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bncCn2/dJMcaazzz86/WqAbMBR8pNGeJkhU9lxKQk/img.png&quot; data-alt=&quot;나는 진짜 바보야&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bncCn2/dJMcaazzz86/WqAbMBR8pNGeJkhU9lxKQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbncCn2%2FdJMcaazzz86%2FWqAbMBR8pNGeJkhU9lxKQk%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;450&quot; height=&quot;62&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나는 진짜 바보야&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AAAA가 그대로 나왔습니다. 이거보고 제가 앞에서 얼마나 대충 해석하고 있었는지 깨달았습니다. 돌이켜보면, 함수 구조가 이렇습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;fgets에는 stdin으로 입력을 받아 s에 저장한다.(이걸 생각도 안하고 있었음)&lt;/li&gt;
&lt;li&gt;s를 인자로 받는 sub_3298의 리턴 값에 따라 출력되는 문구가 다르다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 정확한 플래그를 입력해야 sub_3298을 무사히 통과하고 Congrats! .. 문구가 나오는 구조인 것 입니다. 왠진 모르겠지만, 이 구조도 파악을 못하고 있었다는게 참..아쉬울 따름입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. sub_3298의 로직을 제대로 분석해보자.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qB9pM/dJMcaalUXHU/TBwV4nY5NevRu9h6eREzC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qB9pM/dJMcaalUXHU/TBwV4nY5NevRu9h6eREzC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qB9pM/dJMcaalUXHU/TBwV4nY5NevRu9h6eREzC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqB9pM%2FdJMcaalUXHU%2FTBwV4nY5NevRu9h6eREzC0%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;637&quot; height=&quot;451&quot; data-origin-width=&quot;904&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 인자 a1과 a2는 각 byte_6020과 s임. -&amp;gt; ASCII 코드 값과 연관이 있을 것임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v5 = *a1 + i*i -&amp;gt; a1의 i번째 요소에 i제곱을 더함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v6 = *a2 -&amp;gt; a2의 i번 째 요소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if(__popcnt(v5) == 0) break; -&amp;gt; v5의 값이 0이되어야 반복문 탈출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if( (i &amp;amp; 1) != 0) -&amp;gt; i를 이진수 비트로 표현했을 때 LSB 1비트가 1인지 아닌지 검사하는 조건 -&amp;gt; i가 짝수인가 홀수인가를 판별하는 조건과 같은 듯함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v8 -&amp;gt; i가 짝수인지 홀수인지에 따라 v5와 v6의 차를 더하거나 둘의 비트 단위 XOR 값을 더하거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sub_3298의 리턴값: popcnt(v6) + v8 = 0을 만족하려면 둘 다 0이어야함. popcnt(v6) = -v8(즉, v8이 음수)인 경우는 v8이 unsigned로 선언되어있으므로 불가능함.&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;결과적으로, a1의 값과 입력값의 연산 결과에 따라 정확한 flag인지 아닌지를 판단하는 것 같습니다. 그런데 이걸 손수 계산하려니 머리가 너무 복잡해서 분석 결과를 보여주고 도움을 요청해봤습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1ybMe/dJMcagzI5QG/JFtH8YIr0KgH4Kx7ud7SY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1ybMe/dJMcagzI5QG/JFtH8YIr0KgH4Kx7ud7SY1/img.png&quot; data-alt=&quot;나는 진짜 바보야2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1ybMe/dJMcagzI5QG/JFtH8YIr0KgH4Kx7ud7SY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1ybMe%2FdJMcagzI5QG%2FJFtH8YIr0KgH4Kx7ud7SY1%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;904&quot; height=&quot;438&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나는 진짜 바보야2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 다 분석해놓고...답을 눈 앞에 두고... 결론을 놓치고 있었습니다. 당시에는 뭐에 매몰된건지 모르겠는데, v5 = v6를 생각해내지 못했네요. 아무튼 이제 다왔습니다. v5 = v6라는 말은 입력값 s와 v5가 같으면 되니까. v5를 역산해내면 플래그를 얻어낼 수 있겠습니다!&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;... 그런데 잠깐, 그럼 v5가 어떻게 정지 조건을 만족 시킬 수 있는거지요? v5는 반드시 양수만 더해지고 있는데요...&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tZQgF/dJMcagT4iMN/wR14CJFSPXoLHX1rkrOe6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tZQgF/dJMcagT4iMN/wR14CJFSPXoLHX1rkrOe6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tZQgF/dJMcagT4iMN/wR14CJFSPXoLHX1rkrOe6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtZQgF%2FdJMcagT4iMN%2FwR14CJFSPXoLHX1rkrOe6K%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;721&quot; height=&quot;311&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 역산을 통해 플래그를 얻어냈다! 그런데....&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬 스크립트로 역산해서 플래그를 얻어냈습니다. 그래서 검증을 위해 프로그램을 실행시켜 Key 입력으로 플래그를 입력했고, 정상 결과를 얻어냈습니다.&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;p data-ke-size=&quot;size16&quot;&gt;그 때 생각난 예전에 동아리 회장님이 말해준 조언이 생각났습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;잘못된 결과.png&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/z55j5/dJMcahSRVoJ/RkpxKoKrOTB635Nk4YcWl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/z55j5/dJMcahSRVoJ/RkpxKoKrOTB635Nk4YcWl1/img.png&quot; data-alt=&quot;틀린 플래그이지만, 의도된 플래그이므로 공개하지 않겠습니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/z55j5/dJMcahSRVoJ/RkpxKoKrOTB635Nk4YcWl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fz55j5%2FdJMcahSRVoJ%2FRkpxKoKrOTB635Nk4YcWl1%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;1164&quot; height=&quot;84&quot; data-filename=&quot;잘못된 결과.png&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;틀린 플래그이지만, 의도된 플래그이므로 공개하지 않겠습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: Noto Serif KR;&quot;&gt;가짜 플래그도 있다. 제목이 왜 상대성 이론인지 생각해봐라.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇습니다... 제가 구한건 가짜 플래그였던겁니다. 마지막에 &quot;if you didn't cheat!&quot;가 그런 의미였던거군요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 트릭이 뭘까?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lNCFC/dJMcaa0Ai7C/T0X7xnb8Dhk80fJhm2z5PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lNCFC/dJMcaa0Ai7C/T0X7xnb8Dhk80fJhm2z5PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lNCFC/dJMcaa0Ai7C/T0X7xnb8Dhk80fJhm2z5PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlNCFC%2FdJMcaa0Ai7C%2FT0X7xnb8Dhk80fJhm2z5PK%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;1430&quot; height=&quot;258&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ptrace가 안티 디버거 역할을 해서 가짜 플래그를 생성하게 만드는 트릭이라고합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ptrace는 리눅스에서 프로세스를 추적/디버깅 하기 위한 시스템콜입니다. 프로세스를 추적하고 디버깅하는 시스템콜이 어떻게 안티 디버거로써 사용될까요? 이는 ptrace의 호출 규칙을 알아야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GDB 같은 디버거는 내부적으로 ptrace를 호출합니다. 그런데 이 ptrace는 한 프로세스 당 하나만 호출할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 gdb로 관찰 중인 프로세스가 스스로에게 ptrace를 호출한다면, 이미 gdb가 ptrace를 통해서 붙어있으므로, ptrace 호출에 실패하게됩니다. 이런 원리를 이용하여 프로그램 내부적으로 ptrace 호출에 실패하면 디버깅 중인 것으로 감지하는 분기를 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 relativity도 ptrace 감지 시 byte_6020 데이터의 복호화 결과를 변조하여 잘못된 플래그가 출력되도록하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. ptrace를 우회하여 플래그를 얻어내보자&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;GDB catch syscall ptrace: GDB에서 ptrace를 호출할 때, 자동으로 멈추도록 catch를 설정하고 리턴 값을 0으로 덮어써서 프로그램을 속이는 방법&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1786261214698&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;catch syscall
continue(첫번째 ptrace 호출 시점)
continue(두번 째, 리턴 시점)
set $rax = 0
continue&lt;/code&gt;&lt;/pre&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;1280&quot; data-origin-height=&quot;396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ocUK8/dJMcahlczlr/YXKFk38KyZrKxDwxkeOcNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ocUK8/dJMcahlczlr/YXKFk38KyZrKxDwxkeOcNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ocUK8/dJMcahlczlr/YXKFk38KyZrKxDwxkeOcNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FocUK8%2FdJMcahlczlr%2FYXKFk38KyZrKxDwxkeOcNk%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;396&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;396&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;처음과 다른 데이터 셋을 얻어냈지만, 첫번째 0x35만 다르고 나머지는 같았습니다. 이를 기반으로 계산한 플래그 또한 정답이 아니었습니다. 아마도 gdb가 붙어있는 것 자체로도 감지되는 메커니즘이 있거나, 중간에 뭔가 꼬인 것 같습니다.(실제로 3번정도 시도해봤는데, 다 실패함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 파일의 원본 데이터와 gdb 덤프를 각각 추출하여 비교 해보았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdq5c0/dJMb99N4Gxi/EXBZoKHlqEUelJOX88BqT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdq5c0/dJMb99N4Gxi/EXBZoKHlqEUelJOX88BqT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdq5c0/dJMb99N4Gxi/EXBZoKHlqEUelJOX88BqT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdq5c0%2FdJMb99N4Gxi%2FEXBZoKHlqEUelJOX88BqT1%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;1028&quot; height=&quot;666&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위가 gdb 덤프값 즉, gdb가 붙어있을 때, 6020의 데이터 값이고 아래가 원본 데이터셋입니다. 파일 원본과 런타임 데이터 셋이 다르다는 것은 프로그램 실행 중에 byte_6020을 복호화하는 루틴을 거친다는 의미입니다. 이 루틴 내부에 안티디버깅을 적용하여 gdb가 탐지되면 잘못된 복호화를 하는 구조인 듯 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 2. GDB + LD_PRELOAD ptrace 우회: ptrace를 항상 0을 리턴하는 가짜 함수로 대체하는 공유 라이브러리를 만들고, GDB 내에서 set environment 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는 리눅스가 프로그램을 실행할 때, 필요한 공유 라이브러리를 메모리에 로드하는 과정에 특정 라이브러리를 가장 먼저 로드하도록 강제하는 환경 변수입니다. 이를 이용하여 가짜 라이브러리를 먼저 로드하도록 강제하는 거죠&lt;/p&gt;
&lt;pre id=&quot;code_1786261526065&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;gcc -shared -fPIC -o /tmp/bypass.so bypass.c 
gdb ./relativity &amp;rarr; set environment LD_PRELOAD /tmp/bypass.so 
start
b *(베이스+0x3298)
continue
x/100bx $rdi&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 방법도 실패했습니다. 덤프 결과가 첫번째 시도와 똑같은 결과가 출력되었고, ptrace 우회와 관계 없이 gdb가 붙어있는 사실 자체가 문제인 것 같습니다.&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;3. fgets 후킹을 이용한 key 추출&lt;/p&gt;
&lt;pre id=&quot;code_1786265273131&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat &amp;gt; /tmp/dump.c &amp;lt;&amp;lt; 'EOF'
#define _GNU_SOURCE
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;dlfcn.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;fcntl.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

long ptrace(int request, ...) { return 0; } //ptrace 우회 부분, 가짜 함수를 호출시킴

char* fgets(char* s, int n, FILE* stream) {
    static int dumped = 0;
    char* (*real_fgets)(char*, int, FILE*) = dlsym(RTLD_NEXT, &quot;fgets&quot;); //가짜 함수를 실행하고 나면, 라이브러리에서 진짜 fgets를 찾아서 실행 시키도록함
    char* result = real_fgets(s, n, stream);

    if (!dumped) {
        dumped = 1;
        int fd = open(&quot;/proc/self/maps&quot;, O_RDONLY);
        char buf[8192] = {0};
        read(fd, buf, sizeof(buf)-1);
        close(fd);

		//relativity의 base 주소 계산
        char* p = strstr(buf, &quot;relativity&quot;);
        if (p) {
            while (p &amp;gt; buf &amp;amp;&amp;amp; *(p-1) != '\n') p--;
            unsigned long base;
            sscanf(p, &quot;%lx&quot;, &amp;amp;base);
            
         // 계산된 베이스 주소 기반으로 6020의 데이터로 key값 계산
            unsigned char* data = (unsigned char*)(base + 0x6020);

            char out[512] = {0};
            int pos = 0;
            for (int i = 0; i &amp;lt; 100; i++) {
                unsigned char v5 = (unsigned char)(data[i] + i * i);
                if (v5 == 0) break;
                out[pos++] = v5;
            }
            out[pos] = 0;
            write(2, &quot;KEY: &quot;, 5);
            write(2, out, pos);
            write(2, &quot;\n&quot;, 1);
        }
    }
    return result;
}
EOF
gcc -shared -fPIC -o /tmp/dump.so /tmp/dump.c -ldl&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 복잡한 스크립트를 작성했습니다. 이번 방법의 핵심은 fgets 후킹인데, 이는 원래 함수 호출을 가로채서 원하는 함수가 대신 실행되게 하는 것입니다. main 내부에는 복호화 루틴을 수행하는 함수가 없었고, 바로 fgets로 입력받은 데이터를 sub_3298에 넘겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 원본 데이터와 덤프 값이 달랐으므로, byte_6020의 복호화 루틴은 main 이전에 실행될 것이라고 추정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 현재 프로그램의 실행 흐름이 &quot;복호화 루틴 &amp;rarr; main &amp;rarr; fgets(Key 입력) &amp;rarr; sub_3298&quot; 순서로 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fgets로 입력을 받는 시점에는 이미 복호화가 완료 되어있으므로, gdb가 붙어있지 않는 한, 정상 데이터가 byte_6020에 들어가게 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-09 오후 6.10.20.png&quot; data-origin-width=&quot;1484&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boK8Ft/dJMcacRzAxB/w8kcsLpdkYP7O192yhnhaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boK8Ft/dJMcacRzAxB/w8kcsLpdkYP7O192yhnhaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boK8Ft/dJMcacRzAxB/w8kcsLpdkYP7O192yhnhaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboK8Ft%2FdJMcacRzAxB%2Fw8kcsLpdkYP7O192yhnhaK%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;1484&quot; height=&quot;160&quot; data-filename=&quot;스크린샷 2026-08-09 오후 6.10.20.png&quot; data-origin-width=&quot;1484&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키 값을 알아내기 위해 아무런 값이나 입력했고, 제대로 된 key 값을 얻어낼 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배울 점이 많은 문제였다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 문제 하나를 해결하기 위해 많은 개념을 배웠습니다. 간단하게는 sub_3298 내부의 조건문, 정지조건, 플래그를 도출하기 위한 조건부터 크게는 ptrace의 개념과 안티디버거로써 사용되는 방법, 진짜 key를 얻어내기 위해 적용한 LD_PRELOAD, fgets 후킹 등 중요한 개념들을 배울 수 있어서 좋았어요. 이 문제는 다음에 한번 더 풀어보면서 오늘 배운 개념들을 적용해봐야하겠습니다. 여러분들도 이 문제는 꼭 한번쯤 풀어보시길 바랍니다. 감사합니다.&lt;/p&gt;</description>
      <category>write-up</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/5</guid>
      <comments>https://commanderjjm.tistory.com/5#entry5comment</comments>
      <pubDate>Sun, 9 Aug 2026 18:18:07 +0900</pubDate>
    </item>
    <item>
      <title>Small Counter</title>
      <link>https://commanderjjm.tistory.com/4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;죽어버린 클로드&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.41.28.png&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kVpsk/dJMcaaTMwj4/e4mk8lNJoNAe39KcVqrWr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kVpsk/dJMcaaTMwj4/e4mk8lNJoNAe39KcVqrWr0/img.png&quot; data-alt=&quot;요즘들어 갑자기 토큰이 엄청 빨리 줄어드는 듯하다..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kVpsk/dJMcaaTMwj4/e4mk8lNJoNAe39KcVqrWr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkVpsk%2FdJMcaaTMwj4%2Fe4mk8lNJoNAe39KcVqrWr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;78&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.41.28.png&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;요즘들어 갑자기 토큰이 엄청 빨리 줄어드는 듯하다..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 dbg 문제를 해결하고 첫 문제를 풀려고 하니까 내 길잡이가 파업을 선언했단다. 그래도 어쩔 수 있나. 혼자 풀어보기로 결정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chat GPT 무료 플랜에게 아직 익숙치 않은 어셈블리 관련 용어의 뜻을 물어보며 해결했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;처음보면 정말 어지러운 화면&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.47.30.png&quot; data-origin-width=&quot;2296&quot; data-origin-height=&quot;1158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmevVG/dJMb998omJO/0hZNf2EvNX55TY2Ig5c5Mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmevVG/dJMb998omJO/0hZNf2EvNX55TY2Ig5c5Mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmevVG/dJMb998omJO/0hZNf2EvNX55TY2Ig5c5Mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmevVG%2FdJMb998omJO%2F0hZNf2EvNX55TY2Ig5c5Mk%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;2296&quot; height=&quot;1158&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.47.30.png&quot; data-origin-width=&quot;2296&quot; data-origin-height=&quot;1158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.48.08.png&quot; data-origin-width=&quot;1124&quot; data-origin-height=&quot;1196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOR9Rx/dJMcaa7oWtT/7KBs2BDTFYloTPABgqIVY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOR9Rx/dJMcaa7oWtT/7KBs2BDTFYloTPABgqIVY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOR9Rx/dJMcaa7oWtT/7KBs2BDTFYloTPABgqIVY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOR9Rx%2FdJMcaa7oWtT%2F7KBs2BDTFYloTPABgqIVY1%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;1124&quot; height=&quot;1196&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.48.08.png&quot; data-origin-width=&quot;1124&quot; data-origin-height=&quot;1196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.48.40.png&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dRfZDD/dJMcajpxVQp/NwsH8YzYfEmgd2JtGwuryk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dRfZDD/dJMcajpxVQp/NwsH8YzYfEmgd2JtGwuryk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dRfZDD/dJMcajpxVQp/NwsH8YzYfEmgd2JtGwuryk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRfZDD%2FdJMcajpxVQp%2FNwsH8YzYfEmgd2JtGwuryk%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;1680&quot; height=&quot;1254&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.48.40.png&quot; data-origin-width=&quot;1680&quot; data-origin-height=&quot;1254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 진짜 감도 안 잡혔는데, 우선 어셈블리와 디컴파일 결과가 어떻게 대응되는지부터 해석하기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 명령어 한줄씩 커서를 놓고 tab을 눌러서 디컴파일 결과의 어디에 대응되는지부터 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 드는 생각&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;너무 간단한 디컴파일 결과에 비해 어셈블리가 복잡하게 구성되어있다..?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 지피티에게 물어봤다. &quot;디컴파일 결과가 다소 부정확하거나 명령어가 잘려서 보일 수도 있나?&quot;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.54.56.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mSdnb/dJMcahk93Rn/LmXQFF5slyyi0wlkCyrOD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mSdnb/dJMcahk93Rn/LmXQFF5slyyi0wlkCyrOD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mSdnb/dJMcahk93Rn/LmXQFF5slyyi0wlkCyrOD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmSdnb%2FdJMcahk93Rn%2FLmXQFF5slyyi0wlkCyrOD1%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;1312&quot; height=&quot;190&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.54.56.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;190&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애초에 문제에서도 &quot;플래그를 생성하는 함수를 '호출'하라&quot;고 했기 때문에, 의도적으로 숨기려면 숨길 수 있겠다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 생각을 바꿔 flag_gen 함수가 어디에 존재하는지부터 찾아보았다.&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-filename=&quot;스크린샷 2026-08-05 오후 9.56.35.png&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;1098&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMnIzD/dJMcaidjhJ5/9WxgY9egSQFyBk9uhXyQb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMnIzD/dJMcaidjhJ5/9WxgY9egSQFyBk9uhXyQb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMnIzD/dJMcaidjhJ5/9WxgY9egSQFyBk9uhXyQb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMnIzD%2FdJMcaidjhJ5%2F9WxgY9egSQFyBk9uhXyQb1%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;1148&quot; height=&quot;1098&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.56.35.png&quot; data-origin-width=&quot;1148&quot; data-origin-height=&quot;1098&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명히 하단 중간에 존재하는 flag_gen을 발견할 수 있었다. 그럼 각 노드를 가리키는 화살표를 따라가보며 어떤 조건을 만족해야 해당 부분이 실행되는건지를 고민하며 그래프를 역으로 따라 올라가보았다.&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-filename=&quot;스크린샷 2026-08-05 오후 9.58.41.png&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wGZ86/dJMcaiqI0mk/m25ytukKmOjXR4ysnAhbH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wGZ86/dJMcaiqI0mk/m25ytukKmOjXR4ysnAhbH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wGZ86/dJMcaiqI0mk/m25ytukKmOjXR4ysnAhbH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwGZ86%2FdJMcaiqI0mk%2Fm25ytukKmOjXR4ysnAhbH1%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;552&quot; height=&quot;264&quot; data-filename=&quot;스크린샷 2026-08-05 오후 9.58.41.png&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flag_gen 이전에 실행되어야하는 것으로 추정되는 루틴 두 가지이다. 여기서 눈에 띈 부분은 rbp+var_4였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 무엇인가하니&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.00.41.png&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EZaru/dJMcabE7wiE/5SmkhhKzqNM1ekS7C5xBLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EZaru/dJMcabE7wiE/5SmkhhKzqNM1ekS7C5xBLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EZaru/dJMcabE7wiE/5SmkhhKzqNM1ekS7C5xBLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEZaru%2FdJMcabE7wiE%2F5SmkhhKzqNM1ekS7C5xBLK%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;1144&quot; height=&quot;324&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.00.41.png&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;324&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.03.06.png&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evvDJb/dJMcacYnpDL/YVxhsG5j7KbleoB9ZwDh81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evvDJb/dJMcacYnpDL/YVxhsG5j7KbleoB9ZwDh81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evvDJb/dJMcacYnpDL/YVxhsG5j7KbleoB9ZwDh81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FevvDJb%2FdJMcacYnpDL%2FYVxhsG5j7KbleoB9ZwDh81%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;624&quot; height=&quot;212&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.03.06.png&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 변수에 대고 tab을 눌러보니 디컴파일 부분에는 for문 부분에 하이라이트가 된다. 지피티에게 어셈블리 명령어 의미를 물어보니 mov는 값 복사, jmp는 해당 루틴으로 점프 등등...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 두 줄에 주목해보자. rbp_var_4(간단하게 rv라고 부르겠다)를 10으로 초기화하고 loc15_A0로 점프하는 코드가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 loc15_A0는 무슨 일을 하고 있을까?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.14.27.png&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjruHX/dJMcadv50ws/Mp4hSzLGAIzVgQ7a82Lsok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjruHX/dJMcadv50ws/Mp4hSzLGAIzVgQ7a82Lsok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjruHX/dJMcadv50ws/Mp4hSzLGAIzVgQ7a82Lsok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjruHX%2FdJMcadv50ws%2FMp4hSzLGAIzVgQ7a82Lsok%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;240&quot; height=&quot;124&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.14.27.png&quot; data-origin-width=&quot;240&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rv와 0을 비교하고 rv가 크면 loc_14C5로 이동하도록하고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.16.24.png&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;1106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7FtED/dJMcabylWOH/KwElTVmZKHTI2WoNepw6Lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7FtED/dJMcabylWOH/KwElTVmZKHTI2WoNepw6Lk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7FtED/dJMcabylWOH/KwElTVmZKHTI2WoNepw6Lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7FtED%2FdJMcabylWOH%2FKwElTVmZKHTI2WoNepw6Lk%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;1150&quot; height=&quot;1106&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.16.24.png&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;1106&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적인 구도를 살펴보면 rv가 3인지 비교하며 분기하는 루틴이 있고, rv를 1씩 깎고 다시 loc_15A0 루틴으로 돌아오는 구도를 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 나는 rv는 for문의 i를 의미하는걸로 추정을한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;loc_15A0에서 조건을 불만족 시켜야한다.&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loc_15A0에서 조건을 불만족했을 때의 그래프를 따라가야 flag_gen까지 도달할 수 있다는 것을 알 수 있다. 그러나 이 사실은 디컴파일 결과에서는 명시적으로 나타나고 있지 않다. 가장 눈에 띄는 것은 아래 부분이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.19.13.png&quot; data-origin-width=&quot;266&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9x1wv/dJMcabSFkg8/M3pbYLKJ8In0KGkRTTAkK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9x1wv/dJMcabSFkg8/M3pbYLKJ8In0KGkRTTAkK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9x1wv/dJMcabSFkg8/M3pbYLKJ8In0KGkRTTAkK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9x1wv%2FdJMcabSFkg8%2FM3pbYLKJ8In0KGkRTTAkK1%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;266&quot; height=&quot;102&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.19.13.png&quot; data-origin-width=&quot;266&quot; data-origin-height=&quot;102&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;h2 data-ke-size=&quot;size26&quot;&gt;for문이 끝난 이후에 브레이크 포인트를 걸어 i값을 수정한다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i값이 0이되어 반복문이 끝난 이후에, i 값을 5로 수정한다면? loc_15A0의 조건을 불만족 시키고 jnz short loc_15FE의 조건을 만족시켜 flag_gen이 존재하는 루틴까지 한번에 갈 수 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.23.57.png&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ4BE8/dJMcaazw716/Ak4UKqGraNwJyhSPpSpqkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ4BE8/dJMcaazw716/Ak4UKqGraNwJyhSPpSpqkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ4BE8/dJMcaazw716/Ak4UKqGraNwJyhSPpSpqkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ4BE8%2FdJMcaazw716%2FAk4UKqGraNwJyhSPpSpqkk%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;1596&quot; height=&quot;418&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.23.57.png&quot; data-origin-width=&quot;1596&quot; data-origin-height=&quot;418&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rbp-4(rv)와 5가 같은지 비교하고 점프하는 부분의 주소가 0x5555555555aa임을 알 수 있다. 이 곳에 브레이크 포인트를 설정하고 프로그램을 실행시킨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.25.30.png&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;606&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tEJMW/dJMcahyCQQw/Pel4b3KW4odjhh09EbLQeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tEJMW/dJMcahyCQQw/Pel4b3KW4odjhh09EbLQeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tEJMW/dJMcahyCQQw/Pel4b3KW4odjhh09EbLQeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtEJMW%2FdJMcahyCQQw%2FPel4b3KW4odjhh09EbLQeK%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;1186&quot; height=&quot;606&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.25.30.png&quot; data-origin-width=&quot;1186&quot; data-origin-height=&quot;606&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 실행되고 멈췄다. 이제 예측이 맞다면, 이 곳에서 rv의 값을 확인하면 0이 나올 것이다. 또한 display 명령어를 통해 다음에 실행할 명령어를 확인해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.28.44.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/miJ7X/dJMcadXh0JC/b5OqKixsQYXKPKUuYRPO00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/miJ7X/dJMcadXh0JC/b5OqKixsQYXKPKUuYRPO00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/miJ7X/dJMcadXh0JC/b5OqKixsQYXKPKUuYRPO00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmiJ7X%2FdJMcadXh0JC%2Fb5OqKixsQYXKPKUuYRPO00%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;916&quot; height=&quot;138&quot; data-filename=&quot;스크린샷 2026-08-05 오후 10.28.44.png&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 값이 0으로 나왔고, 다음으로 실행할건 5와 같은지 비교하는 것이다. 그럼 이제 rv의 값을 5로 수정해본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-06 오후 2.03.48.png&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oFw2c/dJMcagfoFgX/JZfakkPsSmEyQLGJugb3D1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oFw2c/dJMcagfoFgX/JZfakkPsSmEyQLGJugb3D1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oFw2c/dJMcagfoFgX/JZfakkPsSmEyQLGJugb3D1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoFw2c%2FdJMcagfoFgX%2FJZfakkPsSmEyQLGJugb3D1%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;1674&quot; height=&quot;392&quot; data-filename=&quot;스크린샷 2026-08-06 오후 2.03.48.png&quot; data-origin-width=&quot;1674&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;5로 수정됐음을 확인하고 프로그램을 계속 진행시켜 플래그를 얻을 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로는 AI의 도움을 최대한 덜 받았다고 생각하는데, 그래도 중간에 어셈블리 명령어의 의미, 명령어가 하나로 합쳐져 보일 수 있다는 것, 명령어의 조합이 for문일 가능성 등은 AI의 도움을 받았다. 그래도 코난급 추리로 성취감이 매우 큰 문제였다. 해결 과정이 중구난방이라 무슨 소리를 하는건지 이해 안될 수도 있는데, 정리되지 않은 생각을 까먹기 전에 급하게 작성해서 그렇습니다..하하&amp;nbsp;&lt;/p&gt;</description>
      <category>write-up</category>
      <category>Small Counter #Dreamhack 문제</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/4</guid>
      <comments>https://commanderjjm.tistory.com/4#entry4comment</comments>
      <pubDate>Wed, 5 Aug 2026 22:34:27 +0900</pubDate>
    </item>
    <item>
      <title>Apple Silicon Mac에서 x86-64 디버깅 환경 구축하는 방법</title>
      <link>https://commanderjjm.tistory.com/3</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Apple, 자네가 정말 밥맛이야.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;아톨밥맛.jpg&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KetvE/dJMcacqBtmm/QDkYXhkkxafYKDo5aOIyPk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KetvE/dJMcacqBtmm/QDkYXhkkxafYKDo5aOIyPk/img.jpg&quot; data-alt=&quot;엇나가는 애플의 행보 때문에 미치겠다..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KetvE/dJMcacqBtmm/QDkYXhkkxafYKDo5aOIyPk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKetvE%2FdJMcacqBtmm%2FQDkYXhkkxafYKDo5aOIyPk%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;1019&quot; height=&quot;1024&quot; data-filename=&quot;아톨밥맛.jpg&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;엇나가는 애플의 행보 때문에 미치겠다..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어제 동적 분석을 공부하기 위해 Dreamhack의 Check Return Value 문제를 풀려고 했다. 정적 분석에는 IDA를 이용했다면 이번에는 gdb를 사용하려고 환경을 구축하는데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;아키텍처 호환 문제로 gdb를 설치해도 제대로 실행이 되지 않는 문제가 발생한다.&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;절규.jpg&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;979&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RDb1n/dJMcaasLt69/48ZwkW6ddNlSIOGqhoIuU1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RDb1n/dJMcaasLt69/48ZwkW6ddNlSIOGqhoIuU1/img.jpg&quot; data-alt=&quot;나한테 왜이러는거야 진짜&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RDb1n/dJMcaasLt69/48ZwkW6ddNlSIOGqhoIuU1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRDb1n%2FdJMcaasLt69%2F48ZwkW6ddNlSIOGqhoIuU1%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;850&quot; height=&quot;979&quot; data-filename=&quot;절규.jpg&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;979&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;나한테 왜이러는거야 진짜&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맥OS를 쓰는자의 숙명인걸까... 이 일로 나는 문제 하나를 &quot;풀기&quot;위해 5시간을 환경 구축에만 매달리게 된다. 결과적으로 방법은 찾았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나와 비슷한 사람들에게 조금이라도 도움이 됐으면 해서 삽질 과정을 공유해보겠다. 그 전에, GDB, pwndbg의 개념 등은 추후 따로 정리하겠습니다. 해결 방법의 핵심만 보고 싶은 분들은 맨 뒤로 이동해주세요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 이렇게 오래 걸렸을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 사이트도 마찬가지이겠지만, Dreamhack의 어지간한 문제들의 실행 파일은 x86-64 아키텍처 기반으로 작성되어있다. 왜 그런지 이유를 찾아봤는데, 이게 교육용으로 쓰기 좋고 관례적으로 사용해왔다는 듯하다. 그런데, Apple silicon 즉, M1 이상의 M시리즈 칩들은 ARM 아키텍처를 채택하고 있다. 이 말은 내 환경과 실행 파일의 명령어 구성이 다르다는 것이다..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;말이 안통.jpg&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beprpW/dJMcaidi6xP/STiQwLzdGHdfMOR0e0BEkk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beprpW/dJMcaidi6xP/STiQwLzdGHdfMOR0e0BEkk/img.jpg&quot; data-alt=&quot;서로 말이 안통하는 ARM과 x86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beprpW/dJMcaidi6xP/STiQwLzdGHdfMOR0e0BEkk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeprpW%2FdJMcaidi6xP%2FSTiQwLzdGHdfMOR0e0BEkk%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;761&quot; height=&quot;800&quot; data-filename=&quot;말이 안통.jpg&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서로 말이 안통하는 ARM과 x86&lt;/figcaption&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;h2 data-ke-size=&quot;size26&quot;&gt;첫번째 시도: UTM 기반 VM 우분투에서 실행해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 작년에 들은 전공 수업 때문에, UTM과 리눅스 환경이 구축되어있었다. 그러나 이것도 여러 문제가 있었는데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;단순히 VM에서 gdb를 설치한다고해서 되는게 아니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 UTM에 있는 리눅스 환경의 설정이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 5.32.16.png&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cc84pn/dJMb998oelQ/wkPMwiBcsWqxTeOnLmTm2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cc84pn/dJMb998oelQ/wkPMwiBcsWqxTeOnLmTm2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cc84pn/dJMb998oelQ/wkPMwiBcsWqxTeOnLmTm2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcc84pn%2FdJMb998oelQ%2FwkPMwiBcsWqxTeOnLmTm2K%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;1238&quot; height=&quot;266&quot; data-filename=&quot;스크린샷 2026-08-05 오후 5.32.16.png&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍처가 여전히 ARM으로 설정되어 있었다. 이러니 당연히 이 환경에서도 실행이 안되지.. 그래서 QEMU 에뮬레이션을 설치해보았다. 간단하게 설명하면 다른 아키텍처의 프로그램을 실행할 수 있게 해주는 시뮬레이션이라고한다. 바로 환경 구성해서 실행을 해보았는데, 여러 문제가 터졌다..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;조졌다리.webp&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pDMzo/dJMcaafd8cu/BHIDjkMUKhd4d9GarLmJ7k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pDMzo/dJMcaafd8cu/BHIDjkMUKhd4d9GarLmJ7k/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pDMzo/dJMcaafd8cu/BHIDjkMUKhd4d9GarLmJ7k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpDMzo%2FdJMcaafd8cu%2FBHIDjkMUKhd4d9GarLmJ7k%2Fimg.webp&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;482&quot; height=&quot;749&quot; data-filename=&quot;조졌다리.webp&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;qemu에서 gdb를 붙이면 아키텍처 불일치 경고, 심볼 로딩 지연, 연결 끊김 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;아키텍처가 다른걸 전제로 qemu를 설치했는데 왜 아키텍처 불일치 경고가?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 gdb도 실행 파일의 아키텍처가 무엇인지 알아야한다는 사실 때문에 문제가 된다. qemu가 바이너리를 실행하고 GDB 서버를 열면 GDB는 이 프로세스의 아키텍처가 무엇인지 물어보는데, 이 과정에서 QEMU가 응답할 때, 호스트(ARM)과 게스트(x86)의 정보를 섞어서 전달해주는 경우가 발생한다. 즉, GDB에게 메타데이터를 안정적으로 전달하기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;심볼 로딩 지연은 무슨 문제일까&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main, printf 등 함수를 사람이 읽을 수 있는 형태의 이름표와 그 이름이 가리키는 메모리 주소를 연결해주는 정보인 심볼을 GDB가 읽어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬에서 GDB를 사용한다면, 빠르게 끝나지만, QEMU 원격 디버깅에서는 GDB가 바이너리 파일을 GDB 원격 프로토콜을 통해서 읽어온다. 그러나 이 프로토콜은 소량의 디버그 명령을 주고 받기 위해 설계된건데, 바이너리 파일 전체를 전송함으로써 속도가 매우 느려진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;애초에 연결 자체도 불안정하다&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스가 종료되면 QEMU도 같이 종료되어 연결 자체가 사라진다. 또한 앞서 QEMU의 메타데이터 전송이 불안정한 문제에서 기반하여 GDB가 기대하는 형식의 데이터가 오지 않으면 GDB쪽에서 신뢰할 수 없는 연결로 간주하고 연결을 끊어버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론은 QEMU와 GDB를 같이 사용하는건 안 맞다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 ARM 아키텍처로 설정되어있던 VM 대신 새 VM을 생성하고 Rosetta를 사용하기로 했다. 생성 과정에서 Enable Rosetta 옵션을 선택할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Rostta는 Apple에서 만든 자체 번역 기술인데, ARM에서 x86용으로 만들어진 프로그램을 실행할 수 있게 해준다고한다. 그런데 아직 기술이 불완전한가보다 체크 박스 옆에 아직 불안정하니 사용하지 않는걸 권고하는 문구가 있었다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 문제는 Rosetta는 ptrace(디버거가 프로세스에 붙는 시스템 콜)을 지원하지 않아서 GDB로 디버깅 자체가 불가능 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정말 미워.png&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9NXSU/dJMcabylOBI/RJotaJKqE41Gp9AhvakIB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9NXSU/dJMcabylOBI/RJotaJKqE41Gp9AhvakIB0/img.png&quot; data-alt=&quot;이 시점에 이미 3시간 경과...문제 두 개 풀러왔다가 시도조차 못했다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9NXSU/dJMcabylOBI/RJotaJKqE41Gp9AhvakIB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9NXSU%2FdJMcabylOBI%2FRJotaJKqE41Gp9AhvakIB0%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;802&quot; height=&quot;512&quot; data-filename=&quot;정말 미워.png&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이 시점에 이미 3시간 경과...문제 두 개 풀러왔다가 시도조차 못했다&lt;/figcaption&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;h2 data-ke-size=&quot;size26&quot;&gt;SSH 원격 서버를 이용해보자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH 프로토콜로 원격으로 x86 환경을 가진 서버에 접속하여 서버에서 gdb를 돌리는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;츄라이츄라이.png&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXEgcD/dJMcadbOoHD/O6KQK1fzjle9uxcWaiXoc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXEgcD/dJMcadbOoHD/O6KQK1fzjle9uxcWaiXoc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXEgcD/dJMcadbOoHD/O6KQK1fzjle9uxcWaiXoc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXEgcD%2FdJMcadbOoHD%2FO6KQK1fzjle9uxcWaiXoc0%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;608&quot; height=&quot;388&quot; data-filename=&quot;츄라이츄라이.png&quot; data-origin-width=&quot;608&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식을 채택한 이유는 여러가지가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상시 무료 서비스(Oracle Cloud Free Tier)&lt;/li&gt;
&lt;li&gt;네이티브 x86-64 환경을 사용할 수 있음(에뮬레이션 없음)&lt;/li&gt;
&lt;li&gt;한번 설정 후 재사용이 간편함&lt;/li&gt;
&lt;li&gt;GDB, pwndbg가 모두 정상 동작&lt;/li&gt;
&lt;li&gt;서버가 상시 가동되므로 맥을 꺼도 서버는 유지됨&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, x86 환경을 가진 서버를 내 컴퓨터처럼 사용할 수 있는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Oracle Cloud Free Tier에 회원가입 하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;oracle.com/kr/cloud/free &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 링크에 접속하여 &quot;무료로 시작하기&quot;를 클릭한다. Cloud 계정과 Oracle 계정이 따로 있는데, 무료로 시작하기로 가입하면 둘 다 자동으로 계정 설정이 된다.&amp;nbsp;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. VM 인스턴스 생성하기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.20.21.png&quot; data-origin-width=&quot;1886&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUzdeX/dJMcagl8m6o/GcjaSsgnpvbFrRfSORGxLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUzdeX/dJMcagl8m6o/GcjaSsgnpvbFrRfSORGxLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUzdeX/dJMcagl8m6o/GcjaSsgnpvbFrRfSORGxLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUzdeX%2FdJMcagl8m6o%2FGcjaSsgnpvbFrRfSORGxLk%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;1886&quot; height=&quot;1306&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.20.21.png&quot; data-origin-width=&quot;1886&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 화면에서 Instances를 선택하고 Create Instance로 들어간다.&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-filename=&quot;스크린샷 2026-08-05 오후 7.21.33.png&quot; data-origin-width=&quot;2842&quot; data-origin-height=&quot;1130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3vUvL/dJMb991GEGZ/5KrLiUXpEazgzA9EAJuqXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3vUvL/dJMb991GEGZ/5KrLiUXpEazgzA9EAJuqXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3vUvL/dJMb991GEGZ/5KrLiUXpEazgzA9EAJuqXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3vUvL%2FdJMb991GEGZ%2F5KrLiUXpEazgzA9EAJuqXk%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;2842&quot; height=&quot;1130&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.21.33.png&quot; data-origin-width=&quot;2842&quot; data-origin-height=&quot;1130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 화면에서 Change image를 누른다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.22.45.png&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o8cRc/dJMcacYnkBI/PUzEyv0tIGNSCSF4jS2rt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o8cRc/dJMcacYnkBI/PUzEyv0tIGNSCSF4jS2rt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o8cRc/dJMcacYnkBI/PUzEyv0tIGNSCSF4jS2rt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo8cRc%2FdJMcacYnkBI%2FPUzEyv0tIGNSCSF4jS2rt0%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;2156&quot; height=&quot;938&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.22.45.png&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 Ubuntu를 선택하고 아래로 스크롤하면 위와 같은 화면이 나오는데, 나는 24.04 버전을 선택했다.(aarch64는 ARM 아키텍처를 의미하는 것이므로 절대 선택하면 안된다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 자잘한 설정들은 기본값으로 설정하고 Next를 계속 누른다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.25.27.png&quot; data-origin-width=&quot;1828&quot; data-origin-height=&quot;802&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0coSp/dJMcah6wTyd/1U7kjepOlTCOcdbdD6iwZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0coSp/dJMcah6wTyd/1U7kjepOlTCOcdbdD6iwZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0coSp/dJMcah6wTyd/1U7kjepOlTCOcdbdD6iwZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0coSp%2FdJMcah6wTyd%2F1U7kjepOlTCOcdbdD6iwZK%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;1828&quot; height=&quot;802&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.25.27.png&quot; data-origin-width=&quot;1828&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;처음 만들면, Create new virtual cloud network를 선택해야한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.52.42.png&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doUyxO/dJMcaccZeZm/ymgBOzkcjyVkgdbKgZo9n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doUyxO/dJMcaccZeZm/ymgBOzkcjyVkgdbKgZo9n1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doUyxO/dJMcaccZeZm/ymgBOzkcjyVkgdbKgZo9n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoUyxO%2FdJMcaccZeZm%2FymgBOzkcjyVkgdbKgZo9n1%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;1654&quot; height=&quot;364&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.52.42.png&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;364&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.53.20.png&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dabi0q/dJMcaaM3j2Y/klUEJrc0MJ7RfHSSPgpXNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dabi0q/dJMcaaM3j2Y/klUEJrc0MJ7RfHSSPgpXNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dabi0q/dJMcaaM3j2Y/klUEJrc0MJ7RfHSSPgpXNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdabi0q%2FdJMcaaM3j2Y%2FklUEJrc0MJ7RfHSSPgpXNK%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;1918&quot; height=&quot;658&quot; data-filename=&quot;스크린샷 2026-08-05 오후 7.53.20.png&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Generate a key pair for me를 선택하고 아래의 private key와 public key를 다운로드하여 잘 보관한다(잃어버리면 다시 접속 못하니까 주의!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 설정은 기본값으로 놔두고 Next를 누르면 모든 준비가 완료된다. 이제 맥 터미널 창을 켜 아래와 같은 명령어를 입력해준다&lt;/p&gt;
&lt;pre id=&quot;code_1785927388161&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh -i ~/Desktop/ssh 키 파일 이름 ubuntu@내서버공인 IP&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 접속에 성공하면 서버의 자원을 쓸 수 있게 됐으므로, 해당 환경에 GDB와 pwndbg를 설치해주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주의사항&lt;/h4&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;30일 이상 서버에 접속하지 않으면 Oracle이 인스턴스를 회수할 수 있다.&lt;/li&gt;
&lt;li&gt;인스턴스 생성 시 Public IP를 할당받지 못했을 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스 상세 -&amp;gt; Networking -&amp;gt; Attached VNICs 섹션 -&amp;gt; IP adminstration 탭 -&amp;gt; IPv4 addresses에서 &lt;span&gt;⋮&lt;/span&gt;클릭 -&amp;gt; Edit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; Ephemeral public IP 선택 -&amp;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;결과적으로 아주 쾌적하고 빠른 속도로 GDB를 사용할 수 있게됐다 !&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;아이좋아.webp&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;741&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dddBHN/dJMcafAOlu7/PSuQ72H1uTwybxEmEhcTrK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dddBHN/dJMcafAOlu7/PSuQ72H1uTwybxEmEhcTrK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dddBHN/dJMcafAOlu7/PSuQ72H1uTwybxEmEhcTrK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdddBHN%2FdJMcafAOlu7%2FPSuQ72H1uTwybxEmEhcTrK%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;597&quot; height=&quot;538&quot; data-filename=&quot;아이좋아.webp&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;741&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 같은 환경에서 보안 공부하시는 분들에게 조금이라도 도움이 되었으면 좋겠습니다...! 노트북 사지 말고 이 방법 먼저 해보십쇼 다들&lt;/p&gt;</description>
      <category>환경 구성</category>
      <category>ssh #맥 #gdb</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/3</guid>
      <comments>https://commanderjjm.tistory.com/3#entry3comment</comments>
      <pubDate>Wed, 5 Aug 2026 20:03:53 +0900</pubDate>
    </item>
    <item>
      <title>rev-basic-1 , rev-basic-4, simple_patch_me, patch</title>
      <link>https://commanderjjm.tistory.com/2</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;할 일은 많고, 하기는 귀찮다(+잡담)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;할일은.jpg&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;597&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9cGZb/dJMcabylkQF/eoIE6fgVRem1qHkhlcd3CK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9cGZb/dJMcabylkQF/eoIE6fgVRem1qHkhlcd3CK/img.jpg&quot; data-alt=&quot;그래도 보안 공부는 재밌습니다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9cGZb/dJMcabylkQF/eoIE6fgVRem1qHkhlcd3CK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9cGZb%2FdJMcabylkQF%2FeoIE6fgVRem1qHkhlcd3CK%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;335&quot; height=&quot;597&quot; data-filename=&quot;할일은.jpg&quot; data-origin-width=&quot;335&quot; data-origin-height=&quot;597&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그래도 보안 공부는 재밌습니다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이틀 전에 빡공팟과 함께 풀어본 문제들을 쌓아뒀다가 이제 리뷰하기로 했다. 사실 어제 쓰려고 했는데, 어제 동적 분석 환경 설정에 애먹어서 그것만 하다가 집에갔음..(이것도 다룰 예정이다) 그래서 오늘은 꼭 작성하기로 결심했다. 블로그 작성하는거 생각보다 많이 귀찮은 일인데, 꾸준히 작성하시는 분들 존경스럽습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;안즐겁다.jpeg&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4xWe6/dJMcaa0xjRK/3jjY14CJvaP3U7qg8qGKH0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4xWe6/dJMcaa0xjRK/3jjY14CJvaP3U7qg8qGKH0/img.jpg&quot; data-alt=&quot;공부는 즐거우나 기록과 복습은 괴롭다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4xWe6/dJMcaa0xjRK/3jjY14CJvaP3U7qg8qGKH0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4xWe6%2FdJMcaa0xjRK%2F3jjY14CJvaP3U7qg8qGKH0%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;200&quot; height=&quot;308&quot; data-filename=&quot;안즐겁다.jpeg&quot; data-origin-width=&quot;200&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공부는 즐거우나 기록과 복습은 괴롭다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빡공팟 마무리 시간에 자신이 공부한걸 ppt로 정리해서 발표하는 시간을 가졌는데, 마지막 문제에 시간이 많이 뺏겨서 ppt를 정성스레 못 만들었다. 너무 아쉬웠음.. 회장형이 ppt는 글 보단 이미지가 많아야한다고 했는데, 만들고 보니 글 밖에 없었던...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;rev-basic-1&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;rev-basic 문제 시리즈를 5까지 풀어봤는데, 문제 해결 패턴은 전부 똑같아서 전체 프로그램 구조를 다루진 않겠다. Correct를 출력하기 위한 조건에 집중하는 것만 인지하면 될 듯 하다. 바로 조건식에 들어가는 함수를 살펴보자.&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-filename=&quot;image.png&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P0C0l/dJMcabrCRhn/k16SJfIkSpOvRGPhw84X61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P0C0l/dJMcabrCRhn/k16SJfIkSpOvRGPhw84X61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P0C0l/dJMcabrCRhn/k16SJfIkSpOvRGPhw84X61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP0C0l%2FdJMcabrCRhn%2Fk16SJfIkSpOvRGPhw84X61%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;446&quot; height=&quot;1000&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 봤을 때는 a1의 각 자리 요소가 조건문 내에 숫자들과 일치해야한다는건 알았다. 그러나 입력은 문자열로 받는데 왜 조건문에 숫자가 나오지?라는 궁금증이 들었는데, 이는 문자가 메모리에 저장될 때 ASCII 코드 표에 대응되는 숫자로 저장된다는 것을 이용한 트릭이었다. 생각보다 흔히 나오는 방식이니까 기억해두면 좋을 듯하다. IDA에서는 단축키 r을 누르면 숫자-문자의 아스키코드 변환 기능을 사용할 수 있다. 매우 유용한듯함. 결론적으로 플래그는 Compar3_the_ch4ract3r가 되겠다. 다른 분의 풀이를 보니 동적 분석으로 푸는 방법도 있던데, 다음에 기회가 되면 리뷰해보도록 하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;rev_basic_4&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 문제도 마찬가지로 조건문의 함수만 살펴보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HgUKF/dJMcabrCRBf/wK7FZcEwpGZDXRfbKPRddk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HgUKF/dJMcabrCRBf/wK7FZcEwpGZDXRfbKPRddk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HgUKF/dJMcabrCRBf/wK7FZcEwpGZDXRfbKPRddk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHgUKF%2FdJMcabrCRBf%2FwK7FZcEwpGZDXRfbKPRddk%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;1126&quot; height=&quot;232&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for문을 살펴보니 1부터 27까지 카운트를 세는 듯하다. 즉, 27번 반복한다. for문 내부에는 언뜻 보기에 복잡한 조건식이 들어있는데, |를 기준으로 좌우를 나눠 살펴보도록 하자.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;좌항&lt;/h4&gt;
&lt;pre id=&quot;code_1785891866272&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(unsigned __int8)(16 * *(_BYTE *)(a1 + i))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난 처음에 중간에 **를 보고 제곱인줄 알았다.. 나 같은 사람이 또 있을 수도 있으니 알려드려요. 이제 단계별로 분석해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. (_BYTE *)(a1 + i): a1의 i번째 요소의 주소를 1바이트 크기를 가리키는 주소로 해석하도록한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 바로 앞에 *를 붙여 해당 포인터가 가리키는 값을 읽도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 1번과 2번 과정을 합쳐서 해석하면, 그냥 a1의 i번째 요소 값을 가져온다는 뜻이된다. 이 값에 16을 곱한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;16을 곱한다는 것의 의미?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16을 곱한다는 것, 즉 2의 n승을 곱한다는 것은 특별한 의미가 있다. 숫자를 바이트, 또는 비트 단위로 보았을 때, 이는 비트를 왼쪽 또는 오른쪽으로 n만큼 이동시킨다는 뜻이된다. 또한 이동하고 나면 빈자리는 0으로 채워지게 된다. 이 개념은 비트의 각 자리가 2의 n승만큼의 가중치를 가진다는 개념을 알고있으면 쉽게 이해될 것이다. 즉, 16을 곱한다는 것은 왼쪽으로 4비트씩 이동한다는 뜻이된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;우항&lt;/h4&gt;
&lt;pre id=&quot;code_1785892354980&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;((int)*(unsigned __int8 *)(a1 + i) &amp;gt;&amp;gt; 4)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 해석하기 쉬울 것이다. &quot;&amp;gt;&amp;gt;&quot;는 비트연산자로써, n만큼의 비트를 오른쪽으로 이동시키게된다. &quot;&amp;lt;&amp;lt;&quot;는 왼쪽으로 미룬다는 것이 되겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 위 식은 a1의 i번째 요소의 비트를 오른쪽으로 4비트 이동시킨다는 뜻이된다.. 수학적으로 생각해보면 16으로 나눈다는 것이된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;|와 두 수식이 말해주는 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;| 는 bitwise OR로, 같은 자리 비트 단위의 OR을 수행해주는 연산자이다. 위에서 살펴본 두 수식과 이 연산자가 합쳐지면 꽤 재밌는 연산을 하게된다. 먼저 1바이트 크기의 11110000이라는 비트를 예시로 생각해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서말한 좌항의 식을 예시 비트에 적용하면 00000000이 된다.(빈자리는 0으로 채워진다고 했으니) 똑같이 우항을 적용하면 00001111이 된다. 여기서 00000000과 00001111에 |를 적용하면 어떻게 될까? 00001111이 된다! 이건 상위 4비트와 하위 4비트의 위치를 교환하는 효과를 낸다. 이걸 니블 스왑(nibble swap)이라고 한다. 1 nibble = 4 bit이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론적으로&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a1의 각 요소를 니블 스왑한 것과 byte_140003000[i]의 요소가 같아야한다. 니블 스왑의 역연산은 니블 스왑 자신이므로(앞뒤 4자리를 원위치하는 효과) byte_140003000[i] 요소에 니블 스왑을 적용한 것이 정답이 되겠다.&lt;br /&gt;IDA를 통해 byte_140003000[i] 의 데이터를 알아낸 다음 계산하면 플래그는 &quot;Br1ll1antbit_dr1bble&amp;lt;&amp;lt;_&amp;gt;&amp;gt;&quot;이된다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;rev_basic 시리즈를 풀어보며&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;simple_patch_me&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 문제는 1년이 지나야 플래그를 출력하는 프로그램에게서 플래그를 얻어내야하는 문제이다.&lt;/p&gt;
&lt;pre id=&quot;code_1785893298789&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//main 함수 구조
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  puts(s: &quot;I will show you the flag after 1 year :p&quot;);
  dword_40404C = 0;
  while ( (unsigned int)dword_40404C &amp;lt;= 0x2237 )
  {
    sleep(seconds: 0xE10u);
    if ( ++dword_40404C == 1 )
      puts(s: &quot;1 hour passed&quot;);
    else
      printf(format: &quot;%u hours passed\n&quot;, dword_40404C);
    if ( dword_40404C % 0x18u == 0 )
    {
      if ( dword_40404C == 24 )
        puts(s: &quot;1 day has paased.&quot;);
      else
        printf(format: &quot;%u days have passed.\n&quot;, dword_40404C % 0x18u);
    }
  }
  printf(format: &quot;Great xD 1 year has passed! The flag is: &quot;);
  sub_401196();
  return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위는 main 함수의 구조이다. 대략 코드의 구조는 dword_40404C가 시간 단위의 숫자를 카운트하고 8759시간(=1년)보다 작을 동안 while을 순회한다. while문이 끝나고 나면(1년 후) &quot;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Great xD 1 year has passed! The flag is:&quot;와 함께 플래그가 출력되는 구조이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년을 기다리지 않고 플래그를 출력해야하니까. 내가 생각하기에 가장 간단한 방법은 dword_40404C의 초기값을 0에서 8759보다 큰 수로 변경하는 것이다. 또는 while 문 내의 조건을 변경해도 될 것이다. 이러면 while문을 무력화 시켜 1년을 기다리지 않고 flag를 바로 출력하게 만들 수 있다. IDA에서 dword_40404C의 초기값을 정의한 어셈블리 부분을 선택하여 edit을 통해 정정할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-08-05 오전 10.40.11.png&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpSQE2/dJMcaf8xILo/VeoFhnwHhVyzHIgf2wE8R1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpSQE2/dJMcaf8xILo/VeoFhnwHhVyzHIgf2wE8R1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpSQE2/dJMcaf8xILo/VeoFhnwHhVyzHIgf2wE8R1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpSQE2%2FdJMcaf8xILo%2FVeoFhnwHhVyzHIgf2wE8R1%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;1396&quot; height=&quot;48&quot; data-filename=&quot;스크린샷 2026-08-05 오전 10.40.11.png&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Patch&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flag를 그리는 루틴을 분석하고 가려진 flag를 보이게 해야하는 문제이다. 내 생각에 내가 푼 방법은 좀 가라로 푼 것 같긴한데, 일단 작성해보겠다. 문제에 들어가기 앞서, 대부분의 드림핵 문제는 x86-64 아키텍처 기반의 문제들로 구성되어 있는데, 나의 환경은 M1칩이 탑재된 맥이기 때문에, 특히나 이 문제를 해결하는데 어려움을 겪었다. 푸는 방법은 알겠는데, 환경문제로 정답을 구하는 과정 자체가 어려웠달까.. 그래서 실제 정답을 찾아 내는건 AI에게 시뮬레이션으로 맡겨서 찾았음.&lt;/p&gt;
&lt;pre id=&quot;code_1785894291098&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  HCURSOR CursorW; // rax
  HWND Window; // rax
  HWND v8; // rbx
  HACCEL AcceleratorsW; // rbx
  WNDCLASSEXW v11; // [rsp+60h] [rbp-A8h] BYREF
  struct tagMSG Msg; // [rsp+B0h] [rbp-58h] BYREF

  LoadStringW(hInstance, uID: 0x67u, lpBuffer: &amp;amp;WindowName, cchBufferMax: 100);
  LoadStringW(hInstance, uID: 0x6Du, lpBuffer: &amp;amp;ClassName, cchBufferMax: 100);
  v11.cbSize = 80;
  v11.style = 3;
  v11.lpfnWndProc = (WNDPROC)sub_1400032F0;
  *(_QWORD *)&amp;amp;v11.cbClsExtra = 0;
  v11.hInstance = hInstance;
  v11.hIcon = LoadIconW(hInstance, lpIconName: (LPCWSTR)0x6B);
  CursorW = LoadCursorW(hInstance: nullptr, lpCursorName: (LPCWSTR)0x7F00);
  *(__m128i *)&amp;amp;v11.hbrBackground = _mm_load_si128((const __m128i *)&amp;amp;xmmword_1400053F0);
  v11.hCursor = CursorW;
  v11.lpszClassName = &amp;amp;ClassName;
  v11.hIconSm = LoadIconW(hInstance, lpIconName: (LPCWSTR)0x6C);
  RegisterClassExW(a1: &amp;amp;v11);
  qword_140007880 = (__int64)&amp;amp;unk_1400078A0;
  Window = CreateWindowExW(
             dwExStyle: 0,
             lpClassName: &amp;amp;ClassName,
             lpWindowName: &amp;amp;WindowName,
             dwStyle: 0xC80000u,
             X: 0x80000000,
             Y: 0,
             nWidth: 600,
             nHeight: 200,
             hWndParent: nullptr,
             hMenu: nullptr,
             hInstance,
             lpParam: nullptr);
  v8 = Window;
  if ( Window != nullptr )
  {
    hWnd = Window;
    dword_140007920 = 600;
    dword_140007924 = 200;
    GdiplusStartup(a1: &amp;amp;unk_1400078A0, a2: &amp;amp;dword_1400078A8, a3: 0);
    ShowWindow(hWnd: v8, nCmdShow: nShowCmd);
    UpdateWindow(hWnd: v8);
    AcceleratorsW = LoadAcceleratorsW(hInstance, lpTableName: (LPCWSTR)0x6D);
    while ( GetMessageW(lpMsg: &amp;amp;Msg, hWnd: nullptr, wMsgFilterMin: 0, wMsgFilterMax: 0) )
    {
      if ( TranslateAcceleratorW(hWnd: Msg.hwnd, hAccTable: AcceleratorsW, lpMsg: &amp;amp;Msg) == 0 )
      {
        TranslateMessage(lpMsg: &amp;amp;Msg);
        DispatchMessageW(lpMsg: &amp;amp;Msg);
      }
    }
    LODWORD(Window) = Msg.wParam;
  }
  return (int)Window;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 main 함수의 구조인데, 생각보다 꽤 복잡하다. 완벽히 해석은 못했지만, 자세히 보면, 여러 객체(windows 시스템 라이브러리 객체란다)로 이루어져있고, 문제 설명으로 유추해보면, 뭔가를 그리는게 프로그램인 것 같다.(맥이라서 문제 프로그램을 실행 못시켜봄)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숨겨진 플래그를 찾아라 -&amp;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. 그렇다면 뭔가 그리는 역할을 하는 듯한 객체나 함수가 있어야 할 텐데, 그게 뭘까? -&amp;gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_1400032F0 함수가 수상하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그렇다면 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_1400032F0의 구조를 살펴보자&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1785894675481&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;LRESULT __fastcall sub_1400032F0(HWND a1, UINT a2, WPARAM a3, LPARAM a4)
{
  _QWORD *v5; // rbx
  __int64 v6; // rbx
  __int64 v7; // [rsp+20h] [rbp-18h] BYREF

  switch ( a2 )
  {
    case 2u:
      PostQuitMessage(nExitCode: 0);
      return 0;
    case 0xFu:
      qword_140007910 = (__int64)BeginPaint(hWnd: hWnd, lpPaint: &amp;amp;Paint);
      v5 = (_QWORD *)GdipAlloc(a1: 16);
      if ( v5 != nullptr )
      {
        *v5 = 0;
        v5[1] = 0;
        v7 = 0;
        *((_DWORD *)v5 + 2) = GdipCreateFromHDC(a1: qword_140007910, a2: &amp;amp;v7);
        *v5 = v7;
      }
      else
      {
        v5 = nullptr;
      }
      qword_140007918 = (__int64)v5;
      sub_140002C40();
      v6 = qword_140007918;
      if ( qword_140007918 != 0 )
      {
        GdipDeleteGraphics(a1: *(_QWORD *)qword_140007918);
        GdipFree(a1: v6);
      }
      EndPaint(hWnd: hWnd, lpPaint: &amp;amp;Paint);
      return 0;
    case 0x202u:
      InvalidateRect(hWnd: hWnd, lpRect: nullptr, bErase: true);
      UpdateWindow(hWnd: hWnd);
      return 0;
    default:
      return DefWindowProcW(hWnd: a1, Msg: a2, wParam: a3, lParam: a4);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2.여기서도 뭔가를 그리는 객체나 함수가 없는 듯한데, 대놓고 중간에 있는 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_140002C40()가 너무 수상했음 -&amp;gt; 바로 분석&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1785894777633&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char __fastcall sub_140002C40(__int64 a1, int a2)
{
  int v2; // ebx
  int v3; // edx
  int v4; // edx
  int v5; // edx
  int v6; // edx
  int v7; // edx
  int v8; // edx
  int v9; // edx
  int v10; // edx
  int v11; // edx
  int v12; // edx
  int v13; // edx
  int v14; // edx
  int v15; // edx
  int v16; // edx
  int v17; // edx
  int v18; // edx
  int v19; // edx
  int v20; // edx
  int v21; // edx
  int v22; // edx
  int v23; // edx
  int v24; // edx
  int v25; // edx
  int v26; // edx
  __int64 v27; // rbx
  __int64 v28; // r8
  __int64 v29; // r8
  __int64 v30; // rdx
  __int64 v31; // r8
  __int64 v32; // rdx
  __int64 v33; // r8
  __int64 v34; // rdx
  __int64 v35; // r8
  __int64 v36; // rdx
  __int64 v37; // r8
  __int64 v38; // rdx
  __int64 v39; // r8
  __int64 v40; // rdx
  __int64 v41; // r8
  __int64 v42; // r8
  __int64 v43; // rdx
  __int64 v44; // r8
  __int64 v45; // r8
  __int64 v46; // rdx
  __int64 v47; // r8

  v2 = qword_140007880;
  sub_140002B80(a1: qword_140007880, a2, a3: 30, a4: 470, a5: 80, a6: -16777216);
  sub_140002B80(a1: v2, a2: v3, a3: 35, a4: 470, a5: 75, a6: -16777216);
  sub_140002B80(a1: v2, a2: v4, a3: 40, a4: 470, a5: 70, a6: -16777216);
  sub_140002B80(a1: v2, a2: v5, a3: 45, a4: 470, a5: 65, a6: -16777216);
  sub_140002B80(a1: v2, a2: v6, a3: 50, a4: 470, a5: 60, a6: -16777216);
  sub_140002B80(a1: v2, a2: v7, a3: 55, a4: 470, a5: 55, a6: -16777216);
  sub_140002B80(a1: v2, a2: v8, a3: 60, a4: 470, a5: 50, a6: -16777216);
  sub_140002B80(a1: v2, a2: v9, a3: 65, a4: 470, a5: 45, a6: -16777216);
  sub_140002B80(a1: v2, a2: v10, a3: 70, a4: 470, a5: 40, a6: -16777216);
  sub_140002B80(a1: v2, a2: v11, a3: 75, a4: 470, a5: 75, a6: -16777216);
  sub_140002B80(a1: v2, a2: v12, a3: 80, a4: 400, a5: 60, a6: -16777216);
  sub_140002B80(a1: v2, a2: v13, a3: 30, a4: 470, a5: 90, a6: -16777216);
  sub_140002B80(a1: v2, a2: v14, a3: 35, a4: 470, a5: 30, a6: -16777216);
  sub_140002B80(a1: v2, a2: v15, a3: 40, a4: 470, a5: 35, a6: -16777216);
  sub_140002B80(a1: v2, a2: v16, a3: 45, a4: 470, a5: 50, a6: -16777216);
  sub_140002B80(a1: v2, a2: v17, a3: 50, a4: 470, a5: 40, a6: -16777216);
  sub_140002B80(a1: v2, a2: v18, a3: 55, a4: 400, a5: 90, a6: -16777216);
  sub_140002B80(a1: v2, a2: v19, a3: 60, a4: 470, a5: 60, a6: -16777216);
  sub_140002B80(a1: v2, a2: v20, a3: 65, a4: 470, a5: 30, a6: -16777216);
  sub_140002B80(a1: v2, a2: v21, a3: 70, a4: 470, a5: 80, a6: -16777216);
  sub_140002B80(a1: v2, a2: v22, a3: 75, a4: 470, a5: 70, a6: -16777216);
  sub_140002B80(a1: v2, a2: v23, a3: 80, a4: 470, a5: 60, a6: -16777216);
  sub_140002B80(a1: v2, a2: v24, a3: 80, a4: 470, a5: 80, a6: -16777216);
  sub_140002B80(a1: v2, a2: v25, a3: 80, a4: 470, a5: 70, a6: -16777216);
  sub_140002B80(a1: v2, a2: v26, a3: 90, a4: 470, a5: 90, a6: -16777216);
  v27 = qword_140007880;
  sub_1400017A0(a1: qword_140007880, a2: 40, a3: v28, a4: 4278190080LL);
  sub_140001C80(a1: v27, a2: 80, a3: v29, a4: 4278190080LL);
  sub_140002640(a1: v27, a2: v30, a3: v31, a4: 4278190080LL);
  sub_1400020F0(a1: v27, a2: v32, a3: v33, a4: 4278190080LL);
  sub_140002390(a1: v27, a2: v34, a3: v35, a4: 4278190080LL);
  sub_140001240(a1: v27, a2: v36, a3: v37, a4: 4278190080LL);
  sub_140001F20(a1: v27, a2: v38, a3: v39, a4: 4278190080LL);
  sub_140001560(a1: v27, a2: v40, a3: v41, a4: 4278190080LL);
  sub_140001C80(a1: v27, a2: 360, a3: v42, a4: 4278190080LL);
  sub_1400019D0(a1: v27, a2: v43, a3: v44, a4: 4278190080LL);
  sub_1400017A0(a1: v27, a2: 440, a3: v45, a4: 4278190080LL);
  sub_140002870(a1: v27, a2: v46, a3: v47, a4: 4278190080LL);
  return 0;
}&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;3. 와..동일한 함수가 24번 반복되고, 밑에 12개의 또 다른 함수가 있다. 여기서 느낌이 왔다. 뭔가 있구나. 그래서 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_140002B80&lt;span&gt;의 내부를 살펴봤다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1785894846351&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;__int64 __fastcall sub_140002B80(__int64 a1, __int64 a2, unsigned int a3, int a4, int a5, unsigned int a6)
{
  int v9; // eax
  __int64 v10; // rsi
  int v11; // eax
  __int64 v12; // rbx
  int v13; // eax
  __int64 v15; // [rsp+30h] [rbp-38h] BYREF
  __int64 v16; // [rsp+38h] [rbp-30h]

  v16 = 0;
  v15 = 0;
  v9 = GdipCreatePen1(a1: a6, a2, a3: 0, a4: &amp;amp;v15);
  v10 = *(_QWORD *)(a1 + 120);
  LODWORD(v16) = v9;
  v11 = GdipDrawLineI(a1: *(_QWORD *)v10, a2: v15, a3: 150, a4: a3, a5: a4, a6: a5);
  if ( v11 != 0 )
    *(_DWORD *)(v10 + 8) = v11;
  v12 = *(_QWORD *)(a1 + 120);
  v13 = GdipSetSmoothingMode(a1: *(_QWORD *)v12, a2: 4);
  if ( v13 != 0 )
    *(_DWORD *)(v12 + 8) = v13;
  return GdipDeletePen(a1: v15);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 중간에 &quot;GdipDrawLineI&quot;가 그리는 역할을 하는걸로 추정되는 함수를 발견했다. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_1400017A0&lt;/span&gt; 등 12개의 함수 내부에도 같은 함수가 있는걸 확인했다. -&amp;gt; 12개의 함수가 플래그를 그리고, 그 위에 24번 반복하는 함수로 덮어서 가려놨다고 추정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;sub_140002B80 내부의 &quot;GdipDrawLineI&quot; 부분을 커서로 선택하고 tab을 눌러서, 어셈블리에서 위치를 찾아내어 NOP로 값을 수정해서 무력화해서 해결했다. -&amp;gt; 플래그는 DH{UPATCHED}였다.&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; text-align: start;&quot;&gt;내가 이 문제를 해결하는 과정을 정리해봤는데, 이렇게 푸는게 맞는지는 잘 모르겠다. 그런데, 만약 내가 진짜 해커이고 처음 본 프로그램을 리버싱하는 상황이라면 이런 방식으로 접근하지 않았을까라는 생각을 해본다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;썩어가는 정신과 건강해지는 몸&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;요즘 운동은 열심히 해서 몸은 건강해지고 있는데, 방학이라 그런가 한달을 통으로 날렸다... 실시간으로 정신이 썩어가는 기분을 느끼고 있음. 졸업이 1년 반정도 남았는데, 이제 보안 공부를 시작했으니 열심히 해야지...드림핵 유료 결제를 몇달 간 해볼까 고민 중이다.&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&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-filename=&quot;피할수.jpg&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bypVi6/dJMcaazwyh0/KQ2kXTnGtZ08TdlicbzKHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bypVi6/dJMcaazwyh0/KQ2kXTnGtZ08TdlicbzKHk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bypVi6/dJMcaazwyh0/KQ2kXTnGtZ08TdlicbzKHk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbypVi6%2FdJMcaazwyh0%2FKQ2kXTnGtZ08TdlicbzKHk%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;480&quot; height=&quot;360&quot; data-filename=&quot;피할수.jpg&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;360&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>write-up</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/2</guid>
      <comments>https://commanderjjm.tistory.com/2#entry2comment</comments>
      <pubDate>Wed, 5 Aug 2026 11:15:23 +0900</pubDate>
    </item>
    <item>
      <title>리버싱(reversing)과 rev-basic-0</title>
      <link>https://commanderjjm.tistory.com/1</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 계기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;6월에는 유럽의 여름을 체험하더니, 요즘은 기상관측 역사상 최고의 더위를 찍는(94년보다 더 덥다고함) 국장 같은 요즘 날씨에 살기 너무 힘들다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;무잔.jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r7KGe/dJMcaijX0cK/acgo74c06jK4yLkjnv3Lg1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r7KGe/dJMcaijX0cK/acgo74c06jK4yLkjnv3Lg1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r7KGe/dJMcaijX0cK/acgo74c06jK4yLkjnv3Lg1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr7KGe%2FdJMcaijX0cK%2Facgo74c06jK4yLkjnv3Lg1%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;800&quot; height=&quot;420&quot; data-filename=&quot;무잔.jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3학년 여름방학, 계속 진로 고민을 해오던 내게 더 이상 물러날 곳이 없어진 기분이다. 여러 진로를 고민만하는 것보단 일단 가장 끌리는 분야에 박치기를 해보기로했다. 그래서 우리 학교 최고의 보안 동아리에 들어가게 되었고, 보안 공부를 시작하기로 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFlyUc/dJMcajpv4NX/Tm4fX08y6ccyeiN7n4oeZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFlyUc/dJMcajpv4NX/Tm4fX08y6ccyeiN7n4oeZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFlyUc/dJMcajpv4NX/Tm4fX08y6ccyeiN7n4oeZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFlyUc%2FdJMcajpv4NX%2FTm4fX08y6ccyeiN7n4oeZ1%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;666&quot; height=&quot;694&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;보안 공부를 막 시작한 내가 어떤 자료로 공부를 할지 방황하고 있어서, 동아리 회장형이 제게 리버싱을 공부해보라며 과제를 줬다. Dreamhack에 있는 rev-basic-0~7까지 풀어보고, 공부한 과정을 블로그로 정리하는 것이 과제라서 블로그를 시작했다. 이 과제를 끝내고 나면, Dreamhack Pro 요금제를 결제해서 열심히 해볼까 생각 중이다.(좀 비싸요..)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 리버싱(reversing)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;리버싱, reverse engineering&lt;/b&gt;이라고도 불리는 이 작업은 완성된 결과물을 분석해서, 내부 동작 원리나 구조를 알아내는 작업을 말한다.&lt;br /&gt;보안 분야에 한정된 리버싱은 소프트웨어의 실행파일을 분석하여 내부 로직을 파악하는 과정을 말하게 돼요. 저는 이 과정에 IDA를 이용하여 두 가지 도구를 이용하여 리버싱을 진행했다.&lt;br /&gt;&lt;br /&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;디컴파일러: 어셈블리어를 C와 유사한 의사코드로 복원해주는 도구(F5 키를 이용해 실행 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. rev-basic-0&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpHXlh/dJMcadCN4jJ/VoeDVbuM6hkBQPUycMvUC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpHXlh/dJMcadCN4jJ/VoeDVbuM6hkBQPUycMvUC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpHXlh/dJMcadCN4jJ/VoeDVbuM6hkBQPUycMvUC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpHXlh%2FdJMcadCN4jJ%2FVoeDVbuM6hkBQPUycMvUC1%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;1452&quot; height=&quot;584&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;첨부 파일을 다운 받고, IDA를 통해 해당 파일을 열어보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kBhSx/dJMcafU7uPH/qKewk8gq4MimEvky3uuSg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kBhSx/dJMcafU7uPH/qKewk8gq4MimEvky3uuSg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kBhSx/dJMcafU7uPH/qKewk8gq4MimEvky3uuSg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkBhSx%2FdJMcafU7uPH%2FqKewk8gq4MimEvky3uuSg1%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;2880&quot; height=&quot;1800&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다운받은 파일을 디어셈블러가 어셈블리어로 변환하고 그래프 형태로 보여주는 화면이 나온다. 이 화면에서 F5를 눌러 디컴파일러를 실행하면 아래와 같은 화면이 나온다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC3ifJ/dJMcag7tcEY/JKbdep5VHOGQvOfN8lyRP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC3ifJ/dJMcag7tcEY/JKbdep5VHOGQvOfN8lyRP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC3ifJ/dJMcag7tcEY/JKbdep5VHOGQvOfN8lyRP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC3ifJ%2FdJMcag7tcEY%2FJKbdep5VHOGQvOfN8lyRP0%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;2880&quot; height=&quot;1800&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;256의 버퍼 크기를 가지는 v4를 모두 0으로 초기화한다.&lt;/li&gt;
&lt;li&gt;sub_140...1190 함수(이는 함수 이름을 모르기 때문에 ida가 임의로 붙인 함수명이라고한다)를 통해 입력값을 프롬프트에 그대로 출력한다.&lt;/li&gt;
&lt;li&gt;sub_140...11F0은 v4에 값을 입력받는 함수이다.&lt;/li&gt;
&lt;li&gt;sub_140...1000의 결과값이 0이 아니면 &quot;Correct&quot;, 0이면 &quot;Wrong&quot;을 출력한다. 이 부분이 문제의 핵심 지점이 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;correct를 출력하는 입력값을 찾아야 하므로, sub_140...1000의 내부 구조를 파악해보면 될 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xAaap/dJMb998mv2h/o0kmK0s5WCi3LOKiN7pTc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xAaap/dJMb998mv2h/o0kmK0s5WCi3LOKiN7pTc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xAaap/dJMb998mv2h/o0kmK0s5WCi3LOKiN7pTc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxAaap%2FdJMb998mv2h%2Fo0kmK0s5WCi3LOKiN7pTc1%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;2880&quot; height=&quot;1800&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 sub_140...1000의 함수 내부 구조이다. 매우 간단한 구조인데, 입력값과 str2, 즉 &quot;Compar3_the_str1ng&quot;가 같은지 비교하여 참 거짓을 판별하는 함수였다.(strcmp는 두 문자열이 같으면 0을 출력한다)&amp;nbsp;&lt;br /&gt;두 문자열이 같으면, 0이 출력되고, 이는 뒤의 조건식을 만족하므로, return 값이 1이 나오게 되며, 이는 &quot;Correct&quot;를 출력하게 하는 값이 된다.&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;p data-ke-size=&quot;size16&quot;&gt;DH{Compar3_the_str1ng}이다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>write-up</category>
      <author>commanderjjm</author>
      <guid isPermaLink="true">https://commanderjjm.tistory.com/1</guid>
      <comments>https://commanderjjm.tistory.com/1#entry1comment</comments>
      <pubDate>Mon, 3 Aug 2026 11:52:02 +0900</pubDate>
    </item>
  </channel>
</rss>