<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>포렌식 &amp;amp; 개발 이야기  - Forensics &amp;amp; Development</title>
    <link>https://pental.tistory.com/</link>
    <description>Pental - Forensics / iOS / Windows / Android / Kakaotalk / Telegram / Etc</description>
    <language>ko</language>
    <pubDate>Mon, 25 May 2026 17:04:35 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>pental</managingEditor>
    <image>
      <title>포렌식 &amp;amp; 개발 이야기  - Forensics &amp;amp; Development</title>
      <url>https://tistory1.daumcdn.net/tistory/2794575/attach/4b05676c166f43a29cc55817a9471dd5</url>
      <link>https://pental.tistory.com</link>
    </image>
    <item>
      <title>인터넷이 안되는 시골집에 CCTV 설치하기</title>
      <link>https://pental.tistory.com/600</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;때는 2025년 초쯤, 시골에 계시는 할아버지집 뿐만 아니라 근처에서 큰 불이 발생하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l1zon/dJMcai4ccGT/2tyRPMXScT0bHUq3Y58MWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l1zon/dJMcai4ccGT/2tyRPMXScT0bHUq3Y58MWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l1zon/dJMcai4ccGT/2tyRPMXScT0bHUq3Y58MWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl1zon%2FdJMcai4ccGT%2F2tyRPMXScT0bHUq3Y58MWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1154&quot; height=&quot;454&quot; data-origin-width=&quot;1154&quot; data-origin-height=&quot;454&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 통신망이 끊겨서 전화조차 터지지 않는 상황,,, 그래서 무슨일 없는지 확인할 수도 없는 상황이라, 근처 지구대에 연락해서 피해상황이 어떤지 등을 확인했던 기억이 있어서 26년 초쯤 CCTV를 설치하기로 협의하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 해당 시골집(친가, 외가)에는 기지국은 설치되어 있지만, 할아버지, 할머니가 인터넷을 사용하지 않는 폴더폰이기에 인터넷망을 구축하기에 월 비용 부담이 조금 크다. (100mb라고 해도 월 2만원대가 기본이기 때문이다..)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1209&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r0Yfu/dJMcacXf7VI/DwKr77UXnadAY0oPBqkt81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r0Yfu/dJMcacXf7VI/DwKr77UXnadAY0oPBqkt81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r0Yfu/dJMcacXf7VI/DwKr77UXnadAY0oPBqkt81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr0Yfu%2FdJMcacXf7VI%2FDwKr77UXnadAY0oPBqkt81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1209&quot; height=&quot;187&quot; data-origin-width=&quot;1209&quot; data-origin-height=&quot;187&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 두집에 모두 인터넷 라인을 깔게 되면 월 4.4만원이라는 부담이 생기게 되는것이다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이 방법을 어떻게 파훼할까 해서 LTE CCTV등을 알아 보았고, 알리에서 LTE CCTV를 파는 것을 확인해서 바로 주문했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(본 글은 두집에 설치한 내용이 짬뽕되어 있기 때문에 복잡할 수 있다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLZKSW/dJMcahxwJxc/ORPkyacqk5piMfrwFkHLY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLZKSW/dJMcahxwJxc/ORPkyacqk5piMfrwFkHLY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLZKSW/dJMcahxwJxc/ORPkyacqk5piMfrwFkHLY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLZKSW%2FdJMcahxwJxc%2FORPkyacqk5piMfrwFkHLY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;994&quot; height=&quot;268&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3U64Y/dJMcaffq7kB/BT6ZMuaBKumKOUi1Yvblbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3U64Y/dJMcaffq7kB/BT6ZMuaBKumKOUi1Yvblbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3U64Y/dJMcaffq7kB/BT6ZMuaBKumKOUi1Yvblbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3U64Y%2FdJMcaffq7kB%2FBT6ZMuaBKumKOUi1Yvblbk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1237&quot; height=&quot;549&quot; data-origin-width=&quot;1237&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 5월 기준으로 현재는 5만원 미만으로 살수 있다. 해당 제품을 구입해서 유심을 개통했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X4Fq5/dJMcabxg0ST/6uo6H0e9kEjmsIVB8RqGP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X4Fq5/dJMcabxg0ST/6uo6H0e9kEjmsIVB8RqGP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X4Fq5/dJMcabxg0ST/6uo6H0e9kEjmsIVB8RqGP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX4Fq5%2FdJMcabxg0ST%2F6uo6H0e9kEjmsIVB8RqGP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1179&quot; height=&quot;1428&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1179&quot; data-origin-height=&quot;1428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 5회선을 사용하고 있다. 데이터 함께쓰기 요금제로 월 5천원씩 2회선 총 1만원씩 부과되고 이렇게 되면 두집 인터넷 설치 4.4만원보다 3.4만원을 아낀셈이 된것이다. (ESIM 회선도 1개 쓰고 있다, 1회선은 라우터용, 그리고 3회선 전화번호는 나도 모른다..)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;EDC9B426-ED94-489C-83D4-B0378C03A035_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yIvG2/dJMcagk3rbj/KlG2VNUAv11JE4875ATA91/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yIvG2/dJMcagk3rbj/KlG2VNUAv11JE4875ATA91/img.jpg&quot; data-alt=&quot;2026년 2월&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yIvG2/dJMcagk3rbj/KlG2VNUAv11JE4875ATA91/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyIvG2%2FdJMcagk3rbj%2FKlG2VNUAv11JE4875ATA91%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-filename=&quot;EDC9B426-ED94-489C-83D4-B0378C03A035_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2026년 2월&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2D87D527-5DB6-4999-97CD-890A78C7845D_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l5JWz/dJMcafzIbmc/qAAd7Cir1KS7f0FU3Xkzak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l5JWz/dJMcafzIbmc/qAAd7Cir1KS7f0FU3Xkzak/img.jpg&quot; data-alt=&quot;2026년 4월&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l5JWz/dJMcafzIbmc/qAAd7Cir1KS7f0FU3Xkzak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl5JWz%2FdJMcafzIbmc%2FqAAd7Cir1KS7f0FU3Xkzak%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-filename=&quot;2D87D527-5DB6-4999-97CD-890A78C7845D_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2026년 4월&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대리점에 들려서 USIM 발급을 받으려는데 회선이 너무 많아서 &quot;심사 부적격&quot; 판정을 받았지만 어찌저찌 우회해서 발급이 됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 0청년 69요금제로 160GB 요금제를 사용하고 있는데, 카메라에서 사용되는 데이터는 달에 대략 2GB안팍이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(클라우드 서비스를 사용하지 않고, SD카드에 저장하는 방식을 사용함)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2E24B7F6-F573-46D1-8DDD-562BB29048BD_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ReO0h/dJMcadPlYtb/l8FY6beRvP3300LtOwaTeK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ReO0h/dJMcadPlYtb/l8FY6beRvP3300LtOwaTeK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ReO0h/dJMcadPlYtb/l8FY6beRvP3300LtOwaTeK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FReO0h%2FdJMcadPlYtb%2Fl8FY6beRvP3300LtOwaTeK%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-filename=&quot;2E24B7F6-F573-46D1-8DDD-562BB29048BD_1_105_c.jpeg&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폭력적으로 생긴 CCTV에 USIM을 끼워놓고 작동시키면 끝난다. 따로 APN 설정을 하지 않아도 알아서 잡아준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태양광으로도 충전이 가능하다고는 하는데 설치가 귀찮으니 패스 하고, 그냥 쿠팡에서 5M짜리 충전선을 구입해서 장착했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9OzaK/dJMcac30Xwz/cXfbviz34qfZAWygDmwIPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9OzaK/dJMcac30Xwz/cXfbviz34qfZAWygDmwIPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9OzaK/dJMcac30Xwz/cXfbviz34qfZAWygDmwIPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9OzaK%2FdJMcac30Xwz%2FcXfbviz34qfZAWygDmwIPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;792&quot; height=&quot;255&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 5m도 충분했다. 3m사도 됐을듯,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 위 글까지는 자체 LTE모듈이 들어 있는 카메라에 대한 내용이고, 아래는 외가댁에 설치한 LTE 라우터를 이용한 CCTV 설치이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eGX5k5/dJMcadV8W37/kRwwGAGXoydbasUegNSbKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eGX5k5/dJMcadV8W37/kRwwGAGXoydbasUegNSbKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eGX5k5/dJMcadV8W37/kRwwGAGXoydbasUegNSbKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeGX5k5%2FdJMcadV8W37%2FkRwwGAGXoydbasUegNSbKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;247&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czX2ax/dJMcadV8W4b/K8dTdkMEuFKjTwNCuNdxgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czX2ax/dJMcadV8W4b/K8dTdkMEuFKjTwNCuNdxgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czX2ax/dJMcadV8W4b/K8dTdkMEuFKjTwNCuNdxgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczX2ax%2FdJMcadV8W4b%2FK8dTdkMEuFKjTwNCuNdxgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;944&quot; height=&quot;251&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외가댁에는 거실 + 현관을 찍기 위해서 LTE 라우터도 하나 구입하였고, 2대를 연결한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYnif/dJMcadPlYyX/3k8HOYAdLonB2CyKocWgb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYnif/dJMcadPlYyX/3k8HOYAdLonB2CyKocWgb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYnif/dJMcadPlYyX/3k8HOYAdLonB2CyKocWgb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYnif%2FdJMcadPlYyX%2F3k8HOYAdLonB2CyKocWgb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;634&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 드릴로 뚫고 설치하고 얘도 태양광을 달기에는 영 못미더워서 그냥 DC 5V로 연결했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PIEij/dJMcaiiSapx/7W53mga9kDMrNPGTvVI1Ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PIEij/dJMcaiiSapx/7W53mga9kDMrNPGTvVI1Ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PIEij/dJMcaiiSapx/7W53mga9kDMrNPGTvVI1Ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPIEij%2FdJMcaiiSapx%2F7W53mga9kDMrNPGTvVI1Ek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;1306&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1BT8p/dJMcadBNkiE/88Fz6sYtjgMqrA4KHorb91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1BT8p/dJMcadBNkiE/88Fz6sYtjgMqrA4KHorb91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1BT8p/dJMcadBNkiE/88Fz6sYtjgMqrA4KHorb91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1BT8p%2FdJMcadBNkiE%2F88Fz6sYtjgMqrA4KHorb91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;1306&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굉장히 만족스럽게 잘 장착되었고, 잘 작동한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 끝.&lt;/p&gt;</description>
      <category>이것저것</category>
      <category>CCTV</category>
      <category>CCTV 설치</category>
      <category>LTE CCTV</category>
      <category>시골집 CCTV</category>
      <category>인터넷 없이 CCTV</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/600</guid>
      <comments>https://pental.tistory.com/600#entry600comment</comments>
      <pubDate>Sun, 3 May 2026 00:33:10 +0900</pubDate>
    </item>
    <item>
      <title>[2025 DFC] 2025 디지털포렌식 챌린지 - 301 - 404 VMK Not Found</title>
      <link>https://pental.tistory.com/599</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Step-by-step methodology:&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제풀이에 앞서&lt;span&gt; MD5 &lt;/span&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;299&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qvQD1/dJMcab4YL4N/dMC2oZCbb8Ibp7rGfF8gP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qvQD1/dJMcab4YL4N/dMC2oZCbb8Ibp7rGfF8gP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qvQD1/dJMcab4YL4N/dMC2oZCbb8Ibp7rGfF8gP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqvQD1%2FdJMcab4YL4N%2FdMC2oZCbb8Ibp7rGfF8gP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;299&quot; height=&quot;192&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Mem_files.zip &lt;/span&gt;파일 해시 검증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서 주어진 &lt;span&gt;Mem_files.zip&lt;/span&gt;의&lt;span&gt; MD5 &lt;/span&gt;해시값이 &lt;span&gt;C488FB533376039D5345F19E65C4D190&lt;/span&gt;과 동일한것을 확인했다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서 주어진 이미지 파일인&lt;span&gt; diskimg &lt;/span&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;306&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5Ybtn/dJMcadaBfmB/ORhnzACHhZipYf9kcWnqH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5Ybtn/dJMcadaBfmB/ORhnzACHhZipYf9kcWnqH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5Ybtn/dJMcadaBfmB/ORhnzACHhZipYf9kcWnqH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5Ybtn%2FdJMcadaBfmB%2FORhnzACHhZipYf9kcWnqH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;306&quot; height=&quot;125&quot; data-origin-width=&quot;306&quot; data-origin-height=&quot;125&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; diskimg &lt;/span&gt;파일의 해시 정보&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;File Name&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;diskimg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;File Size&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;1,048,576,000 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;2D1560610DF4AF997A00D3882E4DFDF5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SHA1&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;A743E5447280DF0210B09543B044EC423ACF55D1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; diskimg &lt;/span&gt;파일의 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 파일을&lt;span&gt; HxD&lt;/span&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;328&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1oQ0B/dJMcagZvopD/7u9DSUCtehCZff2ua6ia7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1oQ0B/dJMcagZvopD/7u9DSUCtehCZff2ua6ia7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1oQ0B/dJMcagZvopD/7u9DSUCtehCZff2ua6ia7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1oQ0B%2FdJMcagZvopD%2F7u9DSUCtehCZff2ua6ia7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;328&quot; height=&quot;302&quot; data-origin-width=&quot;328&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; HxD&lt;/span&gt;를 통해 확인한&lt;span&gt; diskimg &lt;/span&gt;파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;br /&gt;HxD&lt;/span&gt;를 통해 확인한 결과&lt;span&gt;, FVE-FS &lt;/span&gt;라는 시그니처를 확인 할 수 있으며&lt;span&gt;, &lt;/span&gt;이는&lt;span&gt; BitLocker &lt;/span&gt;암호화 볼륨의 메타데이터 시그니처이다&lt;span&gt;. BitLocker&lt;/span&gt;로 보호되는 드라이브의 시작 부분&lt;span&gt;(&lt;/span&gt;메타데이터 영역&lt;span&gt;)&lt;/span&gt;에 기록되는 특징을 가지고 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;diskimg &lt;/span&gt;파일을 인식시키기 위해 아스날 이미지 마운터를 사용하였으며 아래는 &lt;span&gt;diskimg&lt;/span&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;453&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqSK4i/dJMcaipvXMm/me82K9zdtfGhUgO65keO9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqSK4i/dJMcaipvXMm/me82K9zdtfGhUgO65keO9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqSK4i/dJMcaipvXMm/me82K9zdtfGhUgO65keO9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqSK4i%2FdJMcaipvXMm%2Fme82K9zdtfGhUgO65keO9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;232&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ARSENAL IMAGE MOUNTER&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;453&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MnuiF/dJMcaipvXMp/OK70jHMtKWQcKFha9u6FPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MnuiF/dJMcaipvXMp/OK70jHMtKWQcKFha9u6FPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MnuiF/dJMcaipvXMp/OK70jHMtKWQcKFha9u6FPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMnuiF%2FdJMcaipvXMp%2FOK70jHMtKWQcKFha9u6FPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;273&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ARSENAL IMAGE MOUNTER&lt;/span&gt;의 실행화면&lt;span&gt;&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;453&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kXrca/dJMcaipvXMs/Cb72HA0jRcFoKmLLOl3dT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kXrca/dJMcaipvXMs/Cb72HA0jRcFoKmLLOl3dT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kXrca/dJMcaipvXMs/Cb72HA0jRcFoKmLLOl3dT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkXrca%2FdJMcaipvXMs%2FCb72HA0jRcFoKmLLOl3dT1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;251&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; diskimg &lt;/span&gt;파일을 탑재한 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아스날 이미지 마운터&lt;span&gt; (ARSENAL IMAGE MOUNTER)&lt;/span&gt;을 통해&lt;span&gt; diskimg&lt;/span&gt;를 탑재 후 파일 탐색기를 통해 이미지가 정상적으로 마운트 된 것을 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&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;173&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WAaIZ/dJMcagZvopJ/WMY8iUKayu4TuDY97ZOKZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WAaIZ/dJMcagZvopJ/WMY8iUKayu4TuDY97ZOKZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WAaIZ/dJMcagZvopJ/WMY8iUKayu4TuDY97ZOKZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWAaIZ%2FdJMcagZvopJ%2FWMY8iUKayu4TuDY97ZOKZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;173&quot; height=&quot;53&quot; data-origin-width=&quot;173&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&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;314&quot; data-origin-height=&quot;94&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFdOo0/dJMcaaZiyES/mkPkFMGcfVywjhyxKV3Qp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFdOo0/dJMcaaZiyES/mkPkFMGcfVywjhyxKV3Qp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFdOo0/dJMcaaZiyES/mkPkFMGcfVywjhyxKV3Qp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFdOo0%2FdJMcaaZiyES%2FmkPkFMGcfVywjhyxKV3Qp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;314&quot; height=&quot;94&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;94&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;디스크 우 클릭 후 메뉴 일부&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탑재한 결과 비트라커로 암호화된 디스크&lt;span&gt; 1&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;&lt;span&gt;Mem_files.zip &lt;/span&gt;파일을 압축 해제하면 다음 그림과 같이&lt;span&gt; 6&lt;/span&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;451&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/01coI/dJMcafGkraI/KNm2gZo9J1eziOS8q2ltyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/01coI/dJMcafGkraI/KNm2gZo9J1eziOS8q2ltyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/01coI/dJMcafGkraI/KNm2gZo9J1eziOS8q2ltyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F01coI%2FdJMcafGkraI%2FKNm2gZo9J1eziOS8q2ltyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;132&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Mem_files.zip&lt;/span&gt;의 압축해제 후 파일 목록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 파일은 메모리 덤프 파일이며 &lt;span&gt;cat &lt;/span&gt;명령어를 통해서&lt;span&gt; 6&lt;/span&gt;개로 나뉘어져 있는 파일을 모두 통합한다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;pental@pentalui-MacBookAir Mem_files % cat mempart00.bin mempart01.bin mempart02.bin mempart03.bin mempart04.bin mempart05.bin &amp;gt; memory.dmp&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;메모리 파일을 통합하기 위해 사용한 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비트라커&lt;span&gt;(BitLocker) &lt;/span&gt;복구키&lt;span&gt;(Recovery Key) &lt;/span&gt;는&lt;span&gt; Windows&lt;/span&gt;에서 드라이브 암호화를 해제하거나&lt;span&gt;, &lt;/span&gt;정상적인 인증 절차로는 접근할 수 없을 때 데이터를 복구하기 위해 사용하는 특수한&lt;span&gt; 48&lt;/span&gt;자리 숫자 암호이다&lt;span&gt;. &lt;/span&gt;복구키의 경우&lt;span&gt; 6&lt;/span&gt;자리 숫자가&lt;span&gt; 8&lt;/span&gt;개의 그룹 형태를 나타내고 있으며 예시는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;123456-123456-123456-123456-123456-123456-123456-123456&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비트라커 복구키의 예시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;합쳐진&lt;span&gt; memory &lt;/span&gt;덤프 파일에서 &lt;span&gt;strings &lt;/span&gt;및 정규식을 통해 &lt;span&gt;Bitlocker &lt;/span&gt;복구키와 관련된 증거를 확보한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;strings memory.dmp | grep -E &quot;[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}-[0-9]{6}&quot;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;정규식을 통한 복구키 파싱 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 명령을 수행한 결과 아래와 같은 복구키를 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;played by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;322839-683573-358259-411290-335368-358182-335566-709874 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;entifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;060896-522335-394207-442046-104115-373010-632456-443289 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;8FE0955C If the above identifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;322839-683573-358259-411290-335368-358182-335566-709874 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;To verify that this is the correct recovery key, compare the start of the following identifier with&lt;span&gt;&amp;nbsp; &lt;/span&gt;the identifier value displayed on your PC. Identifier:&lt;span&gt;&amp;nbsp; &lt;/span&gt;1088859C-680D-45C7-9376-7C228FE0955C If the above identifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;322839-683573-358259-411290-335368-358182-335566-709874 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BitLocker Drive Encryption recovery key To verify that this is the correct recovery key, compare the start of the following identifier with&lt;span&gt;&amp;nbsp; &lt;/span&gt;the identifier value displayed on your PC. Identifier:&lt;span&gt;&amp;nbsp; &lt;/span&gt;1088859C-680D-45C7-9376-7C228FE0955C If the above identifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;322839-683573-358259-411290-335368-358182-335566-709874 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BitLocker Drive Encryption recovery key To verify that this is the correct recovery key, compare the start of the following identifier with&lt;span&gt;&amp;nbsp; &lt;/span&gt;the identifier value displayed on your PC. Identifier:&lt;span&gt;&amp;nbsp; &lt;/span&gt;91442E6D-8B2B-42F0-84F7-A844A6C15290 If the above identifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;060896-522335-394207-442046-104115-373010-632456-443289 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your driv&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BitLocker Drive Encryption recovery key To verify that this is the correct recovery key, compare the start of the following identifier with&lt;span&gt;&amp;nbsp; &lt;/span&gt;the identifier value displayed on your PC. Identifier:&lt;span&gt;&amp;nbsp; &lt;/span&gt;1088859C-680D-45C7-9376-7C228FE0955C If the above identifier matches the one displayed by your PC, then use the following key to&lt;span&gt;&amp;nbsp; &lt;/span&gt;unlock your drive. Recovery Key:&lt;span&gt;&amp;nbsp; &lt;/span&gt;322839-683573-358259-411290-335368-358182-335566-709874 If the above identifier doesn't match the one displayed by your PC, then this isn't the right key&lt;span&gt;&amp;nbsp; &lt;/span&gt;to unlock your drive. Try another recovery key, or refer to &lt;a href=&quot;https://go.microsoft.com/fwlink/?LinkID=260589&quot;&gt;https://go.microsoft.com/fwlink/?LinkID=260589&lt;/a&gt; for&lt;span&gt;&amp;nbsp; &lt;/span&gt;additional assistance.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;표&lt;span&gt; 4&lt;/span&gt;의 실행 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 결과를 종합적으로 분석한 결과&lt;span&gt; 2&lt;/span&gt;개의 복구키를 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Identifier&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Recovery Key&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;1088859C-680D-45C7-9376-7C228FE0955C&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;322839-683573-358259-411290-335368-358182-335566-709874&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;91442E6D-8B2B-42F0-84F7-A844A6C15290&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;060896-522335-394207-442046-104115-373010-632456-443289&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&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;287&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9xoc3/dJMcagFfOa5/piYRGrviB2tKa9FWZZzdp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9xoc3/dJMcagFfOa5/piYRGrviB2tKa9FWZZzdp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9xoc3/dJMcagFfOa5/piYRGrviB2tKa9FWZZzdp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9xoc3%2FdJMcagFfOa5%2FpiYRGrviB2tKa9FWZZzdp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;287&quot; height=&quot;225&quot; data-origin-width=&quot;287&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비트라커 디스크 잠금 해제 과정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비트라커의 경우 드라이브 암호를 알지 못하는 경우 기타 옵션을 통해 복구키를 입력 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;287&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hs5WF/dJMcagFfOa7/lGsaP7jArDX7KyMrO3uV3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hs5WF/dJMcagFfOa7/lGsaP7jArDX7KyMrO3uV3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hs5WF/dJMcagFfOa7/lGsaP7jArDX7KyMrO3uV3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHs5WF%2FdJMcagFfOa7%2FlGsaP7jArDX7KyMrO3uV3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;287&quot; height=&quot;255&quot; data-origin-width=&quot;287&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;기타 옵션을 클릭 한 후 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복구 키 입력 버튼을 클릭하면 해당 디스크의 키&lt;span&gt; ID&lt;/span&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;366&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baa42y/dJMcagFfObm/XuFSRc2q9OBUCdJuzfc3Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baa42y/dJMcagFfObm/XuFSRc2q9OBUCdJuzfc3Q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baa42y/dJMcagFfObm/XuFSRc2q9OBUCdJuzfc3Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaa42y%2FdJMcagFfObm%2FXuFSRc2q9OBUCdJuzfc3Q0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;366&quot; height=&quot;225&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구 키 입력을 클릭 한 후 확인되는 식별자&lt;span&gt; ID&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림에서 확인 할 수 있듯이 키&lt;span&gt; ID&lt;/span&gt;가&lt;span&gt; 91442E6D&lt;/span&gt;임을 나타내고 있으며&lt;span&gt;, &lt;/span&gt;이 키는 메모리 덤프 파일에서 정규식을 통해 추출한 결과에서 동일한&lt;span&gt; 8&lt;/span&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;366&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebEskl/dJMcaaZiyF7/5dyrHHmqm9NvFodwHfCFc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebEskl/dJMcaaZiyF7/5dyrHHmqm9NvFodwHfCFc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebEskl/dJMcaaZiyF7/5dyrHHmqm9NvFodwHfCFc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebEskl%2FdJMcaaZiyF7%2F5dyrHHmqm9NvFodwHfCFc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;366&quot; height=&quot;225&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;추출한 복구키를 입력한 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 표&lt;span&gt; 6&lt;/span&gt;을 참고하여 &lt;b&gt;&lt;span&gt;91442E6D&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;키&lt;span&gt; ID&lt;/span&gt;를 가진&lt;span&gt; Recovery Key&lt;/span&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;451&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xsdIv/dJMcagkUkSx/PKxKShLHSku5HgEKKMa5oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xsdIv/dJMcagkUkSx/PKxKShLHSku5HgEKKMa5oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xsdIv/dJMcagkUkSx/PKxKShLHSku5HgEKKMa5oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxsdIv%2FdJMcagkUkSx%2FPKxKShLHSku5HgEKKMa5oK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;230&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비트라커가 해제된 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상적으로 비트라커가 해제되었으며 해당 디스크에서는&lt;span&gt; flag.txt &lt;/span&gt;파일을 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;flag.txt &lt;/span&gt;파일의 정보는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;File Name&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;flag.txt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;File Size&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;20 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;BDEA960F1BC2F21D8CF3579D44DD0FED&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SHA1&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;29492F034EDF0EFA5553305779752868C2989697&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; flag.txt &lt;/span&gt;파일 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 기본 프로그램인 메모장을 통해&lt;span&gt; flag.txt &lt;/span&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;356&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0W8Xb/dJMcaaZiyIq/WaAKXAcSBg2gpEchoaTY41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0W8Xb/dJMcaaZiyIq/WaAKXAcSBg2gpEchoaTY41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0W8Xb/dJMcaaZiyIq/WaAKXAcSBg2gpEchoaTY41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0W8Xb%2FdJMcaaZiyIq%2FWaAKXAcSBg2gpEchoaTY41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;177&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; flag.txt &lt;/span&gt;에 담겨져 있는 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Base64&lt;/span&gt;로 인코딩 된 결과를 확인 할 수 있으며 복호화 하기 위해서&lt;span&gt; base64decode.org &lt;/span&gt;온라인 도구를 사용하였다&lt;span&gt;. (&lt;a href=&quot;https://base64decode.org)&quot;&gt;https://base64decode.org)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;345&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/THwE6/dJMcahKUQCT/sK3O8mmN1Y3iWTG7RGJDtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/THwE6/dJMcahKUQCT/sK3O8mmN1Y3iWTG7RGJDtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/THwE6/dJMcahKUQCT/sK3O8mmN1Y3iWTG7RGJDtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTHwE6%2FdJMcahKUQCT%2FsK3O8mmN1Y3iWTG7RGJDtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;345&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;345&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;span&gt; base64 &lt;/span&gt;복호화 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복호화 결과&lt;span&gt; 200 Ok-DFC2025 &lt;/span&gt;라는 값을 얻을 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답&lt;span&gt; : 200 Ok-DFC2025&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>Forensics/DFC</category>
      <category>DFC</category>
      <category>DFC2025</category>
      <category>디지털포렌식</category>
      <category>디지털포렌식챌린지</category>
      <category>디포챌</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/599</guid>
      <comments>https://pental.tistory.com/599#entry599comment</comments>
      <pubDate>Mon, 20 Apr 2026 21:15:57 +0900</pubDate>
    </item>
    <item>
      <title>[2025 DFC] 2025 디지털포렌식 챌린지 - 207 &amp;ndash; iBackup Trace</title>
      <link>https://pental.tistory.com/598</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Step-by-step methodology:&lt;/span&gt;&lt;/b&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 풀이에 앞서&lt;span&gt;, dfchallenge.org&lt;/span&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;381&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX2vze/dJMcagSLIrW/0r9vv4ku8x0DGNKgbDL95K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX2vze/dJMcagSLIrW/0r9vv4ku8x0DGNKgbDL95K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX2vze/dJMcagSLIrW/0r9vv4ku8x0DGNKgbDL95K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX2vze%2FdJMcagSLIrW%2F0r9vv4ku8x0DGNKgbDL95K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;381&quot; height=&quot;52&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; dfchallenge.org&lt;/span&gt;에 명시되어 있는&lt;span&gt; MD5 &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;282&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WPdn2/dJMcacpimKe/3WNrgF3UsAJSlfX2LPf4Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WPdn2/dJMcacpimKe/3WNrgF3UsAJSlfX2LPf4Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WPdn2/dJMcacpimKe/3WNrgF3UsAJSlfX2LPf4Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWPdn2%2FdJMcacpimKe%2F3WNrgF3UsAJSlfX2LPf4Qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;282&quot; height=&quot;113&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;113&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; HashTab&lt;/span&gt;을 사용해 다운로드 받은 파일의&lt;span&gt; MD5 &lt;/span&gt;해시값&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 파일은&lt;span&gt; backup.zip &lt;/span&gt;파일이며 상세 정보는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;FileName&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;454&quot;&gt;&lt;span&gt;&lt;span&gt;backup.zip&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Size&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;454&quot;&gt;&lt;span&gt;&lt;span&gt;131,621,229 Bytes&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;454&quot;&gt;&lt;span&gt;&lt;span&gt;d4591cd1aa35101c2484bc6a6d986538&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;주어진 파일의 상세 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축을 해제하면&lt;span&gt; `00008130-001E682D11181001C` &lt;/span&gt;폴더가 생성되며&lt;span&gt;, &lt;/span&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;453&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btTUqb/dJMcabRrnzR/iWheuSb9Boxt0TvQY1oFI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btTUqb/dJMcabRrnzR/iWheuSb9Boxt0TvQY1oFI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btTUqb/dJMcabRrnzR/iWheuSb9Boxt0TvQY1oFI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtTUqb%2FdJMcabRrnzR%2FiWheuSb9Boxt0TvQY1oFI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;114&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;압축 해제 된 파일의 일부 폴더&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서 주어진 파일들은&lt;span&gt; iTunes&lt;/span&gt;를 통한 아이폰 논리 백업파일의 형태이며&lt;span&gt;, &lt;/span&gt;일반적인 백업 파일과 다르게&lt;span&gt; Manifest.db &lt;/span&gt;등이&lt;span&gt; 0Bytes&lt;/span&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;453&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHtY2D/dJMcabRrnzV/FesofwpxG9sE4vWB1rLd2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHtY2D/dJMcabRrnzV/FesofwpxG9sE4vWB1rLd2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHtY2D/dJMcabRrnzV/FesofwpxG9sE4vWB1rLd2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHtY2D%2FdJMcabRrnzV%2FFesofwpxG9sE4vWB1rLd2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;56&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비정상적으로&lt;span&gt; Manifiest.db &lt;/span&gt;파일등이&lt;span&gt; 0bytes&lt;/span&gt;로 되어 있는 모습&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;문자 메시지 기록과 연락처를 복구하기 위해서는 각각 어떤 파일과 매핑되는지를 먼저 확인해야 한다&lt;span&gt;. &lt;/span&gt;이를 위해 문제 시나리오와 유사한 환경에서 직접 아이폰 논리 백업을 수행하였다&lt;span&gt;. &lt;/span&gt;논리 백업이 완료된 후&lt;span&gt;, Manifest.db &lt;/span&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;453&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2mqcQ/dJMcab4YLTH/MB5Y2S6dAaRyQSy9UqbNfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2mqcQ/dJMcab4YLTH/MB5Y2S6dAaRyQSy9UqbNfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2mqcQ/dJMcab4YLTH/MB5Y2S6dAaRyQSy9UqbNfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2mqcQ%2FdJMcab4YLTH%2FMB5Y2S6dAaRyQSy9UqbNfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;47&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비슷한 환경에서 논리 백업 후&lt;span&gt; Manifest.db &lt;/span&gt;파일 내&lt;span&gt; sms.db &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;453&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RXh9Z/dJMcabcOI9b/GKUKugy5m0Xh95FTygavt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RXh9Z/dJMcabcOI9b/GKUKugy5m0Xh95FTygavt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RXh9Z/dJMcabcOI9b/GKUKugy5m0Xh95FTygavt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRXh9Z%2FdJMcabcOI9b%2FGKUKugy5m0Xh95FTygavt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;47&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;비슷한 환경에서 논리 백업 후&lt;span&gt; Manifest.db &lt;/span&gt;파일 내&lt;span&gt; AddressBook.sqlitedb &lt;/span&gt;문자열 검색 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 확인된&lt;span&gt; fileID &lt;/span&gt;값은&lt;span&gt; SHA1 &lt;/span&gt;해시를 기반으로 생성된다&lt;span&gt;. &lt;/span&gt;해시 생성 방식은&lt;span&gt; Manifest.db&lt;/span&gt;의&lt;span&gt; Files &lt;/span&gt;테이블에서&lt;span&gt; domain &lt;/span&gt;컬럼과&lt;span&gt; relativePath &lt;/span&gt;컬럼을&lt;span&gt; &amp;ldquo;-&amp;rdquo;&lt;/span&gt;로 연결한 문자열을 입력값으로 하여&lt;span&gt; SHA1 &lt;/span&gt;알고리즘을 적용하는 방식이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;import hashlib&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def string_to_sha1(s) :&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return hashlib.sha1(s.encode('utf-8')).hexdigest()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# &quot;3d0d7e5fb2ce288813306e4d4636395e047a3d28&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;print(string_to_sha1(&quot;HomeDomain&quot; + &quot;-&quot; + &quot;Library/SMS/sms.db&quot;))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# &quot;31bb7ba8914766d4ba40d6dfb6113c8b614be442&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;print(string_to_sha1(&quot;HomeDomain&quot; + &quot;-&quot; + &quot;Library/AddressBook/AddressBook.sqlitedb&quot;))&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;특정 경로를&lt;span&gt; sha1&lt;/span&gt;으로 변환 검증 코드&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;각각 문제에서 필요한 데이터베이스의 파일 해쉬값은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;604&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;Type&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;511&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SHA1&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SMS&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;511&quot;&gt;&lt;span&gt;&lt;span&gt;3d0d7e5fb2ce288813306e4d4636395e047a3d28&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;AddressBook&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;511&quot;&gt;&lt;span&gt;&lt;span&gt;31bb7ba8914766d4ba40d6dfb6113c8b614be442&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;문제에서 필요한&lt;span&gt; SHA1 &lt;/span&gt;해시값&lt;span&gt; (fileID)&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;text-align: left;&quot;&gt;&lt;b&gt;총 몇개의 메세지가 존재하는가&lt;span&gt;? (50&lt;/span&gt;점&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;SMS &lt;/span&gt;데이터베이스는 &lt;b&gt;&lt;span&gt;3d0d7e5fb2ce288813306e4d4636395e047a3d28&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;파일에 존재하며&lt;span&gt;, &lt;/span&gt;실제 파일명은&lt;span&gt; sms.db&lt;/span&gt;이다&lt;span&gt;. &lt;/span&gt;이하 본 보고서에서는 이를&lt;span&gt; sms.db &lt;/span&gt;파일이라 칭한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;해당 데이터베이스는&lt;span&gt; DB Browser for SQLite &lt;/span&gt;도구를 이용하여 분석하였다&lt;span&gt;. sms.db&lt;/span&gt;의&lt;span&gt; message &lt;/span&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;453&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dg1JN2/dJMcafl1BXn/OY0lyxlgdKKtGadB8jl8W0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dg1JN2/dJMcafl1BXn/OY0lyxlgdKKtGadB8jl8W0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dg1JN2/dJMcafl1BXn/OY0lyxlgdKKtGadB8jl8W0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdg1JN2%2FdJMcafl1BXn%2FOY0lyxlgdKKtGadB8jl8W0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;253&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; DB Browser for SQLite&lt;/span&gt;를 통한&lt;span&gt; sms.db &lt;/span&gt;파일 내&lt;span&gt; message &lt;/span&gt;테이블의 일부&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;SELECT COUNT(*) FROM message;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;전체 행 개수를 계산 하기 위한&lt;span&gt; SQL &lt;/span&gt;쿼리&lt;span&gt;&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;453&quot; data-origin-height=&quot;108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kSd0b/dJMcaju9QAR/cCyLWONcSXMb2K0K57UQNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kSd0b/dJMcaju9QAR/cCyLWONcSXMb2K0K57UQNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kSd0b/dJMcaju9QAR/cCyLWONcSXMb2K0K57UQNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkSd0b%2FdJMcaju9QAR%2FcCyLWONcSXMb2K0K57UQNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;108&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; SQL &lt;/span&gt;쿼리 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정답&lt;span&gt; : 131&lt;/span&gt;개&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;2. &lt;/span&gt;총 몇 명이 주소록에 저장되어있는가&lt;span&gt;? (50&lt;/span&gt;점&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;주소록 데이터베이스는 &lt;b&gt;&lt;span&gt;31bb7ba8914766d4ba40d6dfb6113c8b614be442&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;파일에 존재하며&lt;span&gt;, &lt;/span&gt;실제 파일명은&lt;span&gt; AddressBook.sqlitedb&lt;/span&gt;이다&lt;span&gt;. &lt;/span&gt;이하 본 보고서에서는 이를&lt;span&gt; AddressBook &lt;/span&gt;파일이라 칭한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;해당 데이터베이스는&lt;span&gt; DB Browser for SQLite &lt;/span&gt;도구를 통해 분석하였다&lt;span&gt;. &lt;/span&gt;주소록에 저장된 인원 정보는&lt;span&gt; ABPerson &lt;/span&gt;테이블에 기록되어 있으며&lt;span&gt;, &lt;/span&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;453&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b637zV/dJMcaju9QBF/aZF6R35TIi5v0jBzEJmzs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b637zV/dJMcaju9QBF/aZF6R35TIi5v0jBzEJmzs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b637zV/dJMcaju9QBF/aZF6R35TIi5v0jBzEJmzs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb637zV%2FdJMcaju9QBF%2FaZF6R35TIi5v0jBzEJmzs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;156&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; DB Browser for SQLite&lt;/span&gt;를 통한&lt;span&gt; AddressBook &lt;/span&gt;파일 내&lt;span&gt; ABPerson &lt;/span&gt;테이블의 일부&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SELECT COUNT(*) FROM ABPerson;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;전체 행 개수를 확인하기 위한&lt;span&gt; SQL &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;453&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEAAMC/dJMb99MPPFw/r6XRLkaliYX8Izr0T3ucKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEAAMC/dJMb99MPPFw/r6XRLkaliYX8Izr0T3ucKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEAAMC/dJMb99MPPFw/r6XRLkaliYX8Izr0T3ucKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEAAMC%2FdJMb99MPPFw%2Fr6XRLkaliYX8Izr0T3ucKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;112&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; SQL &lt;/span&gt;쿼리 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;3. &lt;/span&gt;지인으로부터 온 메세지의 제목과 내용을 알아내시오&lt;span&gt;. (50&lt;/span&gt;점&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AddressBook &lt;/span&gt;파일에서는 총&lt;span&gt; 12&lt;/span&gt;명의 주소록을 확인할 수 있으며&lt;span&gt;, &lt;/span&gt;문제에서 의미하는 지인은&lt;span&gt; A&lt;/span&gt;씨의 주소록에 저장된 사람을 의미하는 것으로 추정된다&lt;span&gt;. &lt;/span&gt;따라서&lt;span&gt; AddressBook &lt;/span&gt;파일에 존재하는 주소록을 기반으로 분석을 진행한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;아래 사진은&lt;span&gt; AddressBook &lt;/span&gt;파일의&lt;span&gt; ABPerson &lt;/span&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;453&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q10s4/dJMcahjRPjk/wpHkWzKIgxNqS1EjyK2owk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q10s4/dJMcahjRPjk/wpHkWzKIgxNqS1EjyK2owk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q10s4/dJMcahjRPjk/wpHkWzKIgxNqS1EjyK2owk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq10s4%2FdJMcahjRPjk%2FwpHkWzKIgxNqS1EjyK2owk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;268&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; AddressBook &lt;/span&gt;파일 내&lt;span&gt; ABPerson &lt;/span&gt;테이블 일부&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;위 사진에서는 주소록에 저장된 실제 전화번호를 확인할 수 없으며&lt;span&gt;, ABMultiValue &lt;/span&gt;테이블에서 실제 연락처 정보를 확인할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;아래 사진은&lt;span&gt; AddressBook &lt;/span&gt;파일의&lt;span&gt; ABMultiValue &lt;/span&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;453&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5ZvPs/dJMb99MPPFI/Bj0in24ZkBIZaakv96qKc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5ZvPs/dJMb99MPPFI/Bj0in24ZkBIZaakv96qKc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5ZvPs/dJMb99MPPFI/Bj0in24ZkBIZaakv96qKc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5ZvPs%2FdJMb99MPPFI%2FBj0in24ZkBIZaakv96qKc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;216&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; AddressBook &lt;/span&gt;파일 내&lt;span&gt; ABMultiValue &lt;/span&gt;테이블 일부&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; 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;453&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kznIQ/dJMcaipvXF8/kIsDIlMNFbfRtFTtBsj5zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kznIQ/dJMcaipvXF8/kIsDIlMNFbfRtFTtBsj5zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kznIQ/dJMcaipvXF8/kIsDIlMNFbfRtFTtBsj5zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkznIQ%2FdJMcaipvXF8%2FkIsDIlMNFbfRtFTtBsj5zk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;313&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;span&gt; AddressBook &lt;/span&gt;파일의 구조 도식화&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AddressBook &lt;/span&gt;파일의&lt;span&gt; ABPerson &lt;/span&gt;테이블과&lt;span&gt; ABMultiValue &lt;/span&gt;테이블이 연관이 있는 테이블이다&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ABPerson&lt;/span&gt;의&lt;span&gt; ROWID&lt;/span&gt;가&lt;span&gt; ABMultiValue &lt;/span&gt;테이블의&lt;span&gt; record_id&lt;/span&gt;와 연결된다&lt;span&gt;. &lt;/span&gt;따라서 아래와 같은 주소록 정보를 얻을 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;595&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;ABPerson-ROWID&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;ABPerson-FIRST&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;ABPerson-LAST&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;ABMultiValue-value&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Lisa&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Yo&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010990058411&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;James&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Ahn&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010210084511&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Emily&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Smith&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010850861301&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Michael&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Johnson&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010514438041&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Olivia&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Williams&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010905861151&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Ethan&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Brown&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010378812541&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Ava&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Jones&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010667438511&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Daniel&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Garcia&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010455304201&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Sophia&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Miller&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010751292861&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Benjamin&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Davis&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010385699121&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Mia&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Wilson&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010985233641&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Lucas&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;151&quot;&gt;&lt;span&gt;&lt;span&gt;Anderson&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;142&quot;&gt;&lt;span&gt;&lt;span&gt;010318424451&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ABPerson&lt;/span&gt;과&lt;span&gt; ABMultiValue&lt;/span&gt;를 조합한 정리 테이블&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;위 표에서 확인한 전화번호를 바탕으로&lt;span&gt; DB Browser for SQLite &lt;/span&gt;도구를 통해&lt;span&gt; SMS&lt;/span&gt;파일의&lt;span&gt; message &lt;/span&gt;테이블에서 필터링 한 결과&lt;span&gt; 010751292861 &lt;/span&gt;번호에서만&lt;span&gt; 1&lt;/span&gt;개의 메시지가 발견되었다&lt;span&gt;. &lt;/span&gt;이 전화번호는&lt;span&gt; message &lt;/span&gt;테이블에&lt;span&gt; fallback_hash &lt;/span&gt;칼럼에 다음과 같은 형식으로 저장되어 있다.&lt;span&gt;&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;453&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RTamz/dJMcabjD4Ph/MlhfvVJKyn3DNuSGVLn0V1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RTamz/dJMcabjD4Ph/MlhfvVJKyn3DNuSGVLn0V1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RTamz/dJMcabjD4Ph/MlhfvVJKyn3DNuSGVLn0V1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRTamz%2FdJMcabjD4Ph%2FMlhfvVJKyn3DNuSGVLn0V1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;58&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; sms.db &lt;/span&gt;내&lt;span&gt; message &lt;/span&gt;테이블에서 발견된&lt;span&gt; 751292861 &lt;/span&gt;정보&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;message &lt;/span&gt;테이블의 구조는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;컬럼명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;설명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;활용 포인트&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;ROWID&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;각 메시지의 고유 식별자&lt;span&gt; (PK)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;다른 테이블&lt;span&gt;(message_attachment_join)&lt;/span&gt;과 매핑 시 기준 키&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;guid&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 고유 식별자&lt;span&gt; (UUID)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;iMessage/DB &lt;/span&gt;간 메시지 추적&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;text&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;문자 메시지 본문&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;실제 송수신된 메시지 내용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;subject&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 제목&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;MMS &lt;/span&gt;등 제목 포함 메시지 분석 시&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;handle_id&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;발신&lt;span&gt;/&lt;/span&gt;수신자 식별&lt;span&gt; ID (handle &lt;/span&gt;테이블과 매핑&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;송수신 상대 확인&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;date&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 생성&lt;span&gt;(&lt;/span&gt;전송&lt;span&gt;) &lt;/span&gt;시각&lt;span&gt; (epoch time)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;타임라인 분석&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;date_read&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;읽은 시각&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;수신자 확인 여부 추적&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;date_delivered&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;배달 완료 시각&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;전송 성공 여부 확인&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;is_from_me&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;내가 보낸 메시지 여부&lt;span&gt; (1=&lt;/span&gt;보낸 메시지&lt;span&gt;, 0=&lt;/span&gt;수신 메시지&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;송&lt;span&gt;&amp;middot;&lt;/span&gt;수신 구분&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;is_sent&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 전송 완료 여부&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;실제 전송 성공 여부 판단&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;is_read&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 읽음 여부&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;확인&lt;span&gt;/&lt;/span&gt;미확인 상태 분석&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;service&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;서비스 유형&lt;span&gt; (&lt;/span&gt;예&lt;span&gt;: SMS, iMessage)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;통신 방식 구분&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;account&lt;/span&gt;&lt;/b&gt;&lt;span&gt; / &lt;b&gt;account_guid&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;사용된 계정 정보&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;Apple ID, iCloud &lt;/span&gt;연계 확인&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;cache_has_attachments&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일 존재 여부&lt;span&gt; (0=&lt;/span&gt;없음&lt;span&gt;, 1=&lt;/span&gt;있음&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부 추적 여부 판단&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;fallback_hash&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;전화번호&lt;span&gt;/&lt;/span&gt;세션&lt;span&gt;/&lt;/span&gt;해시가 혼합된 값&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;발신자 번호 추적&lt;span&gt;, &lt;/span&gt;데이터 복구 단서&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; sms.db &lt;/span&gt;내&lt;span&gt; message &lt;/span&gt;테이블의 구조&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;s:tel:+8210751292861|0(28)&amp;lt;6F04EC061108B8DA6F7852BEC387D9800A6A2AEE55BABB4BEB5A32DC448881A6&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; fallback_hash &lt;/span&gt;칼럼에서 발견된&lt;span&gt; 010751292861 &lt;/span&gt;정보&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Fallback_hash&lt;/span&gt;의 구조는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;s:tel:+8210751292861 : &lt;/span&gt;전화번호가 국제 표준&lt;span&gt;(E.164) &lt;/span&gt;형식으로 저장된 부분이며&lt;span&gt;, +82&lt;/span&gt;는 대한민국 국가번호를 의미한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;|0(28) : &lt;/span&gt;메시지 전송 세션과 관련된 내부 식별자를 의미한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;lt;...&amp;gt; : &lt;/span&gt;송수신 시점에서 메시지 무결성 검증 및 추적을 위한 해시값 형태이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;즉&lt;span&gt;, fallback_hash&lt;/span&gt;는 전화번호를 국제 표기 방식으로 변환한 후&lt;span&gt;, &lt;/span&gt;메시지 전송 과정의 고유 식별자와 해시값을 함께 저장하는 필드로 볼 수 있다&lt;span&gt;. &lt;/span&gt;이를 통해 단말기 간 동기화 또는 데이터베이스 복구 과정에서 중복 메시지를 구분하거나 무결성을 확인할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;제목&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Please confirm your order details&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;내용&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;[Web Message]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Transfer Path Activated &amp;mdash; Clean Lane, Silent Move&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Greetings, Mate. This isn&amp;rsquo;t a pitch. It&amp;rsquo;s a notice.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;If you're reading this, your node is trusted and your line is considered green.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Our infrastructure handles mid- to high-volume dispatches, including flagged stacks.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;We process across primary, relay, and ghost channels, depending on timing and pressure.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Primary Gateway: &lt;a href=&quot;http://70.com/login.asp&quot;&gt;http://70.com/login.asp&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Clearance Code: 555&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; Release-on-trigger system &amp;mdash; no confirmations needed post-signal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; Zero KYC enforcement on receiver side&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; Currency-neutral transfer (₩&amp;rarr;$, $&amp;rarr;&amp;euro;, or internal credits)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; Routing auto-adjusts based on throughput; congested lines reassign in real time&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; Split delivery optional &amp;mdash; main + buffer payload if flagged&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Standard dispatch: up to ₩1B per cycle&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Parallel links yield up to 1.2%&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Full log trace available on backchannel&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; Ledger access given via secondary hash (on request only)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;If your recipient requires obscured receipt, enable blind handoff mode in your key panel.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Relay points are scrubbed at 48-hour intervals. No residuals. No trace.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;We&amp;rsquo;re not a brand. We&amp;rsquo;re a mechanism.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Run a 100K test cycle &amp;mdash; it&amp;rsquo;ll move cleaner than any front you&amp;rsquo;ve dealt with.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;문제&lt;span&gt; 3&lt;/span&gt;번의 정답&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 해당 메시지에 첨부된 것으로 추정되는 파일의 저장된 파일명을 찾으시오&lt;span&gt;. (50&lt;/span&gt;점&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;sms.db &lt;/span&gt;파일에는 문자 메시지 송수신 내역이 저장되어 있으며&lt;span&gt;, &lt;/span&gt;이를 기반으로 전체 대화 기록을 확인할 수 있다&lt;span&gt;. &lt;/span&gt;아래 그림은&lt;span&gt; SMS &lt;/span&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;453&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dlSZep/dJMcagFfNLh/Whk56ZAZ7pb5g6YS1iixW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dlSZep/dJMcagFfNLh/Whk56ZAZ7pb5g6YS1iixW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dlSZep/dJMcagFfNLh/Whk56ZAZ7pb5g6YS1iixW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdlSZep%2FdJMcagFfNLh%2FWhk56ZAZ7pb5g6YS1iixW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;205&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; sms.db &lt;/span&gt;파일의 구조 도식화&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;sms.db&lt;/span&gt;의&lt;span&gt; message &lt;/span&gt;테이블에서 각 레코드는 고유 식별자인&lt;span&gt; ROWID&lt;/span&gt;를 가진다&lt;span&gt;. &lt;/span&gt;이&lt;span&gt; ROWID&lt;/span&gt;는&lt;span&gt; message_attachment_join &lt;/span&gt;테이블의&lt;span&gt; message_id&lt;/span&gt;와&lt;span&gt; 1:1&lt;/span&gt;로 매핑된다&lt;span&gt;. &lt;/span&gt;또한&lt;span&gt;, message_attachment_join &lt;/span&gt;테이블의&lt;span&gt; attachment_id&lt;/span&gt;는&lt;span&gt; attachment &lt;/span&gt;테이블의&lt;span&gt; ROWID&lt;/span&gt;와&lt;span&gt; 1:1 &lt;/span&gt;연관 관계를 형성한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;message_attachment_join &lt;/span&gt;테이블은 문자 메시지&lt;span&gt;(message &lt;/span&gt;테이블&lt;span&gt;)&lt;/span&gt;와 첨부파일&lt;span&gt;(attachment &lt;/span&gt;테이블&lt;span&gt;) &lt;/span&gt;간의 관계를 정의한다&lt;span&gt;. &lt;/span&gt;각 메시지는&lt;span&gt; 0&lt;/span&gt;개 이상의 첨부파일을 가질 수 있으며&lt;span&gt;, &lt;/span&gt;하나의 첨부파일이 여러 메시지와 연결될 수도 있다&lt;span&gt;. &lt;/span&gt;이러한 관계를 관리하기 위해 중간 매핑 테이블이 사용된다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;604&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;컬럼명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;타입&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;438&quot;&gt;&lt;span&gt;&lt;b&gt;설명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;message_id&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;438&quot;&gt;&lt;span&gt;&lt;span&gt;message &lt;/span&gt;테이블의&lt;span&gt; ROWID (&lt;/span&gt;외래키&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;attachment_id&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;438&quot;&gt;&lt;span&gt;&lt;span&gt;attachment &lt;/span&gt;테이블의&lt;span&gt; ROWID (&lt;/span&gt;외래키&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; message_attachment_join &lt;/span&gt;테이블의 구조&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;attachment &lt;/span&gt;테이블은 문자 메시지에 첨부된 파일의 메타데이터를 저장한다&lt;span&gt;. &lt;/span&gt;주요 컬럼의 의미는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;컬럼명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;타입&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;설명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;ROWID&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;각 첨부파일 레코드의 고유 식별자&lt;span&gt; (&lt;/span&gt;기본키&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;guid&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일의 전역 고유 식별자&lt;span&gt; (UUID &lt;/span&gt;형식&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;created_date&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일 생성 시각&lt;span&gt; (UNIX &lt;/span&gt;타임스탬프&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;start_date&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일 전송 시작 시각&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;filename&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일 저장 경로&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;uti&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;Uniform Type Identifier (ex. public.png)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;mime_type&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;MIME &lt;/span&gt;타입&lt;span&gt; (ex. image/png)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;transfer_state&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부 전송 상태 코드&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;is_outgoing&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;송신 여부&lt;span&gt; (1=&lt;/span&gt;보낸 첨부&lt;span&gt;, 0=&lt;/span&gt;수신 첨부&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;user_info&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;BLOB&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;사용자 관련 메타데이터&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;transfer_name&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;전송된 실제 파일명&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;total_bytes&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;첨부파일 크기&lt;span&gt; (bytes &lt;/span&gt;단위&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;is_sticker&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;스티커 여부&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;attribution_info&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;BLOB&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;메시지 출처 정보&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;ck_sync_state&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;CloudKit &lt;/span&gt;동기화 상태&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;ck_record_id&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;CloudKit &lt;/span&gt;레코드&lt;span&gt; ID&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;original_guid&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;원본&lt;span&gt; GUID (&lt;/span&gt;중복 방지를 위해&lt;span&gt; UNIQUE &lt;/span&gt;제약 적용&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;is_commsafety_sensitive&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;민감 콘텐츠 여부 표시&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;emoji_image_content_identifier&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;이모지 이미지의 경우&lt;span&gt;) &lt;/span&gt;콘텐츠 식별자&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;emoji_image_short_description&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;TEXT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;이모지 이미지의 경우&lt;span&gt;) &lt;/span&gt;짧은 설명&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;preview_generation_state&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;INTEGER&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;미리보기 생성 상태&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; attachment &lt;/span&gt;테이블의 구조&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;따라서&lt;span&gt;, 3&lt;/span&gt;번 문제에서 확인한 메시지의&lt;span&gt; ROWID &lt;/span&gt;값을 기준으로&lt;span&gt; message_attachment_join &lt;/span&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;307&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpiyZp/dJMcafGkq5f/cdZh4GmHHKZ555pZBZCf5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpiyZp/dJMcafGkq5f/cdZh4GmHHKZ555pZBZCf5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpiyZp/dJMcafGkq5f/cdZh4GmHHKZ555pZBZCf5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpiyZp%2FdJMcafGkq5f%2FcdZh4GmHHKZ555pZBZCf5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;307&quot; height=&quot;319&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;319&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;span&gt; sms.db &lt;/span&gt;파일 내&lt;span&gt; message_attachment_join &lt;/span&gt;테이블의 일부&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3&lt;/span&gt;번 문제에서 확인된 문자 메시지의&lt;span&gt; ROWID&lt;/span&gt;는&lt;span&gt; 125&lt;/span&gt;이며&lt;span&gt;, &lt;/span&gt;해당 메시지는&lt;span&gt; attachment_id = 11&lt;/span&gt;과 연관되어 있다&lt;span&gt;. &lt;/span&gt;따라서&lt;span&gt; attachment &lt;/span&gt;테이블에서&lt;span&gt; ROWID = 11&lt;/span&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;453&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caGNaO/dJMcaiwfdnA/6DCKpTnqAaI821JdpYXWiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caGNaO/dJMcaiwfdnA/6DCKpTnqAaI821JdpYXWiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caGNaO/dJMcaiwfdnA/6DCKpTnqAaI821JdpYXWiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaGNaO%2FdJMcaiwfdnA%2F6DCKpTnqAaI821JdpYXWiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;160&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/span&gt;&lt;span&gt; sms.db &lt;/span&gt;파일 내&lt;span&gt; attachment&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;테이블의 일부 및&lt;span&gt; ROWID 11 &lt;/span&gt;정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 데이터&lt;span&gt;(ROWID=11)&lt;/span&gt;를 추출한 결과는 아래와 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;컬럼명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;값&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;ROWID&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;guid&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;8B37AEFD-D9D3-401E-8A73-8DB82BBAB25D&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;filename&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;~/Library/SMS/Attachments/c7/07/8B37AEFD-D9D3-401E-8A73-8DB82BBAB25D/Resized_1753100894543_1753101056921.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;uti&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;public.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;mime_type&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;image/png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;transfer_name&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;Resized_1753100894543_1753101056921.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;total_bytes&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;567599&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ROWID&lt;/span&gt;가&lt;span&gt; 11&lt;/span&gt;인 데이터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석 결과&lt;span&gt;, &lt;/span&gt;해당 메시지에 첨부된 것으로 확인되는 파일명&lt;span&gt;(transfer_name &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;&lt;b&gt;정답&lt;span&gt; : Resized_1753100894543_1753101056921.png&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>Forensics/DFC</category>
      <category>DFC</category>
      <category>DFC2025</category>
      <category>디지털포렌식</category>
      <category>디지털포렌식챌린지</category>
      <category>디포챌</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/598</guid>
      <comments>https://pental.tistory.com/598#entry598comment</comments>
      <pubDate>Mon, 20 Apr 2026 21:12:43 +0900</pubDate>
    </item>
    <item>
      <title>[2025 DFC] 2025 디지털포렌식 챌린지 - 206 &amp;ndash; Let&amp;rsquo;s Vibe</title>
      <link>https://pental.tistory.com/597</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Step-by-step methodology:&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;359&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjEjDt/dJMcajhBABD/bmE81ftJZTlJ0iRJmHI4z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjEjDt/dJMcajhBABD/bmE81ftJZTlJ0iRJmHI4z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjEjDt/dJMcajhBABD/bmE81ftJZTlJ0iRJmHI4z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjEjDt%2FdJMcajhBABD%2FbmE81ftJZTlJ0iRJmHI4z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;359&quot; height=&quot;52&quot; data-origin-width=&quot;359&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;대회에서 주어진&lt;span&gt; MD5 &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;355&quot; data-origin-height=&quot;140&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qYrHc/dJMcabjD4D9/NbYgT8CXr0QIvjBg21aXG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qYrHc/dJMcabjD4D9/NbYgT8CXr0QIvjBg21aXG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qYrHc/dJMcabjD4D9/NbYgT8CXr0QIvjBg21aXG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqYrHc%2FdJMcabjD4D9%2FNbYgT8CXr0QIvjBg21aXG1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;140&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;140&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; HashTab&lt;/span&gt;을 이용한 다운로드 받은 파일의 해시값 검증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진 파일의 정보는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;208&quot;&gt;&lt;span&gt;&lt;span&gt;File Name&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;desktop.zip&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;208&quot;&gt;&lt;span&gt;&lt;span&gt;File Size&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;20,473,057,512 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;208&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;3908E6DBDE1ED0F0B6A41F97693DA3CB&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;208&quot;&gt;&lt;span&gt;&lt;span&gt;SHA-1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;EA2807F984EA95C40FD903C04B876E05B1AAD340&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;주어진 파일의 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;압축을 해제하면 다음과 같은 파일을 확인 할 수 있으며 각각 정보는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;369&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wN7gi/dJMcaibZSdg/KzjzuIddmvVV58wFqXeeIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wN7gi/dJMcaibZSdg/KzjzuIddmvVV58wFqXeeIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wN7gi/dJMcaibZSdg/KzjzuIddmvVV58wFqXeeIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwN7gi%2FdJMcaibZSdg%2FKzjzuIddmvVV58wFqXeeIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;369&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;369&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;압축 해제 된 파일들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총&lt;span&gt; 18&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;&lt;span&gt;1. &lt;/span&gt;&lt;b&gt;데스크톱에 설치된 응용프로그램들의 정보를 서술하시오&lt;span&gt;.(10 points)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\NTUSER.DAT&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;설치된 응용프로그램의 정보를 확인하기 위한 경로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 경로에서 설치된 응용프로그램들의 정보를 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjrYtz/dJMcaibZSdk/BUjkv8I333qzv1tq9PyXk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjrYtz/dJMcaibZSdk/BUjkv8I333qzv1tq9PyXk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjrYtz/dJMcaibZSdk/BUjkv8I333qzv1tq9PyXk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjrYtz%2FdJMcaibZSdk%2FBUjkv8I333qzv1tq9PyXk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;134&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Magnet Axiom&lt;/span&gt;을 이용한 설치된 응용프로그램 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Magnet Axiom &lt;/span&gt;도구를 사용하여 추출된 결과는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;프로그램명&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;설치 일자&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;버전 정보&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;VMware Tools&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-26 PM 11:59:24.547&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;12.4.5.23787635&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-27 PM 4:06:23.666&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;1.2.4&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;Windsurf&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-27 PM 4:13:33.934&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;1.11.1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;GitHub Desktop&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 AM 1:15:40.448&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;3.5.2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;Eraser 6.2.0.2996&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 AM 2:04:54.141&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;6.2.2996&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;196&quot;&gt;&lt;span&gt;&lt;span&gt;Clipchamp&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;205&quot;&gt;&lt;span&gt;&lt;span&gt;3.0.10220.0&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;설치된 응용프로그램 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;2. &lt;/span&gt;&lt;b&gt;개발자가 사용한&lt;span&gt; Github &lt;/span&gt;계정을 식별하시오&lt;span&gt; (10 points)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 경로에서&lt;span&gt; Github &lt;/span&gt;계정 정보를 식별 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\.gitconfig&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;이미지에서 발견된&lt;span&gt; gitconfig &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;453&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWjN25/dJMcaadW87r/vvyH3ozaZKb4bfEexO1sE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWjN25/dJMcaadW87r/vvyH3ozaZKb4bfEexO1sE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWjN25/dJMcaadW87r/vvyH3ozaZKb4bfEexO1sE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWjN25%2FdJMcaadW87r%2FvvyH3ozaZKb4bfEexO1sE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;378&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; gitconfig &lt;/span&gt;파일 내 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로&lt;span&gt; Github Desktop&lt;/span&gt;이 설치되어 있고&lt;span&gt;, &lt;/span&gt;프리패치 등&lt;span&gt; Github Desktop&lt;/span&gt;을 사용한 흔적이 있으며&lt;span&gt;, &lt;/span&gt;해당 부분을 분석한 결과는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\AppData\Roaming\Github Desktop\Local Storage\leveldb\000003.log&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Github Dektop&lt;/span&gt;에서 생성된 로그파일&lt;span&gt; 1&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 경로는&lt;span&gt; Github Desktop&lt;/span&gt;에서 생성된 로그 파일이며 해당 로그 파일에도&lt;span&gt; .gitconfig &lt;/span&gt;와 동일한&lt;span&gt; Github &lt;/span&gt;이름과 이메일을 확인 할 수 있다.&lt;span&gt;&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;453&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RAfmr/dJMcaadW87A/dStTFpJDiYc60r51VYHfB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RAfmr/dJMcaadW87A/dStTFpJDiYc60r51VYHfB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RAfmr/dJMcaadW87A/dStTFpJDiYc60r51VYHfB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRAfmr%2FdJMcaadW87A%2FdStTFpJDiYc60r51VYHfB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;243&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 000003.log &lt;/span&gt;파일의 일부&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;{&quot;login&quot;:&quot;cyber-chef-2025&quot;,&quot;endpoint&quot;:&quot;&lt;a href=&quot;https://api.github.com&quot;&gt;https://api.github.com&lt;/a&gt;&quot;,&quot;token&quot;:&quot;&quot;,&quot;emails&quot;:[{&quot;email&quot;:&quot;dfc2025.glen@gmail.com&quot;,&quot;primary&quot;:true,&quot;verified&quot;:true,&quot;visibility&quot;:&quot;public&quot;}],&quot;avatarURL&quot;:&quot;&lt;a href=&quot;https://avatars.githubusercontent.com/u/223317873?v=4&quot;&gt;https://avatars.githubusercontent.com/u/223317873?v=4&lt;/a&gt;&quot;,&quot;id&quot;:223317873,&quot;name&quot;:&quot;cyber-chef-2025&quot;,&quot;plan&quot;:&quot;free&quot;,&quot;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 000003.log &lt;/span&gt;파일의 일부&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정답&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;github &lt;/span&gt;계정&lt;span&gt; : cyber-chef-2025&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;github &lt;/span&gt;이메일&lt;span&gt; : dfc2025.glen@gmail.com&lt;/span&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;span&gt;3. &lt;/span&gt;&lt;b&gt;개발자가 첫번째로 사용한&lt;span&gt; IDE&lt;/span&gt;에서 사용한 프롬프트를 분석하고&lt;span&gt;, &lt;/span&gt;타임라인을 구성하시오&lt;span&gt; (50 points)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째로 사용한&lt;span&gt; IDE&lt;/span&gt;를 찾기 위해서 프리패치 분석을 진행했다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 설치된&lt;span&gt; IDE&lt;/span&gt;는&lt;span&gt; Windsurf, Cursor &lt;/span&gt;총&lt;span&gt; 2&lt;/span&gt;개가 설치되어 있다&lt;span&gt;. &lt;/span&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;453&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOwWzc/dJMcacW6Xwa/NbK97N7LO2vrSSdvKO3k61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOwWzc/dJMcacW6Xwa/NbK97N7LO2vrSSdvKO3k61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOwWzc/dJMcacW6Xwa/NbK97N7LO2vrSSdvKO3k61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOwWzc%2FdJMcacW6Xwa%2FNbK97N7LO2vrSSdvKO3k61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;118&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Magnet Axiom&lt;/span&gt;으로 확인한&lt;span&gt; Windsurf&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;453&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uPdlu/dJMcaadW89j/iWLYwp9k943QxfUonLvDvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uPdlu/dJMcaadW89j/iWLYwp9k943QxfUonLvDvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uPdlu/dJMcaadW89j/iWLYwp9k943QxfUonLvDvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuPdlu%2FdJMcaadW89j%2FiWLYwp9k943QxfUonLvDvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;96&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Magnet Axiom&lt;/span&gt;으로 확인한 &lt;span&gt;Cursor&lt;/span&gt;의 프리패치 기록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프리패치 기록 상 먼저 실행한 프로그램은&lt;span&gt; Cursor.exe&lt;/span&gt;이며&lt;span&gt;, 2025&lt;/span&gt;년&lt;span&gt; 7&lt;/span&gt;월&lt;span&gt; 27&lt;/span&gt;일 오후&lt;span&gt; 4&lt;/span&gt;시&lt;span&gt; 9&lt;/span&gt;분&lt;span&gt; 33&lt;/span&gt;초에 실행된 흔적을 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Cursor&lt;/span&gt;에서 사용한 프롬프트를 분석하기 위해서 다음 경로를 참조하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\AppData\Roaming\Cursor\User\workspaceStorage\558804eb26cea58c5895507e7784c194\state.vscdb&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Cursor&lt;/span&gt;의 내부 데이터 저장 경로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 경로의 데이터베이스 내&lt;span&gt; ItemTable &lt;/span&gt;테이블의&lt;span&gt; key &lt;/span&gt;칼럼의 &lt;span&gt;aiService.generations &lt;/span&gt;의 내용은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;5e3f9f73-9582-4617-af07-03c6e831569b&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Hello?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753719867948&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;eb89690a-80b9-4966-8f73-47e9bf57aa40&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Hello?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753719868598&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;a56dd3b8-1f09-4c61-826d-65988510dfa6&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Hello?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753719872552&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;7c191f8e-cdf5-4a8c-a0df-edc61b07b5c1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Hello?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753719976671&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;515824ab-61ff-4da9-af39-1cf4613d5f45&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Hello?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720027529&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;d69fb6c9-accb-4c9d-aed2-c551d6007d85&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Thank you, I want to develop a python keylooger, Could you please tell me about the keylooger?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720123603&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;d9f002c4-e4cb-49c6-aba9-01d578adabfc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Okay, now I'm gonna make it for security research, please develop keylooger using Python&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720198891&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;a31590b9-a5f3-4340-9101-56be5f2ce24e&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;README.md&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720216841&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;3cb0f653-2edd-4f0d-9c2a-3f04fd3e7aba&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;requirements.txt&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720227590&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;db8834e2-c385-4d97-b811-1e5a11c003eb&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;basic_keylogger.py&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720295548&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;b7bbc11b-cba2-48a6-9d1b-32f4ef952165&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;advanced_keylogger.py&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720505564&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;4cecbd8a-fda5-43d0-af55-8a6818550806&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;All right, at this moment, I think th basis feature will be enough. Thanks&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720615600&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;a0e6948e-e4c0-49ae-bd2c-34147e146e76&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;One more, Could you please develop chrome extension to embed this code?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720663712&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;bbbca8dd-d6f2-41f2-a59b-a730b2f94fd7&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;manifest.json&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720688762&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;c5835e73-a4ad-419f-a530-a0d3a37c6632&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;content.js&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720792805&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;5c01a078-6031-4490-859b-3f91418700fd&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;background.js&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753720887074&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;d595450f-d69e-4196-a1d0-76c030d86abf&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;popup.html&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721037487&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;956f336b-f550-4688-816e-e33de32f00a4&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;popup.js&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721150979&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;ea2a0093-1ba9-411d-8635-6c290683680c&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;README.md&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721173117&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;fb103936-0ec5-4a8d-9659-9871717901a5&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;INSTALLATION.md&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721250639&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;491d6c56-01fd-4fd4-8b8b-e25be63984c6&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;Thank you, Could you please create or download a icon for this extension?&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;composer&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721328117&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;generationUUID&quot;: &quot;b4aad9d5-49d6-4d4d-89df-53a55e4b9933&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;textDescription&quot;: &quot;create_icons.py&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;type&quot;: &quot;apply&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unixMs&quot;: 1753721411720&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의&lt;span&gt; aiService.generations &lt;/span&gt;의 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 데이터베이스 내&lt;span&gt; ItemTable&lt;/span&gt;의&lt;span&gt; key &lt;/span&gt;칼럼의 &lt;span&gt;aiService.prompts&lt;/span&gt;의 내용은 다음과 같다&lt;span&gt;. &lt;/span&gt;해당 칼럼은 최근&lt;span&gt; 6&lt;/span&gt;개 프롬프트에 한정하여 출력된다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;Hello?&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;Thank you, I want to develop a python keylooger, Could you please tell me about the keylooger?&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;Okay, now I'm gonna make it for security research, please develop keylooger using Python&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;All right, at this moment, I think th basis feature will be enough. Thanks&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;One more, Could you please develop chrome extension to embed this code?&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;commandType&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;text&quot;: &quot;Thank you, Could you please create or download a icon for this extension?&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의&lt;span&gt; aiService.prompts &lt;/span&gt;의 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한&lt;span&gt; ItemTable&lt;/span&gt;의&lt;span&gt; key &lt;/span&gt;칼럼의 &lt;span&gt;cursorAuth/workspaceOpenedDate&lt;/span&gt;의 내용은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-28T16:23:15.927Z&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의 &lt;span&gt;cursorAuth/workspaceOpenedDate &lt;/span&gt;의 내용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 값은 워크스페이스가 열린 시간이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ItemTable&lt;/span&gt;의&lt;span&gt; key &lt;/span&gt;칼럼의 &lt;span&gt;terminal.integrated.bufferState&lt;/span&gt;에서는 파일 실행 실패에 관련한 내용을 확인 할 수 있다&lt;span&gt;. &lt;/span&gt;아래 표는 해당&lt;span&gt; value&lt;/span&gt;의 일부이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;&quot;shellLaunchConfig&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;cwd&quot;: &quot;C:\\Users\\dfc2025\\Documents\\GitHub\\allachie&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;executable&quot;: &quot;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;icon&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;id&quot;: &quot;terminal-powershell&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;initialText&quot;: &quot;PS C:\\Users\\dfc2025\\Documents\\GitHub\\allachie&amp;gt; \u001b[93mpython3 \u001b[37m.\\chrome_extension\\icons\\create_icons.py\r\n\u001b[0mPython was not found; run without arguments to install from the Microsoft Store, or disable this shortcut from Settings &amp;gt; Manage App Execution Aliases.\r\nPS C:\\Users\\dfc2025\\Documents\\GitHub\\allachie&amp;gt; \r\n\u001b[0m\u001b[7m * \u001b[0;104m History restored \u001b[0m\n\r\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\u001b[H&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;shellIntegrationEnvironmentReporting&quot;: false,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;useShellEnvironment&quot;: true&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;timestamp&quot;: 1753722402800,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;unicodeVersion&quot;: &quot;11&quot;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의 &lt;span&gt;terminal.integrated.bufferState &lt;/span&gt;의 내용 일부&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 오류는&lt;span&gt; python3&lt;/span&gt;를 실행하려고 했지만&lt;span&gt; Python&lt;/span&gt;이 설치되어 있지 않아 발생한 오류이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타임라인으로 정리하면 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;603&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #ffffff;&quot; width=&quot;104&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Time&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(UTC + 9)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff;&quot; width=&quot;180&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Prompt&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff;&quot; width=&quot;76&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Type&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff;&quot; width=&quot;85&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Apply File&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #ffffff;&quot; width=&quot;159&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Content&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:23:15&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;워크스페이스&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;열린 시간&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:24:27.948&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Hello?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;사용자 질의 시작&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:24:28.598&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Hello?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td rowspan=&quot;4&quot; width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;사용자 메시지&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:24:32.552&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Hello?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:26:16.671&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Hello?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:27:07.529&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Hello?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:28:43.603&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Thank you, I want to develop a python keylooger, Could you please tell me about the keylooger?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td rowspan=&quot;2&quot; width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;사용자 메시지&lt;span&gt;&lt;br /&gt;&lt;/span&gt;파이썬을 이용한&lt;span&gt;&lt;br /&gt;&lt;/span&gt;키로거 개발 요청&lt;span&gt;&lt;br /&gt;&lt;/span&gt;프롬프트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:29:58.891&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Okay, now I'm gonna make it for security research, please develop keylooger using Python&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:30:16.841&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의&lt;span&gt; README.md &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:30:27.590&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;requirements.txt &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:31:35.548&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;basic_keylogger.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;basic_keylogger.py &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:35:05.564&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;advanced_keylogger.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;advanced_keylogger.py &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:36:55.600&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;All right, at this moment, I think th basis feature will be enough. Thanks&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td rowspan=&quot;2&quot; width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;사용자 메시지&lt;span&gt;&lt;br /&gt;&lt;/span&gt;크롬 확장 프로그램&lt;span&gt;&lt;br /&gt;&lt;/span&gt;개발 요청 프롬프트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;025-07-29 01:37:43.712&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;One more, Could you please develop chrome extension to embed this code?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:38:08.762&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;manifest.json&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;manifest.json &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:39:52.805&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;content.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;content.js &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:41:27.074&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;background.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;background.js &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:43:57.487&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;popup.html&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;popup.html &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:45:50.979&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;popup.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의&lt;span&gt; popup.json &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:46:13.117&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;README.md &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:47:30.639&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;INSTALLATION.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;INSTALLATION.md &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:48:48.117&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;Thank you, Could you please create or download a icon for this extension?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;composer&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;사용자 메시지&lt;span&gt;&lt;br /&gt;&lt;/span&gt;아이콘 생성 또는 다운로드 요청 프롬프트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 01:50:11.720&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;apply&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;create_icons.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;Cursor&lt;/span&gt;&lt;span&gt;의 &lt;span&gt;create_icons.py &lt;/span&gt;적용&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;104&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-29 02:06:42:800&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;180&quot;&gt;&lt;span&gt;&lt;span&gt;PS C:\\Users\\dfc2025\\Documents\\GitHub\\allachie&amp;gt; \u001b[93mpython3 \u001b[37m.\\chrome_extension\\icons\\create_icons.py\r\n\u001b[0mPython was not found; run without arguments to install from the Microsoft Store, or disable this shortcut from Settings &amp;gt; Manage App Execution Aliases.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;76&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;85&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;159&quot;&gt;&lt;span&gt;&lt;span&gt;오류로 인해&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;실행 실패&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;사용자의 행위를 정리한 타임라인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로&lt;span&gt; state.vscdb &lt;/span&gt;정보를 바탕으로&lt;span&gt; Cursor&lt;/span&gt;에서 생성 또는 수정된 파일은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;File Path&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\src\basic_keylogger.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;advanced_keylogger.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\manifest.json&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\content.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\background.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\popup.html&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\popup.js&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\INSTALLATION.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\icons\README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;C:\Users\dfc2025\Documents\GitHub\allachie\chrome_extension\icons\create_icons.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Cursor&lt;/span&gt;에서 생성 또는 수정된 파일 목록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;advanced_keylogger.py &lt;/span&gt;의 경우&lt;span&gt; Cursor &lt;/span&gt;데이터베이스의 &lt;span&gt;aiService.generations&lt;/span&gt;에서는 존재하지만 &lt;span&gt;history.entries &lt;/span&gt;등에서는 존재하지 않는다&lt;span&gt;. &lt;/span&gt;이 경우&lt;span&gt; Cursor&lt;/span&gt;에서 생성 되었지만 사용자가 지웠을 가능성 또는&lt;span&gt; Cursor&lt;/span&gt;에서 미상의 이유로 생성되지 못했을 경우 두가지가 존재한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만&lt;span&gt; NTFS &lt;/span&gt;로그를 확인해보면 &lt;span&gt;advanced_keylogger.py &lt;/span&gt;파일은 생성된 흔적을 확인 할 수 없다&lt;span&gt;. &lt;/span&gt;따라서&lt;span&gt; Cursor&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;&amp;nbsp;4. &lt;/span&gt;&lt;b&gt;개발자가 두번째로 사용한&lt;span&gt; IDE&lt;/span&gt;에서 생성한 코드 파일을 복구하시오&lt;span&gt; (50 points)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째로 사용한&lt;span&gt; IDE&lt;/span&gt;는&lt;span&gt; Windsurf&lt;/span&gt;이다&lt;span&gt;. Windsurf&lt;/span&gt;의 데이터를 확인하기 위해 아래 경로의 데이터 베이스를 참조하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\AppData\Roaming\Windsurf\User\workspaceStorage\558804eb26cea58c5895507e7784c194\state.vscdb&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Winsurf&lt;/span&gt;의 내부 데이터 저장 경로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 데이터베이스의&lt;span&gt; itemTable &lt;/span&gt;테이블의&lt;span&gt; key&lt;/span&gt;가&lt;span&gt; history.entries &lt;/span&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;453&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mY97X/dJMcaciwQYn/aiDg2pg1P6FskZvoOAYWO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mY97X/dJMcaciwQYn/aiDg2pg1P6FskZvoOAYWO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mY97X/dJMcaciwQYn/aiDg2pg1P6FskZvoOAYWO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmY97X%2FdJMcaciwQYn%2FaiDg2pg1P6FskZvoOAYWO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;253&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; itemTable &lt;/span&gt;테이블의&lt;span&gt; history.entries &lt;/span&gt;&lt;span&gt;일부&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/example_usage.py&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/requirements.txt&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/port_scanner.py&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/.codeium/windsurf/brain/411d5fa3-2192-4df1-8585-13bf6b2fd53c/plan.md&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/PORT_SCANNER_README.md&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;editor&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;forceFile&quot;: true,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;options&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;override&quot;: &quot;default&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;resource&quot;: &quot;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/README.md&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의 &lt;span&gt;history.entries &lt;/span&gt;의 내용 일부&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉&lt;span&gt;, plan.md&lt;/span&gt;에는&lt;span&gt; windsurf&lt;/span&gt;가 사용할 체크리스트를 가지고 있으며&lt;span&gt;, example_usage.py, requirements.txt, port_scanner.py, PORT_SCANNER_README.md, README.md &lt;/span&gt;파일을 생성 및 수정한 것을 확인할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;plan.md &lt;/span&gt;파일은&lt;span&gt; Windsurf&lt;/span&gt;의&lt;span&gt; LLM &lt;/span&gt;에이전트가 사용자의 프롬프트를 통해서 이전에 수행 내용을 미리 정리 해둔 파일이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 &lt;span&gt;memento/workbench.editors.files.textFileEditor &lt;/span&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;453&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xP6LN/dJMcaa55zAt/t4hwn8fLFYkH39Rn1kkZqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xP6LN/dJMcaa55zAt/t4hwn8fLFYkH39Rn1kkZqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xP6LN/dJMcaa55zAt/t4hwn8fLFYkH39Rn1kkZqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxP6LN%2FdJMcaa55zAt%2Ft4hwn8fLFYkH39Rn1kkZqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;253&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; state.vscdb &lt;/span&gt;내&lt;span&gt; ItemTable&lt;/span&gt;의&lt;span&gt; memento/workbench.editors.files.textFileEditor&lt;/span&gt;의 내용 일부&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;FilePath&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;LineCount&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;file:///c%3A/Users/dfc2025/.codeium/windsurf/brain/411d5fa3-2192-4df1-8585-13bf6b2fd53c/plan.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/port_scanner.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;140&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;114&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;451&quot;&gt;&lt;span&gt;&lt;span&gt;file:///c%3A/Users/dfc2025/Documents/GitHub/allachie/example_usage.py&quot;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;150&quot;&gt;&lt;span&gt;&lt;span&gt;38&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; memento/workbench.editors.files.textFileEditor&lt;/span&gt;에서 발견된&lt;span&gt; LineCount&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Windsurf&lt;/span&gt;의 경우 아래 경로에 프로젝트 내부 백업 파일을 저장한다&lt;span&gt;. &lt;/span&gt;따라서 생성한 코드 파일을 복구 하기 위해서 다음 두 경로를 참조하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;66&quot;&gt;&lt;span&gt;&lt;span&gt;Index&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;535&quot;&gt;&lt;span&gt;&lt;span&gt;Path&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;66&quot;&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;535&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\.codeium\windsurf\brain\411d5fa3-2192-4df1-8585-13bf6b2fd53c&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;66&quot;&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;535&quot;&gt;&lt;span&gt;&lt;span&gt;\Users\dfc2025\.codeium\windsurf\code_tracker\active\allachie_e39fe48b75c418d781052bbd4cfec37e7b8ebaa6&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;삭제된 파일을 복구하기 위해 참조한 경로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각 경로에 존재하는 파일은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1&lt;/span&gt;번 경로에서는 다음과 같은 파일을 확인할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;178&quot;&gt;&lt;span&gt;&lt;span&gt;FileName&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;171&quot;&gt;&lt;span&gt;&lt;span&gt;FileSize&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;252&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;178&quot;&gt;&lt;span&gt;&lt;span&gt;plan.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;171&quot;&gt;&lt;span&gt;&lt;span&gt;794 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;252&quot;&gt;&lt;span&gt;&lt;span&gt;90748074D82FAAC94862E7189F0F8799&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;178&quot;&gt;&lt;span&gt;&lt;span&gt;plan_metadata.pbtxt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;171&quot;&gt;&lt;span&gt;&lt;span&gt;78 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;252&quot;&gt;&lt;span&gt;&lt;span&gt;90F6839F7C974AB3071EC01B8FA5D6CF&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;표&lt;span&gt; 15&lt;/span&gt;의&lt;span&gt; 1&lt;/span&gt;번 경로에서 확인된 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2&lt;/span&gt;번 경로에서는 다음과 같은 파일을 확인할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;FileName&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;FileSize&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;23a7f620f90bd83c3795c4f494abc355_PORT_SCANNER_README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;3,820 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;39DC6EE1F10ECB51E4B5F4AA3655A37D&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;816b3a93dd9003225f12de7b2a166e67_README.md&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;4,055 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;6CC88984CEDE782C911B8681447DFB4A&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;28945a67fca14a8292ff59fd8e559f77_requirements.txt&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;414 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;2400AF97B3CE664EA4AB2FDBD9257A55&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;c61863821c3b420d68c73427941a56b1_example_usage.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;1,371 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;1D79F7054BC64D8752C490F01AD17B46&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;293&quot;&gt;&lt;span&gt;&lt;span&gt;fb2e08a8541b0450c9b54bd97377b9a9_port_scanner.py&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;108&quot;&gt;&lt;span&gt;&lt;span&gt;4,815 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;E3A76E8A902EDD215B8CB891C4C46A2A&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;표&lt;span&gt; 15&lt;/span&gt;의&lt;span&gt; 2&lt;/span&gt;번 경로에서 확인된 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 복구된 파일 내용은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;# Simple Port Scanner&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;A Python-based port scanner that can scan for open ports on target hosts using multi-threading for improved performance.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Features&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Multi-threaded scanning**&lt;/b&gt; for faster performance&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Customizable port ranges**&lt;/b&gt; (single port, range, or default 1-1024)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Service identification**&lt;/b&gt; for common ports&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Timeout configuration**&lt;/b&gt; for connection attempts&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Command-line interface**&lt;/b&gt; with argument parsing&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- &lt;b&gt;**Thread pool management**&lt;/b&gt; to prevent resource exhaustion&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Files&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `port_scanner.py` - Main port scanner script with CLI&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `example_usage.py` - Example of programmatic usage&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `PORT_SCANNER_README.md` - This documentation file&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Installation&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;No additional dependencies required - uses only Python standard library modules:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `socket` - For network connections&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `threading` - For concurrent scanning&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `argparse` - For command-line arguments&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `datetime` - For timestamps&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Usage&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;### Command Line Interface&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```bash&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Basic scan of common ports (1-1024)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;python port_scanner.py 127.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Scan specific port range&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;python port_scanner.py 192.168.1.1 -p 1-100&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Scan single port&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;python port_scanner.py example.com -p 80&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Custom timeout and thread count&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;python port_scanner.py 127.0.0.1 -p 1-1000 -t 0.5 --threads 200&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;### Command Line Arguments&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `host` - Target host to scan (required)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `-p, --ports` - Port range to scan (default: 1-1024)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; - Single port: `80`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; - Port range: `1-1024`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; - Custom range: `80-443`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `-t, --timeout` - Connection timeout in seconds (default: 1.0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- `--threads` - Number of concurrent threads (default: 100)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;### Programmatic Usage&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```python&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from port_scanner import PortScanner&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Create scanner instance&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;scanner = PortScanner(&quot;127.0.0.1&quot;, timeout=1.0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Scan port range&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;scanner.scan_ports(start_port=1, end_port=1024, threads=100)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Scan single port&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;scanner.scan_port(80)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# Check results&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;print(f&quot;Open ports: {scanner.open_ports}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Example Output&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Starting port scan on 127.0.0.1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Scanning ports 1-1024&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Started at: 2025-07-28 09:57:56&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;--------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 22: Open&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 80: Open&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 443: Open&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;--------------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Open ports on 127.0.0.1:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 22: SSH&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 80: HTTP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Port 443: HTTPS&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Scan completed at: 2025-07-28 09:58:15&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Common Services Detected&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;The scanner identifies common services for well-known ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 21: FTP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 22: SSH&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 23: Telnet&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 25: SMTP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 53: DNS&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 80: HTTP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 443: HTTPS&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 3389: RDP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 3306: MySQL&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port 5432: PostgreSQL&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- And more...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Performance Tips&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;1. &lt;b&gt;**Adjust thread count**&lt;/b&gt;: More threads = faster scanning, but may overwhelm the target&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;2. &lt;b&gt;**Set appropriate timeout**&lt;/b&gt;: Lower timeout = faster scanning, but may miss slow services&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;3. &lt;b&gt;**Scan specific ranges**&lt;/b&gt;: Avoid scanning all 65535 ports unless necessary&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;4. &lt;b&gt;**Use localhost for testing**&lt;/b&gt;: Test on 127.0.0.1 to avoid network delays&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Ethical Usage&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;This tool is for educational and authorized testing purposes only:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Only scan systems you own or have explicit permission to test&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Respect network policies and terms of service&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Use responsibly and ethically&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Consider the impact on target systems&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Limitations&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- TCP ports only (no UDP scanning)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Basic service detection (port-based only)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- No stealth scanning techniques&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- No OS fingerprinting&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Limited error handling for edge cases&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;## Security Considerations&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Port scanning may trigger security alerts&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Some firewalls may block or rate-limit scan attempts&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Always obtain proper authorization before scanning&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;- Be aware of legal implications in your jurisdiction&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구된&lt;span&gt; PORT_SCANNER_README.md &lt;/span&gt;파일&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;pynput==1.7.6&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;psutil==5.9.5&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;cryptography==41.0.7&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;requests==2.31.0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;colorama==0.4.6&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Pillow==10.0.1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;pywin32==306; sys_platform == &quot;win32&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;python-xlib==0.33; sys_platform == &quot;linux&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;pyobjc-framework-Cocoa==10.1; sys_platform == &quot;darwin&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;19&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구된&lt;span&gt; requirements.txt &lt;/span&gt;파일&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;#!/usr/bin/env python3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Example usage of the Port Scanner&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;This script demonstrates how to use the PortScanner class programmatically.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from port_scanner import PortScanner&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def example_scan():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;&quot;&quot;Example of how to use the PortScanner class&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Example 1: Scan common ports on localhost&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(&quot;=== Example 1: Scanning localhost (common ports) ===&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; scanner = PortScanner(&quot;127.0.0.1&quot;, timeout=0.5)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; scanner.scan_ports(start_port=20, end_port=100, threads=50)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(&quot;\n&quot; + &quot;=&quot;*60 + &quot;\n&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Example 2: Scan specific ports on a target&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(&quot;=== Example 2: Scanning specific ports ===&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; target_host = &quot;127.0.0.1&quot; &amp;nbsp;# Change this to your target&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; scanner2 = PortScanner(target_host, timeout=1.0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Scan only web-related ports&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; web_ports = [80, 443, 8080, 8443, 3000, 5000, 8000]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(f&quot;Scanning web-related ports on {target_host}: {web_ports}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; for port in web_ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; scanner2.scan_port(port)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; if scanner2.open_ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Open web ports found: {sorted(scanner2.open_ports)}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&quot;No open web ports found&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if __name__ == &quot;__main__&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; example_scan()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구된&lt;span&gt; example_usage.py &lt;/span&gt;파일&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;#!/usr/bin/env python3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Simple Port Scanner Script&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;A basic port scanner that checks for open ports on a target host.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import socket&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import threading&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from datetime import datetime&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import argparse&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;class PortScanner:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; def __init__(self, target_host, timeout=1):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.target_host = target_host&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.timeout = timeout&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.open_ports = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.lock = threading.Lock()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; def scan_port(self, port):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;&quot;&quot;Scan a single port on the target host&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Create a socket object&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sock.settimeout(self.timeout)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Attempt to connect to the host and port&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; result = sock.connect_ex((self.target_host, port))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if result == 0:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with self.lock:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.open_ports.append(port)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Port {port}: Open&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sock.close()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except socket.gaierror:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Could not resolve hostname&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Error: Could not resolve hostname {self.target_host}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sys.exit(1)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except Exception as e:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Handle other exceptions&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; def scan_ports(self, start_port=1, end_port=1024, threads=100):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;&quot;&quot;Scan a range of ports using threading for faster scanning&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;\nStarting port scan on {self.target_host}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Scanning ports {start_port}-{end_port}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&quot;-&quot; * 50)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Create and start threads&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread_list = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for port in range(start_port, end_port + 1):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread = threading.Thread(target=self.scan_port, args=(port,))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread_list.append(thread)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread.start()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Limit the number of concurrent threads&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if len(thread_list) &amp;gt;= threads:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for t in thread_list:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; t.join()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread_list = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Wait for remaining threads to complete&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for thread in thread_list:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thread.join()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Display results&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&quot;-&quot; * 50)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if self.open_ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;\nOpen ports on {self.target_host}:&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.open_ports.sort()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for port in self.open_ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; service = self.get_service_name(port)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Port {port}: {service}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;\nNo open ports found on {self.target_host}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;\nScan completed at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; def get_service_name(self, port):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;&quot;&quot;Get the common service name for a port&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; common_ports = {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 21: &quot;FTP&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 22: &quot;SSH&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 23: &quot;Telnet&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 25: &quot;SMTP&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 53: &quot;DNS&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 80: &quot;HTTP&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 110: &quot;POP3&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 143: &quot;IMAP&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 443: &quot;HTTPS&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 993: &quot;IMAPS&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 995: &quot;POP3S&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 3389: &quot;RDP&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 5432: &quot;PostgreSQL&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 3306: &quot;MySQL&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1433: &quot;MSSQL&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 6379: &quot;Redis&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 27017: &quot;MongoDB&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return common_ports.get(port, &quot;Unknown&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def main():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; parser = argparse.ArgumentParser(description=&quot;Simple Port Scanner&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; parser.add_argument(&quot;host&quot;, help=&quot;Target host to scan&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; parser.add_argument(&quot;-p&quot;, &quot;--ports&quot;, default=&quot;1-1024&quot;, &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;help=&quot;Port range to scan (e.g., 1-1024, 80, 80-443)&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; parser.add_argument(&quot;-t&quot;, &quot;--timeout&quot;, type=float, default=1.0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;help=&quot;Connection timeout in seconds (default: 1.0)&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; parser.add_argument(&quot;--threads&quot;, type=int, default=100,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;help=&quot;Number of threads to use (default: 100)&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; args = parser.parse_args()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Parse port range&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; if &quot;-&quot; in args.ports:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; start_port, end_port = map(int, args.ports.split(&quot;-&quot;))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; start_port = end_port = int(args.ports)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Validate port range&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; if start_port &amp;lt; 1 or end_port &amp;gt; 65535 or start_port &amp;gt; end_port:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&quot;Error: Invalid port range. Ports must be between 1-65535&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sys.exit(1)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Create scanner and start scanning&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; scanner = PortScanner(args.host, args.timeout)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; scanner.scan_ports(start_port, end_port, args.threads)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; except KeyboardInterrupt:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&quot;\n\nScan interrupted by user&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sys.exit(1)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if __name__ == &quot;__main__&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; main()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;21&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구된&lt;span&gt; port_scanner.py &lt;/span&gt;파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt;2&lt;/span&gt;번의 분석에 사용된 데이터를 타임라인으로 시각화 할 수 있는 웹 애플리케이션을&lt;span&gt; Vibe&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;b&gt;Coding&lt;/b&gt;&lt;/span&gt;&lt;b&gt;으로 개발하시오&lt;span&gt;. (80 points)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2&lt;/span&gt;번 분석에서 사용된 데이터는 &lt;span&gt;Github Desktop&lt;/span&gt;의 사용자의&lt;span&gt; Appdata\Roaming &lt;/span&gt;데이터이다&lt;span&gt;. &lt;/span&gt;해당 파일을 다음과 같이 &lt;span&gt;Chat GPT &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;아래의 표는 사용한 프롬프트이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;This file is a compressed C:\Users\[UserName]\Local\Roaming\Github Desktop folder, and its detailed structure is as follows.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;abc@code-server:~/workspace/DFC_206/GitHub Desktop$ tree&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; $I30&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; blob_storage&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── baa2ed1f-c213-49c6-96b3-5bdfc86dad06&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Cache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── Cache_Data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── $I30&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── f_000001&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Code Cache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── js&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index-dir&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── the-real-index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── wasm&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index-dir&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── the-real-index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; DawnGraphiteCache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; DawnWebGPUCache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Dictionaries&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── ko-3-0.bdic&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; DIPS&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; DIPS-shm&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; DIPS-wal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; GPUCache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── data_3&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; IndexedDB&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── file__0.indexeddb.leveldb&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── $I30&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── 000003.log&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── CURRENT&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── LOCK&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── LOG&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── MANIFEST-000001&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Local State&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Local Storage&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── leveldb&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── 000003.log&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── CURRENT&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── LOCK&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── LOG&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── MANIFEST-000001&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; lockfile&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; logs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── 2025-07-28.desktop.production.log&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Network&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── $I30&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── Cookies&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── Cookies-journal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── NetworkDataMigrated&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── Network Persistent State&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── TransportSecurity&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── Trust Tokens&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── Trust Tokens-journal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Preferences&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; Shared Dictionary&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── cache&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── index-dir&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;│&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── the-real-index&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── db&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;│&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── db-journal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; SharedStorage&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;├──&lt;span&gt; SharedStorage-wal&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;└──&lt;span&gt; WebStorage&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;├── QuotaManager&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;└── QuotaManager-journal &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Through the data, the user's traces should be expressed in a timeline and visually through a web application through Python. First, look at the structure of the compressed file and proceed with the analysis while focusing on logs, etc&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;If you upload the zip file through Python flask, you need to analyze it and produce a web application that can visually express the timeline, etc&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Additionally, Can you find github email?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Then add this feature and update the flask code&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Even if you use the zip file I gave you, the total number of events is zero&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;2025-07-28T17:05:55.920000+00:00 GitHub Desktop Log log:info [ui] Executing getStashEntries: git log -g -z --format=%gD%x00%H%x00%gs%x00%T%x00%P refs/stash -- (took 11.347s) C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\logs\2025-07-28.desktop.production.log 2025-07-28T17:06:05.972000+00:00 GitHub Desktop Log log:info [ui] Executing getAllTags: git show-ref --tags -d (took 10.033s) C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\logs\2025-07-28.desktop.production.log 2025-09-17T02:13:45.621748+00:00 Local State JSON file:modified Local State JSON modified C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Local State 2025-09-17T02:13:45.621748+00:00 Chromium Local State file:modified Chromium Local State mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Local State 2025-09-17T02:13:45.623742+00:00 Preferences JSON file:modified Preferences JSON modified C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Preferences 2025-09-17T02:13:45.623742+00:00 Chromium Preferences file:modified Chromium Preferences mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Preferences 2025-09-17T02:13:45.736219+00:00 GitHub Account Scan account:noreply_email 2223317873+cyber-chef-2025@users.noreply.github.com IndexedDB\file__0.indexeddb.leveldb\000003.log 2025-09-17T02:13:45.742120+00:00 IndexedDB LevelDB Manifest file:modified IndexedDB LevelDB Manifest mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\IndexedDB\file__0.indexeddb.leveldb\MANIFEST-000001 2025-09-17T02:13:45.744082+00:00 GitHub Account Scan account:primary_email dfc2025.glen@gmail.com Local Storage\leveldb\000003.log 2025-09-17T02:13:45.748915+00:00 LocalStorage LevelDB Manifest file:modified LocalStorage LevelDB Manifest mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Local Storage\leveldb\MANIFEST-000001 2025-09-17T02:13:45.749912+00:00 GitHub Desktop log file:modified GitHub Desktop log mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\logs\2025-07-28.desktop.production.log 2025-09-17T02:13:45.754394+00:00 Chromium Cookies DB file:modified Chromium Cookies DB mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\Network\Cookies 2025-09-17T02:13:45.770776+00:00 WebStorage quota:scan Scanned QuotaManager.sqlite C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\WebStorage\QuotaManager 2025-09-17T02:13:45.770776+00:00 WebStorage QuotaManager file:modified WebStorage QuotaManager mtime C:\Users\User\Downloads\work\case_20250917_111345\extracted\GitHub Desktop\WebStorage\QuotaManager&lt;br /&gt;The e-mail search part seems to be processed because the time has changed to the current date, but would it be difficult to just search in the original file? And you can take out functions such as csv download and json download&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;GitHub Username is not found, can you find github username in logs?&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Since we need to not only focus on this case but also other samples, we should avoid fs_maker focusing on a specific date at the moment&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;22&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;사용된 프롬프트 목록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용한 프롬프트 및 답변은 &lt;span&gt;&lt;a href=&quot;https://chatgpt.com/share/68ca1dc2-0f48-800a-b158-15b1c441d19a&quot;&gt;https://chatgpt.com/share/68ca1dc2-0f48-800a-b158-15b1c441d19a&lt;/a&gt; &lt;/span&gt;를 통해 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시각화를 위해 사용되는 데이터 파일은 &lt;span&gt;AppData\Roaming\Github Desktop &lt;/span&gt;폴더를 압축한 파일이며&lt;span&gt;, &lt;/span&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;451&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvDqoF/dJMcahKUQft/zk9NeNTkww49wQ8lQhnHfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvDqoF/dJMcahKUQft/zk9NeNTkww49wQ8lQhnHfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvDqoF/dJMcahKUQft/zk9NeNTkww49wQ8lQhnHfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvDqoF%2FdJMcahKUQft%2Fzk9NeNTkww49wQ8lQhnHfk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;76&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;76&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;span&gt; python3&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;453&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5fv1N/dJMcahKUQfv/FBk31Y8wvTJqCkStrV4kd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5fv1N/dJMcahKUQfv/FBk31Y8wvTJqCkStrV4kd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5fv1N/dJMcahKUQfv/FBk31Y8wvTJqCkStrV4kd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5fv1N%2FdJMcahKUQfv%2FFBk31Y8wvTJqCkStrV4kd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;136&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; http://127.0.0.1:8000 &lt;/span&gt;을 접속한 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;127.0.0.1:8000&lt;/span&gt;을 접속하면 &lt;span&gt;Github Desktop &lt;/span&gt;폴더를 압축한 파일을 올릴 수 있는 폼이 있다&lt;span&gt;. &lt;/span&gt;해당 폼에 압축된 &lt;span&gt;Github Desktop &lt;/span&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;453&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNkyHD/dJMcagkUkqM/uJfcS3JsYjSLBg8MP5yO80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNkyHD/dJMcagkUkqM/uJfcS3JsYjSLBg8MP5yO80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNkyHD/dJMcagkUkqM/uJfcS3JsYjSLBg8MP5yO80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNkyHD%2FdJMcagkUkqM%2FuJfcS3JsYjSLBg8MP5yO80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;164&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Github Desktop.zip &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;453&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjR1LU/dJMcagkUkqO/oU2UPToUfp13BhLa2BAaB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjR1LU/dJMcagkUkqO/oU2UPToUfp13BhLa2BAaB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjR1LU/dJMcagkUkqO/oU2UPToUfp13BhLa2BAaB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjR1LU%2FdJMcagkUkqO%2FoU2UPToUfp13BhLa2BAaB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;296&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;296&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;span&gt; python&lt;/span&gt;을 통한 &lt;span&gt;Github &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;453&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rz85O/dJMcahKUQfF/AKPXMLK37iuPPuHxwshLH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rz85O/dJMcahKUQfF/AKPXMLK37iuPPuHxwshLH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rz85O/dJMcahKUQfF/AKPXMLK37iuPPuHxwshLH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frz85O%2FdJMcahKUQfF%2FAKPXMLK37iuPPuHxwshLH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;271&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Figure &lt;/span&gt;&lt;span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Timeline&lt;/span&gt;에서 확인 할 수 있는 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 아래와 같으며&lt;span&gt;, &lt;/span&gt;사용한 데이터셋은 별첨&lt;span&gt;1_Github_Desktop.zip &lt;/span&gt;으로 첨부한다&lt;span&gt;. &lt;/span&gt;코드 또한 별첨&lt;span&gt;2_Github_Timeline.py &lt;/span&gt;로 첨부한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import os, zipfile, json, sqlite3, re&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from pathlib import Path&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from datetime import datetime, timedelta, timezone&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;from zoneinfo import ZoneInfo&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ZoneInfo = None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from flask import Flask, request, render_template_string, redirect, url_for&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;APP_DIR = Path(__file__).parent&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;UPLOADS = APP_DIR / &quot;uploads&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;WORK = APP_DIR / &quot;work&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;UPLOADS.mkdir(exist_ok=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;WORK.mkdir(exist_ok=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def get_tz(tz_name: str):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if ZoneInfo is not None:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return ZoneInfo(tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return timezone.utc&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def chrome_webkit_time_to_dt(us: int, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;epoch = datetime(1601,1,1,tzinfo=timezone.utc)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;dt = epoch + timedelta(microseconds=int(us))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return dt.astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def file_mtime(path: Path, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return datetime.fromtimestamp(path.stat().st_mtime, tz=get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def add_event(events, ts, source, category, description, path=None, extra=None):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not ts:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events.append({&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;timestamp&quot;: ts.isoformat() if isinstance(ts, datetime) else str(ts),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;source&quot;: source,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;category&quot;: category,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;description&quot;: description,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;path&quot;: str(path) if path else None,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;extra&quot;: extra or {}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- Parsers for extracted files ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def parse_desktop_logs(root: Path, events, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;log_dir = root / &quot;logs&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not log_dir.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;found = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pat1 = re.compile(r&quot;(?P&amp;lt;ts&amp;gt;\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z)\s*-\s*(?P&amp;lt;lvl&amp;gt;\w+):\s*(?P&amp;lt;msg&amp;gt;.*)&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for p in sorted(log_dir.glob(&quot;*.log&quot;)):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;found.append(str(p))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with p.open(&quot;r&quot;, encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;) as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;for line in f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m = pat1.search(line)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if m:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ts = datetime.fromisoformat(m.group(&quot;ts&quot;).replace(&quot;Z&quot;,&quot;+00:00&quot;)).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;lvl = m.group(&quot;lvl&quot;); msg = m.group(&quot;msg&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;add_event(events, ts, &quot;GitHub Desktop Log&quot;, f&quot;log:{lvl.lower()}&quot;, msg, p)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m2 = re.search(r&quot;\[(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z)\]\s*(.*)&quot;, line)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if m2:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ts = datetime.fromisoformat(m2.group(1).replace(&quot;Z&quot;,&quot;+00:00&quot;)).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;msg = m2.group(2).strip()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;add_event(events, ts, &quot;GitHub Desktop Log&quot;, &quot;log:info&quot;, msg, p)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception as e:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;add_event(events, file_mtime(p, tz_name), &quot;GitHub Desktop Log&quot;, &quot;log:error&quot;, f&quot;Failed to parse log: {e}&quot;, p)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return found&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def parse_cookies(db_path: Path, events, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;out = {&quot;dotcom_user&quot;: None, &quot;count&quot;: 0, &quot;domains&quot;: []}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not db_path.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return out&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn = sqlite3.connect(f&quot;file:{db_path}?mode=ro&quot;, uri=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur = conn.cursor()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur.execute(&quot;SELECT name FROM sqlite_master WHERE type='table'&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;tables = {r[0].lower() for r in cur.fetchall()}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;table = &quot;cookies&quot; if &quot;cookies&quot; in tables else next(iter(tables)) if tables else None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not table:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn.close()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return out&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur.execute(f&quot;PRAGMA table_info({table})&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cols = {r[1]: i for i, r in enumerate(cur.fetchall())}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur.execute(f&quot;SELECT * FROM {table}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;rows = cur.fetchall()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;out[&quot;count&quot;] = len(rows)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;domains = set()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for row in rows:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;host = row[cols.get(&quot;host_key&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;name = row[cols.get(&quot;name&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;path = row[cols.get(&quot;path&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;creation = row[cols.get(&quot;creation_utc&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;last_access = row[cols.get(&quot;last_access_utc&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;expires = row[cols.get(&quot;expires_utc&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;domains.add(host)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;if name == &quot;dotcom_user&quot; and &quot;github.com&quot; in host:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if &quot;value&quot; in cols:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;out[&quot;dotcom_user&quot;] = row[cols.get(&quot;value&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts_c = chrome_webkit_time_to_dt(creation, tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts_a = chrome_webkit_time_to_dt(last_access, tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts_e = chrome_webkit_time_to_dt(expires, tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;if ts_c: add_event(events, ts_c, &quot;Chromium Cookies&quot;, &quot;cookie:created&quot;, f&quot;{name} @ {host}{path}&quot;, db_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;if ts_a: add_event(events, ts_a, &quot;Chromium Cookies&quot;, &quot;cookie:last_access&quot;, f&quot;{name} @ {host}{path}&quot;, db_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;if ts_e and expires != 0: add_event(events, ts_e, &quot;Chromium Cookies&quot;, &quot;cookie:expires&quot;, f&quot;{name} @ {host}{path}&quot;, db_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn.close()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;out[&quot;domains&quot;] = sorted(list(domains))[:50]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return out&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def parse_json_events(path: Path, source_name: str, events, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ts = file_mtime(path, tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if ts:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;add_event(events, ts, source_name, &quot;file:modified&quot;, f&quot;{source_name} modified&quot;, path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;data = json.loads(path.read_text(encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return {&quot;keys&quot;: list(data.keys())[:50]}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return {&quot;keys&quot;: []}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def parse_quota_manager(db_path: Path, events, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;info = {&quot;origins&quot;: 0}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not db_path.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return info&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn = sqlite3.connect(f&quot;file:{db_path}?mode=ro&quot;, uri=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur = conn.cursor()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur.execute(&quot;SELECT name FROM sqlite_master WHERE type='table'&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;tables = {r[0].lower() for r in cur.fetchall()}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for t in tables:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if &quot;origin&quot; in t or &quot;quota&quot; in t or &quot;storage&quot; in t:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cur.execute(f&quot;SELECT * FROM {t} LIMIT 50&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;rows = cur.fetchall()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;info[&quot;origins&quot;] += len(rows)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;conn.close()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;mt = file_mtime(db_path, tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if mt:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;add_event(events, mt, &quot;WebStorage&quot;, &quot;quota:scan&quot;, &quot;Scanned QuotaManager.sqlite&quot;, db_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return info&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- Username detection in logs ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;BAD_OWNERS = set([&quot;login&quot;,&quot;settings&quot;,&quot;site&quot;,&quot;features&quot;,&quot;about&quot;,&quot;contact&quot;,&quot;pricing&quot;,&quot;topics&quot;,&quot;apps&quot;,&quot;marketplace&quot;,&quot;explore&quot;,&quot;issues&quot;,&quot;pulls&quot;])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def username_from_logs(root: Path):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;log_dir = root / &quot;logs&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not log_dir.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return None, {}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;text = &quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for p in sorted(log_dir.glob(&quot;*.log&quot;)):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;text += p.read_text(encoding=&quot;utf-8&quot;, errors=&quot;ignore&quot;) + &quot;\n&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m = re.search(r'&quot;login&quot;\s*:\s*&quot;([^&quot;]+)&quot;', text)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if m:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return m.group(1), {&quot;method&quot;:&quot;json_login&quot;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m = re.search(r'\b\d+\+([A-Za-z0-9._-]+)@users\.noreply\.github\.com\b', text)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if m:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return m.group(1), {&quot;method&quot;:&quot;noreply_email&quot;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;owners = re.findall(r'github\.com[/:]([A-Za-z0-9._-]+)/[A-Za-z0-9._-]+', text)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;owners = [o for o in owners if o.lower() not in BAD_OWNERS]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if owners:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;from collections import Counter&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cand, _ = Counter(owners).most_common(1)[0]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return cand, {&quot;method&quot;:&quot;repo_owner&quot;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return None, {}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- Email scan DIRECTLY from ZIP (keeps original file times) ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;EMAIL_RE = re.compile(rb'([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})')&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;INCLUDE_DIRS_FOR_EMAILS = [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;logs/&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;Local Storage/leveldb/&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;IndexedDB/file__0.indexeddb.leveldb/&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def detect_zip_prefix(z):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for n in z.namelist():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if n.startswith(&quot;GitHub Desktop/&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return &quot;GitHub Desktop/&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return &quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def scan_emails_from_zip(zip_path: Path, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;results = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with zipfile.ZipFile(zip_path, 'r') as z:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;prefix = detect_zip_prefix(z)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for n in z.namelist():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if n.endswith(&quot;/&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;rel = n[len(prefix):] if n.startswith(prefix) else n&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not any(rel.startswith(d) for d in INCLUDE_DIRS_FOR_EMAILS):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;data = z.read(n)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for m in EMAIL_RE.finditer(data):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;email = m.group(1).decode('utf-8', errors='ignore')&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;start = max(0, m.start()-60); end = min(len(data), m.end()+60)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;snippet = data[start:end].decode('utf-8', errors='ignore').replace(&quot;\n&quot;,&quot; &quot;).strip()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;zi = z.getinfo(n)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;naive = datetime(*zi.date_time)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts = naive.replace(tzinfo=timezone.utc).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;score = (3 if rel.startswith(&quot;logs/&quot;) else 0) + (2 if &quot;github&quot; in snippet.lower() else 0) + (1 if (&quot;account&quot; in snippet.lower() or &quot;login&quot; in snippet.lower()) else 0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;results.append({&quot;email&quot;: email, &quot;file&quot;: rel, &quot;file_modified&quot;: ts.isoformat(), &quot;snippet&quot;: snippet, &quot;score&quot;: score})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for r in results:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cat = &quot;account:noreply_email&quot; if &quot;users.noreply.github.com&quot; in r[&quot;email&quot;] else &quot;account:primary_email&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events.append({&quot;timestamp&quot;: r[&quot;file_modified&quot;], &quot;source&quot;: &quot;GitHub Account Scan&quot;, &quot;category&quot;: cat, &quot;description&quot;: r[&quot;email&quot;], &quot;path&quot;: r[&quot;file&quot;], &quot;extra&quot;: {&quot;score&quot;: r[&quot;score&quot;]}})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;from collections import defaultdict&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;agg = defaultdict(int)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for r in results: agg[r[&quot;email&quot;]] += 1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;primary = None; noreplies = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for em, _ in sorted(agg.items(), key=lambda x: -x[1]):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if &quot;users.noreply.github.com&quot; in em: noreplies.append(em)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;elif primary is None: primary = em&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return {&quot;hits&quot;: results, &quot;events&quot;: events, &quot;primary_email&quot;: primary, &quot;noreply_emails&quot;: sorted(list(set(noreplies)))}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- FS presence markers DIRECTLY from ZIP (generalized, no hardcoded dates) ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def scan_fs_markers_from_zip(zip_path: Path, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;&quot;&quot;Emit presence markers for key artefacts using ZIP entry timestamps. No hardcoded filenames.&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;markers = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with zipfile.ZipFile(zip_path, 'r') as z:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;prefix = detect_zip_prefix(z)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;interesting = [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&quot;Network/Cookies&quot;, &quot;Chromium Cookies DB&quot;),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&quot;Preferences&quot;, &quot;Chromium Preferences&quot;),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&quot;Local State&quot;, &quot;Chromium Local State&quot;),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&quot;WebStorage/QuotaManager&quot;, &quot;WebStorage QuotaManager&quot;),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# Any log files&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for n in z.namelist():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not n.endswith(&quot;.log&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;rel = n[len(prefix):] if n.startswith(prefix) else n&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not rel.startswith(&quot;logs/&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;zi = z.getinfo(n)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;naive = datetime(*zi.date_time)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ts = naive.replace(tzinfo=timezone.utc).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;markers.append({&quot;timestamp&quot;: ts.isoformat(), &quot;source&quot;: &quot;GitHub Desktop Log&quot;, &quot;category&quot;: &quot;file:present&quot;, &quot;description&quot;: &quot;log present&quot;, &quot;path&quot;: rel})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# Specific important files&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for rel, label in interesting:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;n = prefix + rel if prefix else rel&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;zi = z.getinfo(n)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;naive = datetime(*zi.date_time)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts = naive.replace(tzinfo=timezone.utc).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;markers.append({&quot;timestamp&quot;: ts.isoformat(), &quot;source&quot;: label, &quot;category&quot;: &quot;file:present&quot;, &quot;description&quot;: f&quot;{label} present&quot;, &quot;path&quot;: rel})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except KeyError:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# MANIFESTs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for n in z.namelist():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if n.endswith(&quot;/&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;rel = n[len(prefix):] if n.startswith(prefix) else n&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if &quot;MANIFEST&quot; in rel and (&quot;leveldb&quot; in rel.lower() or &quot;IndexedDB&quot; in rel):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;zi = z.getinfo(n)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;naive = datetime(*zi.date_time)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;ts = naive.replace(tzinfo=timezone.utc).astimezone(get_tz(tz_name))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;markers.append({&quot;timestamp&quot;: ts.isoformat(), &quot;source&quot;: &quot;LevelDB Manifest&quot;, &quot;category&quot;: &quot;file:present&quot;, &quot;description&quot;: &quot;LevelDB manifest present&quot;, &quot;path&quot;: rel})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return markers&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- Core analysis ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def analyze_zip(zip_path: Path, tz_name=&quot;UTC&quot;):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;work_dir = WORK / f&quot;case_{datetime.now().strftime('%Y%m%d_%H%M%S')}&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;extract_dir = work_dir / &quot;extracted&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;extract_dir.mkdir(parents=True, exist_ok=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with zipfile.ZipFile(zip_path, 'r') as z:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;z.extractall(extract_dir)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;root = extract_dir&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if (extract_dir / &quot;GitHub Desktop&quot;).exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;root = extract_dir / &quot;GitHub Desktop&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;parse_desktop_logs(root, events, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ck = parse_cookies(root / &quot;Network&quot; / &quot;Cookies&quot;, events, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;parse_json_events(root / &quot;Preferences&quot;, &quot;Preferences JSON&quot;, events, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;parse_json_events(root / &quot;Local State&quot;, &quot;Local State JSON&quot;, events, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;parse_quota_manager(root / &quot;WebStorage&quot; / &quot;QuotaManager&quot;, events, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# Username from logs&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;gh_user, user_meta = username_from_logs(root)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# Email + generalized FS markers from ZIP&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;email_info = scan_emails_from_zip(zip_path, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;fs_markers = scan_fs_markers_from_zip(zip_path, tz_name=tz_name)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events.extend(email_info[&quot;events&quot;])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events.extend(fs_markers)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;# sort + summarize&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events = [e for e in events if e.get(&quot;timestamp&quot;)]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;events.sort(key=lambda e: e[&quot;timestamp&quot;])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;from collections import Counter&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;counts = dict(Counter(e[&quot;source&quot;] for e in events))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;username = gh_user or (ck.get(&quot;dotcom_user&quot;) if isinstance(ck, dict) else None)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;summary = {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;events&quot;: len(events),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;github_username&quot;: username,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;github_username_source&quot;: &quot;logs&quot; if gh_user else (&quot;cookie&quot; if username else None),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;cookie_domains&quot;: ck.get(&quot;domains&quot;, []) if isinstance(ck, dict) else [],&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;counts&quot;: counts,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;primary_email&quot;: email_info.get(&quot;primary_email&quot;),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;noreply_emails&quot;: email_info.get(&quot;noreply_emails&quot;, []),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;tz&quot;: tz_name,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return root, events, summary, work_dir&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;# ---------- UI ----------&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;HTML = &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;title&amp;gt;GitHub Desktop Forensic Timeline&amp;lt;/title&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 24px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;h1 { margin-bottom: 0; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.meta { color: #666; margin: 4px 0 16px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.container { max-width: 1200px; margin: auto; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.upload { border: 2px dashed #cbd5e1; border-radius: 12px; padding: 16px; margin: 16px 0; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.cards { display:grid; grid-template-columns: repeat(auto-fit,minmax(220px,1fr)); gap: 12px; margin: 12px 0 24px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.card { border: 1px solid #eee; border-radius: 12px; padding: 12px; box-shadow: 0 1px 4px rgba(0,0,0,.04); }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.muted { color:#666; font-size: 12px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.tag { display:inline-block; background:#f1f5f9; padding:2px 8px; border-radius:999px; font-size: 12px; margin-right:4px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;table { width: 100%; border-collapse: collapse; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;th, td { padding: 8px; border-bottom: 1px solid #eee; font-size: 14px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;th { background: #fafafa; position: sticky; top: 0; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.path { color:#555; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.footer { margin-top: 32px; color:#777; font-size: 12px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.btn { display:inline-block; padding:8px 12px; background:#111827; color:#fff; border-radius:10px; text-decoration:none; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.row { margin: 8px 0; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.pill { background:#eef; padding:2px 6px; border-radius:8px; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.subtle { color:#334155; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;.tz { font-size: 12px; color:#475569; }&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;
&lt;script src=&quot;&amp;lt;a href=https://cdn.jsdelivr.net/npm/chart.js&amp;gt;https://cdn.jsdelivr.net/npm/chart.js&amp;lt;/a&amp;gt;&quot;&gt;&lt;/script&gt;
&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;h1&amp;gt;GitHub Desktop Forensic Timeline&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;meta&quot;&amp;gt;Upload a ZIP of C:\\Users\\&amp;amp;lt;User&amp;amp;gt;\\AppData\\Roaming\\GitHub Desktop &amp;rarr; visual timeline + username/email discovery.&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;upload&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;form method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;&amp;lt;strong&amp;gt;Upload profile ZIP&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;&amp;lt;input type=&quot;file&quot; name=&quot;zipfile&quot; required /&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;Timezone:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;select name=&quot;tz&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;option value=&quot;Asia/Seoul&quot;&amp;gt;Asia/Seoul&amp;lt;/option&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;option value=&quot;UTC&quot;&amp;gt;UTC&amp;lt;/option&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;option value=&quot;America/Los_Angeles&quot;&amp;gt;America/Los_Angeles&amp;lt;/option&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;option value=&quot;Europe/London&quot;&amp;gt;Europe/London&amp;lt;/option&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;button class=&quot;btn&quot; style=&quot;margin-left:8px;&quot;&amp;gt;Analyze&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{% if summary %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;tz&quot;&amp;gt;Using timezone: {{ summary.tz }}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;cards&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Total Events&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div style=&quot;font-size:28px;&quot;&amp;gt;{{ summary.events }}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;muted&quot;&amp;gt;timeline rows&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;GitHub Username&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div style=&quot;font-size:20px;&quot;&amp;gt;{{ summary.github_username or &quot;&amp;lt;span class='muted'&amp;gt;not found&amp;lt;/span&amp;gt;&quot; | safe }}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;muted&quot;&amp;gt;source: {{ summary.github_username_source or &quot;n/a&quot; }}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Primary Email&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;subtle&quot; style=&quot;font-size:16px;&quot;&amp;gt;{{ summary.primary_email or &quot;&amp;lt;span class='muted'&amp;gt;not found&amp;lt;/span&amp;gt;&quot; | safe }}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;muted&quot;&amp;gt;detected from ZIP contents (original file timestamps)&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Noreply Emails&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;{% if summary.noreply_emails %}{% for d in summary.noreply_emails[:4] %}&amp;lt;span class=&quot;pill&quot;&amp;gt;{{ d }}&amp;lt;/span&amp;gt; {% endfor %}{% else %}&amp;lt;span class=&quot;muted&quot;&amp;gt;none&amp;lt;/span&amp;gt;{% endif %}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;&amp;lt;strong&amp;gt;Sources&amp;lt;/strong&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div&amp;gt;{% for k,v in summary.counts.items() %}&amp;lt;span class=&quot;tag&quot;&amp;gt;{{k}}: {{v}}&amp;lt;/span&amp;gt;{% endfor %}&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;canvas id=&quot;eventsPerDay&quot; height=&quot;100&quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;h2&amp;gt;Timeline&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;table&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;thead&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Timestamp ({{ summary.tz }})&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Source&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Category&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Description&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Path&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{% for e in events %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&amp;lt;td&amp;gt;{{ e.timestamp }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&amp;lt;td&amp;gt;{{ e.source }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&amp;lt;td&amp;gt;{{ e.category }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&amp;lt;td&amp;gt;{{ e.description }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&amp;lt;td class=&quot;path&quot;&amp;gt;{{ e.path }}&amp;lt;/td&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{% endfor %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;lt;div class=&quot;footer&quot;&amp;gt;FS markers are generalized and use ZIP entry times (no hardcoded dates, better across samples).&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;{% if events %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;const events = {{ events|tojson }};&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;const counts = {};&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for (const e of events) {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;const d = e.timestamp.slice(0,10);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;counts[d] = (counts[d] || 0) + 1;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;const labels = Object.keys(counts).sort();&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;const data = labels.map(k =&amp;gt; counts[k]);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;new Chart(document.getElementById('eventsPerDay').getContext('2d'), {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;type: 'bar',&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;data: { labels, datasets: [{ label: 'Events per day', data }] },&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;options: { responsive: true, scales: { x: { ticks: { autoSkip: true, maxRotation: 0 }}}}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &lt;/span&gt;{% endif %}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;app = Flask(__name__)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;@app.route(&quot;/&quot;, methods=[&quot;GET&quot;,&quot;POST&quot;])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def index():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if request.method == &quot;POST&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;f = request.files.get(&quot;zipfile&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;tz = request.form.get(&quot;tz&quot;, &quot;UTC&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return &quot;No file&quot;, 400&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;save_path = UPLOADS / f.filename&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;f.save(save_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return redirect(url_for(&quot;case&quot;, filename=f.filename, tz=tz))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return render_template_string(HTML, summary=None, events=None)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;@app.route(&quot;/case/&amp;lt;filename&amp;gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def case(filename):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;tz = request.args.get(&quot;tz&quot;, &quot;UTC&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;zip_path = UPLOADS / filename&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not zip_path.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return &quot;Not found&quot;, 404&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;root, events, summary, _ = analyze_zip(zip_path, tz_name=tz)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return render_template_string(HTML, summary=type(&quot;Obj&quot;,(object,),summary), events=events)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if __name__ == &quot;__main__&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;app.run(host=&quot;0.0.0.0&quot;, port=8000, debug=False)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Table &lt;/span&gt;&lt;span&gt;&lt;span&gt;23&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;바이브 코딩을 통한 타임라인 분석 소스코드&lt;/p&gt;</description>
      <category>Forensics/DFC</category>
      <category>DFC</category>
      <category>DFC2025</category>
      <category>디지털포렌식</category>
      <category>디지털포렌식챌린지</category>
      <category>디포챌</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/597</guid>
      <comments>https://pental.tistory.com/597#entry597comment</comments>
      <pubDate>Mon, 20 Apr 2026 21:02:31 +0900</pubDate>
    </item>
    <item>
      <title>[2025 DFC] 2025 디지털포렌식 챌린지 - 203 - Ooops, your files have ben encrypted!</title>
      <link>https://pental.tistory.com/596</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Step-by-step methodology:&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;277&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mGDJc/dJMcabKIMLA/RhuWDm00GElk54iv12h3rK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mGDJc/dJMcabKIMLA/RhuWDm00GElk54iv12h3rK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mGDJc/dJMcabKIMLA/RhuWDm00GElk54iv12h3rK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmGDJc%2FdJMcabKIMLA%2FRhuWDm00GElk54iv12h3rK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;277&quot; height=&quot;68&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&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;355&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZuD8H/dJMcabKIMLF/5uijQIOQYkykQI6qykiAUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZuD8H/dJMcabKIMLF/5uijQIOQYkykQI6qykiAUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZuD8H/dJMcabKIMLF/5uijQIOQYkykQI6qykiAUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZuD8H%2FdJMcabKIMLF%2F5uijQIOQYkykQI6qykiAUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;119&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; HashTab&lt;/span&gt;을 이용한 해시 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일의 해시값과 다운로드 받은 파일의 해시값이 &lt;span&gt;A530D2ABDEBF60EE0D81B7DC6ED92C7A&lt;/span&gt;으로 동일함을 확인하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반디집 프로그램을 통해&lt;span&gt; PD12M_dataset.zip.enc &lt;/span&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;453&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKs5xI/dJMcajhBAzX/GEQQpIw27Yven22cJtkMNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKs5xI/dJMcajhBAzX/GEQQpIw27Yven22cJtkMNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKs5xI/dJMcajhBAzX/GEQQpIw27Yven22cJtkMNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKs5xI%2FdJMcajhBAzX%2FGEQQpIw27Yven22cJtkMNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;219&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;반디집을 통해&lt;span&gt; PD12M_dataset.zip.enc &lt;/span&gt;파일 열기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오류에서 확인되는 내용은 &lt;span&gt;&amp;ldquo;&lt;/span&gt;이 파일은 손상된 파일입니다&lt;span&gt;.&amp;rdquo; &lt;/span&gt;이며&lt;span&gt;, &lt;/span&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;453&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQ9NyY/dJMcajhBAz1/VTDSwWkRO7cSl7mjhZE54K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQ9NyY/dJMcajhBAz1/VTDSwWkRO7cSl7mjhZE54K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQ9NyY/dJMcajhBAz1/VTDSwWkRO7cSl7mjhZE54K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQ9NyY%2FdJMcajhBAz1%2FVTDSwWkRO7cSl7mjhZE54K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;180&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;그림&lt;span&gt; 3&lt;/span&gt;에서 확인 버튼 클릭 후 보여지는 화면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추출할 수 있는 데이터는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FileName&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;012.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;013.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;014.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;015.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;016.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;017.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;018.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;019.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;020.jpg&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;반디집을 통해 &lt;span&gt;PD12M_dataset.zip.enc &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;453&quot; data-origin-height=&quot;181&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XraWt/dJMcajhBAz5/IGu336kA9sbk723GnyTyD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XraWt/dJMcajhBAz5/IGu336kA9sbk723GnyTyD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XraWt/dJMcajhBAz5/IGu336kA9sbk723GnyTyD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXraWt%2FdJMcajhBAz5%2FIGu336kA9sbk723GnyTyD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;181&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;181&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;그림&lt;span&gt; 4&lt;/span&gt;에서 확인된 파일 추출 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 추출된&lt;span&gt; 020.jpg &lt;/span&gt;파일에서 확인 할 수 있듯&lt;span&gt;, &lt;/span&gt;제대로 추출되지 않음을 육안으로 확인 할 수 있다&lt;span&gt;. &lt;/span&gt;따라서 손상된&lt;span&gt; zip &lt;/span&gt;아카이브를 복구 하기 위해&lt;span&gt; zip&lt;/span&gt;도구를 사용한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;zip&lt;/span&gt;도구의 강력모드인&lt;span&gt; -FF &lt;/span&gt;인자를 통해 복구된 결과를&lt;span&gt; temp.zip&lt;/span&gt;으로 출력하는 명령은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;zip -FF PD12M_dataset.zip.enc --out temp.zip&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKyHf6/dJMcacCQiB0/WMAyYAxEdTcknnDMDUrmuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKyHf6/dJMcacCQiB0/WMAyYAxEdTcknnDMDUrmuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKyHf6/dJMcacCQiB0/WMAyYAxEdTcknnDMDUrmuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKyHf6%2FdJMcacCQiB0%2FWMAyYAxEdTcknnDMDUrmuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;231&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;231&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; zip &lt;/span&gt;명령어를 사용한 강제 복구 과정 및 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 결과는 위 사진과 같으며&lt;span&gt; temp.zip&lt;/span&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;453&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8UzmV/dJMcaiXir5c/nz5knzqlZFhibxPE7NrhyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8UzmV/dJMcaiXir5c/nz5knzqlZFhibxPE7NrhyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8UzmV/dJMcaiXir5c/nz5knzqlZFhibxPE7NrhyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8UzmV%2FdJMcaiXir5c%2Fnz5knzqlZFhibxPE7NrhyK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;150&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&gt;&lt;span&gt; temp.zip &lt;/span&gt;에서 발견된&lt;span&gt; 46&lt;/span&gt;개의 데이터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총&lt;span&gt; 46&lt;/span&gt;개의 데이터를 확인할 수 있으며&lt;span&gt;, &lt;/span&gt;그중&lt;span&gt; 085&lt;/span&gt;번의 파일은&lt;span&gt; docx&lt;/span&gt;파일로 확인되었다&lt;span&gt;. &lt;/span&gt;해당&lt;span&gt; docx&lt;/span&gt;파일에서는&lt;span&gt; 100 &amp;ndash; A Key Too Familiar &lt;/span&gt;이라는 문제를 추가적으로 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;203&lt;/span&gt;번의 문제를 풀기 위해서는&lt;span&gt; 100&lt;/span&gt;번 문제를 필수적으로 풀어야 하기에&lt;span&gt;, &lt;/span&gt;해당 문제 풀이를 먼저 진행한다&lt;span&gt;. 100&lt;/span&gt;번 문제에서 확인 할 수 있는 내용은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Instructions&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;br /&gt;Description&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;당신은&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;컴퓨터에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;존재하는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;랜섬웨어&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;역공학&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;하였습니다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;결과&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;암호화에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;사용된&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;키는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;찾아낼&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;없었지만&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;랜섬웨어에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;취약점이&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;있음을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;확인하였습니다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;암호화된&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;파일들을&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;분석하여&lt;/span&gt;&lt;span&gt; FLAG&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;찾아내시기&lt;/span&gt;&lt;span&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;&lt;b&gt;&lt;span&gt;Hint.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;랜섬웨어는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;스트림&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;암호를&lt;/span&gt;&lt;span&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;&lt;span&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;FLAG&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;바탕화면에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;존재하는&lt;/span&gt;&lt;span&gt; FILE_H&lt;/span&gt;&lt;span&gt;에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;저장되어&lt;/span&gt;&lt;span&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;&lt;span&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;FILE_A ~ FILE_H&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt; ASCII &lt;/span&gt;&lt;span&gt;문자열로만&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;구성되어&lt;/span&gt;&lt;span&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;&lt;span&gt;&lt;span&gt;-&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;FLAG&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt; FILE_A ~ FILE_H &lt;/span&gt;&lt;span&gt;만으로도&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;획득&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;가능합니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;226&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Target&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;375&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Hash (MD5)&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;226&quot;&gt;&lt;span&gt;&lt;span&gt;Disk image (.img)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;375&quot;&gt;&lt;span&gt;&lt;span&gt;D330AF1D7D67349334F96B902652945D&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot; width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Download url: &lt;a href=&quot;https://www.dropbox.com/scl/fi/9u0jepu2z80mkvgdlg4ub/diskdump.img?rlkey=6x8mfdw557vkd29nmf3deqmpv&amp;amp;st=i9kf1zjy&amp;amp;dl=0&quot;&gt;https://www.dropbox.com/scl/fi/9u0jepu2z80mkvgdlg4ub/diskdump.img?rlkey=6x8mfdw557vkd29nmf3deqmpv&amp;amp;st=i9kf1zjy&amp;amp;dl=0&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;Credits&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;1)&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;FLAG&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;획득함&lt;/span&gt;&lt;span&gt; &lt;span&gt;(100 points)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드&lt;span&gt; URL&lt;/span&gt;을 통해 받은&lt;span&gt; diskdump.img &lt;/span&gt;파일과 문제에서 주어진&lt;span&gt; MD5&lt;/span&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;355&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pRlvx/dJMcacCQiCr/g89OMPuFJiOLDVsIbP74Mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pRlvx/dJMcacCQiCr/g89OMPuFJiOLDVsIbP74Mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pRlvx/dJMcacCQiCr/g89OMPuFJiOLDVsIbP74Mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpRlvx%2FdJMcacCQiCr%2Fg89OMPuFJiOLDVsIbP74Mk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;124&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/span&gt;&lt;span&gt; HashTab&lt;/span&gt;을 이용한&lt;span&gt; diskdump.img &lt;/span&gt;파일 해시 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운로드 받은 파일이 주어진 해시값 &lt;span&gt;D330AF1D7D67349334F96B902652945D&lt;/span&gt;과 동일함을 확인하였다&lt;span&gt;. &lt;/span&gt;해당&lt;span&gt; img &lt;/span&gt;파일을&lt;span&gt; FTK Imager&lt;/span&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;453&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1cXH0/dJMcad2Kt5q/ouWBj4rGwWKHybREV9wc0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1cXH0/dJMcad2Kt5q/ouWBj4rGwWKHybREV9wc0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1cXH0/dJMcad2Kt5q/ouWBj4rGwWKHybREV9wc0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1cXH0%2FdJMcad2Kt5q%2FouWBj4rGwWKHybREV9wc0K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;240&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/span&gt;&lt;span&gt; FTK Imager&lt;/span&gt;을 사용하여&lt;span&gt; diskdump.img &lt;/span&gt;인식 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;FTK Imager&lt;/span&gt;을 통해서&lt;span&gt; [NTFS]/[root]/Users/DFC/Desktop &lt;/span&gt;폴더에서&lt;span&gt; FILE_A ~ H.txt &lt;/span&gt;파일 총&lt;span&gt; 8&lt;/span&gt;개를 확인 할 수 있다&lt;span&gt;. &lt;/span&gt;또한&lt;span&gt; [NTFS]/[root]/Users/DFC/Downloads &lt;/span&gt;폴더에서 각 프로그램 설치파일 또한&lt;span&gt; enc &lt;/span&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;453&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Xt4H/dJMcacCQiCz/RbgwgwwAk1ekveXuO31xB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Xt4H/dJMcacCQiCz/RbgwgwwAk1ekveXuO31xB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Xt4H/dJMcacCQiCz/RbgwgwwAk1ekveXuO31xB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Xt4H%2FdJMcacCQiCz%2FRbgwgwwAk1ekveXuO31xB1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;91&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;91&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Downloads &lt;/span&gt;폴더에서 &lt;span&gt;확인된 암호화된 파일들&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석을 위해서&lt;span&gt; Everything-1.4.1.1005.x64-Setup.exe, python-3.13.3-amd64.exe, node-v22.16.0-x64.msi &lt;/span&gt;파일을 공식 홈페이지를 통해서 다운로드 했다&lt;span&gt;. &lt;/span&gt;아래는 각 다운로드 버전 및 링크이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;94&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FileName&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;113&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Version&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;393&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;URL&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;94&quot;&gt;&lt;span&gt;&lt;span&gt;Everything&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;113&quot;&gt;&lt;span&gt;&lt;span&gt;1.4.1.1005.x64&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;a href=&quot;https://www.voidtools.com/ko-kr/support/everything/previous_versions/&quot;&gt;https://www.voidtools.com/ko-kr/support/everything/previous_versions/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;94&quot;&gt;&lt;span&gt;&lt;span&gt;python&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;113&quot;&gt;&lt;span&gt;&lt;span&gt;3.13.3-amd64&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;a href=&quot;https://www.python.org/downloads/release/python-3133/&quot;&gt;https://www.python.org/downloads/release/python-3133/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;94&quot;&gt;&lt;span&gt;&lt;span&gt;node&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;113&quot;&gt;&lt;span&gt;&lt;span&gt;v22.16.0&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;393&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;a href=&quot;https://nodejs.org/en/blog/release/v22.16.0/&quot;&gt;https://nodejs.org/en/blog/release/v22.16.0/&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;분석을 위해 사용된 설치 파일 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스에서는 랜섬웨어가 스트림 암호를 사용했다는 것이 주어졌고&lt;span&gt;, &lt;/span&gt;동일한 키스트림을 여러 파일에 재 사용했다고 전재하고 시작한다&lt;span&gt;. &lt;/span&gt;따라서 각 암호화된 파일과 원본에 대해서&lt;span&gt; XOR &lt;/span&gt;연산결과를 비교하여 키스트림 추출을 진행한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;encrypted_file = &quot;python-3.13.3-amd64.exe.enc&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;original_file = &quot;python-3.13.3-amd64.exe&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;keystream_output = &quot;python-keystream&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;with open(encrypted_file, &quot;rb&quot;) as enc_fp, open(original_file, &quot;rb&quot;) as orig_fp:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; enc_data = enc_fp.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; orig_data = orig_fp.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if len(enc_data) != len(orig_data):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(f&quot;[!] Warning: File sizes are off ({len(enc_data)} vs {len(orig_data)}), will chop to the shorter one.&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;length = min(len(enc_data), len(orig_data))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;keystream = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;for i in range(length):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; keystream.append(enc_data[i] ^ orig_data[i])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;xor_result = bytes(keystream)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;with open(keystream_output, &quot;wb&quot;) as out_fp:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; out_fp.write(xor_result)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;print(f&quot;[+] XOR complete. Output written to '{keystream_output}' ({len(xor_result)} bytes).&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt; XOR &lt;/span&gt;연산을 통한 키스트림 추출 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 수행한 결과&lt;span&gt; python-keystream &lt;/span&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;354&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sifXB/dJMcacCQiCD/Kz7vRvpMpnPGkjWfo0NBx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sifXB/dJMcacCQiCD/Kz7vRvpMpnPGkjWfo0NBx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sifXB/dJMcacCQiCD/Kz7vRvpMpnPGkjWfo0NBx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsifXB%2FdJMcacCQiCD%2FKz7vRvpMpnPGkjWfo0NBx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;354&quot; height=&quot;122&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;추출된&lt;span&gt; keystream&lt;/span&gt;의 해시값 정보&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FileName&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;python-keystream&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;FileSize&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;28,640,016 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;232D6D772CBFFA2A512BCB0C90062165&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;SHA-1&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;A17A73FAE191A54651C9DABEB4F1A89EB21CAB55&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/span&gt;&lt;span&gt; keystream&lt;/span&gt;의 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추출된 키스트림을 바탕으로 바탕화면에 존재하는&lt;span&gt; FILE_A ~ H.txt &lt;/span&gt;파일 복호화를 진행한다&lt;span&gt;. &lt;/span&gt;다음은 복호화에 사용한 코드이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;import pathlib&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;keystream_path = &quot;python-keystream&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;encrypted_files = [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_A.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_B.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_C.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_D.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_E.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_F.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_G.txt.enc&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;FILE_H.txt.enc&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;output_path = &quot;TEMP.txt&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; ks_bytes = pathlib.Path(keystream_path).read_bytes()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;except Exception as e:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(f&quot;Error: Couldn't read keystream file &amp;ndash; {e}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; exit(1)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;with open(output_path, &quot;wb&quot;) as out_file:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; for enc_filename in encrypted_files:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; encrypted_data = pathlib.Path(enc_filename).read_bytes()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except FileNotFoundError:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;(!) Skipping missing file: {enc_filename}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; except Exception as e:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;(!) Error reading {enc_filename}: {e}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; usable_len = min(len(encrypted_data), len(ks_bytes))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; decrypted = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for i in range(usable_len):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; decrypted.append(encrypted_data[i] ^ ks_bytes[i])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; out_file.write(bytes(decrypted))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;print(f&quot;Decryption done. Combined output written to '{output_path}'&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/span&gt;&lt;span&gt; FILE_A ~ H.txt &lt;/span&gt;파일 복호화를 위해 사용된 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드를 실행한 결과&lt;span&gt; temp.txt &lt;/span&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;453&quot; data-origin-height=&quot;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LVYxJ/dJMcab4YLO4/OkdMqKJLsZqchvGJ3iEms0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LVYxJ/dJMcab4YLO4/OkdMqKJLsZqchvGJ3iEms0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LVYxJ/dJMcab4YLO4/OkdMqKJLsZqchvGJ3iEms0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLVYxJ%2FdJMcab4YLO4%2FOkdMqKJLsZqchvGJ3iEms0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;157&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;157&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; temp.txt &lt;/span&gt;에서 확인 된 평문 메시지&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;Cryptographic algorithms must be used in strict compliance with the recommended requirements.In particular, take care with stream cipher to avoid vulnerabilities such as the many-time pad attack.OTP security dies once pads repeat; treat every pad as a single&lt;/span&gt;&lt;span&gt;‑&lt;/span&gt;&lt;span&gt;use consumable block of data.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;Reusing keystreams can lead to plaintext leaks. Update the key or change the mode before reusing.XORing two reused ciphertexts yields P1^P2; The guessed ciphertext can lead to a recovery.Reused pads turn pairs of ciphertexts into clues. With just one good ciphertext, you can decrypt the rest.By the way, one of the encrypted compressed files that should be on this computer is missing. Where is it?Flag: T29vcHMsIGZsYWch&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;span&gt; temp.txt &lt;/span&gt;파일의 평문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Flag&lt;/span&gt;는 &lt;span&gt;T29vcHMsIGZsYWch &lt;/span&gt;으로 적혀있으며&lt;span&gt; base64&lt;/span&gt;를 통해 인코딩 된 것을 확인하였다&lt;span&gt;. base64decode.org &lt;/span&gt;를 통해 온라인&lt;span&gt; base64 &lt;/span&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;453&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcwdTo/dJMcaiJLxGm/xlsC9W1DKOIjmbhswKybL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcwdTo/dJMcaiJLxGm/xlsC9W1DKOIjmbhswKybL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcwdTo/dJMcaiJLxGm/xlsC9W1DKOIjmbhswKybL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcwdTo%2FdJMcaiJLxGm%2FxlsC9W1DKOIjmbhswKybL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;335&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;335&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;span&gt; base64decode.org&lt;/span&gt;를 이용한 복호화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답&lt;span&gt; : Ooops, flag!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시&lt;span&gt; 203&lt;/span&gt;번 문제로 돌아와&lt;span&gt; zip&lt;/span&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;453&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNew6j/dJMcagearYn/ZkKNyRIjCKEkj6nlOstuIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNew6j/dJMcagearYn/ZkKNyRIjCKEkj6nlOstuIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNew6j/dJMcagearYn/ZkKNyRIjCKEkj6nlOstuIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNew6j%2FdJMcagearYn%2FZkKNyRIjCKEkj6nlOstuIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;139&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;139&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; keystream &lt;/span&gt;분석 과정 좌&lt;span&gt; node, &lt;/span&gt;우&lt;span&gt; python&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;453&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mgNB1/dJMcab4YLPo/MyoZLwxpYY0oGmfVHMXD00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mgNB1/dJMcab4YLPo/MyoZLwxpYY0oGmfVHMXD00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mgNB1/dJMcab4YLPo/MyoZLwxpYY0oGmfVHMXD00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmgNB1%2FdJMcab4YLPo%2FMyoZLwxpYY0oGmfVHMXD00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;138&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 27BA74 &lt;/span&gt;이후 두 키스트림의 차이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오프셋&lt;span&gt; 27BA74&lt;/span&gt;부분까지&lt;span&gt; node &lt;/span&gt;키스트림과&lt;span&gt; python &lt;/span&gt;키스트림이 동일한 것을 확인하였다&lt;span&gt;. &lt;/span&gt;하지만&lt;span&gt; python&lt;/span&gt;에서는&lt;span&gt; 27BA74 &lt;/span&gt;이후 부분이&lt;span&gt; 00&lt;/span&gt;으로 되어 있고&lt;span&gt;, node &lt;/span&gt;부분에는 데이터가 있는 것을 확인하였다&lt;span&gt;. &lt;/span&gt;이 분석을 통해서 키스트림과 널바이트의 상관 관계 분석을 진행하였으며&lt;span&gt;, &lt;/span&gt;그 결과&lt;span&gt; python-keystream&lt;/span&gt;에서는&lt;span&gt; 0x27BA74&lt;/span&gt;부분의&lt;span&gt; 2&lt;/span&gt;배인&lt;span&gt; 0x4F74E8 &lt;/span&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;453&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezLHc0/dJMcaiJLxIf/B4QHlWvGVxVmqvThHUgcuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezLHc0/dJMcaiJLxIf/B4QHlWvGVxVmqvThHUgcuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezLHc0/dJMcaiJLxIf/B4QHlWvGVxVmqvThHUgcuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezLHc0%2FdJMcaiJLxIf%2FB4QHlWvGVxVmqvThHUgcuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;233&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;오프셋&lt;span&gt; 27BA74&lt;/span&gt;에서 확인된 동일한 키스트림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 확인했던&lt;span&gt; 46&lt;/span&gt;개의 데이터에서 숫자 연속성이 깨지는 부분을 확인하였으며&lt;span&gt;, 001.jpg ~ 011.jpg, 021.jpg ~ 028.jpg, 038.jpg ~ 046.jpg, 057.jpg ~ 062.jpg, 071.jpg ~ 081.jpg, 092.jpg ~ 100.jpg &lt;/span&gt;가 누락된 것을 확인 할 수 있다&lt;span&gt;. &lt;/span&gt;따라서 주어진&lt;span&gt; enc &lt;/span&gt;파일에&lt;span&gt; 020.jpg &lt;/span&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;453&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTxhPx/dJMcab4YLPz/kuQ5E1zh9NHitMmh0yVn5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTxhPx/dJMcab4YLPz/kuQ5E1zh9NHitMmh0yVn5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTxhPx/dJMcab4YLPz/kuQ5E1zh9NHitMmh0yVn5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTxhPx%2FdJMcab4YLPz%2FkuQ5E1zh9NHitMmh0yVn5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;126&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 020.jpg &lt;/span&gt;를 검색한 모습&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;020.jpg &lt;/span&gt;다음으로 발견되는&lt;span&gt; jpg &lt;/span&gt;문자열은&lt;span&gt; 029.jpg&lt;/span&gt;이다&lt;span&gt;. &lt;/span&gt;따라서&lt;span&gt; 020.jpg &lt;/span&gt;내용부터&lt;span&gt; 029.jpg&lt;/span&gt;가 발견된 부분을 따로 저장해 분석을 진행했다&lt;span&gt;. (0x1DF40F ~ 0x2DE60D)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복호화에 사용한 키스트림의 길이와 시작 위치를 찾기 위해 키스트림 파일&lt;span&gt;(key)&lt;/span&gt;을 이용한&lt;span&gt; XOR &lt;/span&gt;브루트포스 복호화 실험을 수행하였다&lt;span&gt;. &lt;/span&gt;우선&lt;span&gt; key &lt;/span&gt;파일의 앞부분을 이용해 암호화된&lt;span&gt; ZIP &lt;/span&gt;파일 전체를&lt;span&gt; XOR&lt;/span&gt;으로 복호화해 보았고&lt;span&gt;, &lt;/span&gt;복호화가 정상적으로 진행되는 시작 지점이&lt;span&gt; 0x1DF40F&lt;/span&gt;에서&lt;span&gt; 1079&lt;/span&gt;바이트 떨어진 위치임을 확인하였다&lt;span&gt;. &lt;/span&gt;이를 통해 총 키 길이가&lt;span&gt; 0x1DF40F + 1079 = 1,964,102&lt;/span&gt;바이트로 추정되었다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키스트림이 순환 특성을 가지므로 실제 암호화의 시작점이 위에서 구한 길이보다 얼마만큼 더 떨어져 있을 수 있음을 고려해야 했다&lt;span&gt;. &lt;/span&gt;특히 시작 위치가&lt;span&gt; 4096&lt;/span&gt;바이트 단위로 어긋날 가능성이 있어&lt;span&gt;, &lt;/span&gt;스크립트를 일반화하고 브루트포스 방식으로 여러 후보 길이를 시도하도록 확장하였다&lt;span&gt;. &lt;/span&gt;키 길이를 늘려가며 각 경우에 대해 복호화 파일을 생성하였다&lt;span&gt;. &lt;/span&gt;그 결과 생성된&lt;span&gt; ZIP&lt;/span&gt;들 가운데 &lt;span&gt;1&lt;/span&gt;개 파일이 정상적으로 압축해제 되었고&lt;span&gt; 100&lt;/span&gt;장의 이미지 파일을 복구할 수 있었다&lt;span&gt;. &lt;/span&gt;사용한 코드는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;def _xor_bytes(data, key):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; if not key:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; raise ValueError(&quot;&lt;/span&gt;키가 비어있습니다&lt;span&gt;: 'python-keystream' &lt;/span&gt;파일을 확인하세요&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; out = bytearray(len(data))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; klen = len(key)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; for idx in range(len(data)):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; out[idx] = data[idx] ^ key[idx % klen]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; return bytes(out)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;with open('python-keystream', 'rb') as kf:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; keystream = kf.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;with open('PD12M_dataset.zip.enc', 'rb') as ef:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; encrypted = ef.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;for i in range(0, 100) :&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; part_len = 982051 + 2048 * i&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; prefix = keystream[:part_len]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; pad_unit = b'\x00'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; zeros = pad_unit * part_len&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; predict_key = prefix + zeros&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; decrypted = _xor_bytes(encrypted, predict_key)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; out_name = f'decrypted_{i}.zip'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; with open(out_name, 'wb') as out_f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; out_f.write(decrypted)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/span&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;453&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BzaTf/dJMcaibZSat/yQ5ACiCf85lwqg8Nkp56j1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BzaTf/dJMcaibZSat/yQ5ACiCf85lwqg8Nkp56j1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BzaTf/dJMcaibZSat/yQ5ACiCf85lwqg8Nkp56j1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBzaTf%2FdJMcaibZSat%2FyQ5ACiCf85lwqg8Nkp56j1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;199&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;코드 실행 후&lt;span&gt; 100&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;453&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2znes/dJMcaibZSaw/gyBKa7HKLS2a4wUhi9IUKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2znes/dJMcaibZSaw/gyBKa7HKLS2a4wUhi9IUKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2znes/dJMcaibZSaw/gyBKa7HKLS2a4wUhi9IUKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2znes%2FdJMcaibZSaw%2FgyBKa7HKLS2a4wUhi9IUKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;228&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;19&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;추출된&lt;span&gt; 100&lt;/span&gt;개의 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복구 된 파일은 총&lt;span&gt; 100&lt;/span&gt;개 이며 각 파일 이름 및 해시값은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FileName&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;background-color: #e7e6e6;&quot; width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SHA256&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;000.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e55d9e636ce8197ecad3c52b1073de098e28cd9a02c035a1f5ada5c186c3e086&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;001.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;54272c394e867833f17099d1fd2462c9562ff33397eda9795a9a2280808b2915&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;002.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;432e775467541125a8923bad3646a51688ccc7af08562ff5670faba1490ab71f&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;003.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;bad50ba579e971f73942f90a9c014bc52fef02c56155fdc600c6f262a7cd75c4&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;004.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7602d9134fb58ac8433081e3161de088ba54da857056c31c04b20a9a924629bf&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;005.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f4136cefc4c29775390075e25eece8fd2a62dccd466969d9f0dcc02d5e11e8df&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;006.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8488fcfe4dc24d5ffe0d1dcb42dc8662b04978cf55c540c98991177f164fcd64&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;007.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;420da57b90142851499968f85dc99616b103febbb60ace31cab72b64d9076700&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;008.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e2a648f9729b029f3f53329409aca962d98f7763d8110f93d8ffdd882a402233&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;009.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;41891d418c99586c508cf3947426761933f200e37c68ef4776816b8fe0c6e2b4&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;010.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;73b060e408f0bf8c2133d6b5bb4fefb191ccfcd108f28e90b98331797c743016&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;011.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;93e76032b7a0f0db464b5e004859f09576485e5370fdab102b7305d63638354a&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;012.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;65c682f04647569debbc5f321d43a18c10617ea180e7db6cf45e23c0f1090e7a&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;013.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;75116d1266299dd256eb9e00dffeae90054c725c9b7b4718d9903f9537675711&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;014.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;a1e51ea589d0d69757065365b845fe550a1848c962dccd4f8b81d1f0ddef1155&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;015.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;25121a3273ee88f0df1337d35aad7f3b7f10b84edfa1814b298eed43f88bd11a&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;016.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;12ed595337cef2251e9fc6ac12d592264847ffbc9e07e788988b8bf54ee5db38&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;017.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9517cfe1e757e16eff5e3259ef8ee83fd98a40af9b954e807894382bac3fc9c0&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;018.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;d378aa5496e30b4f2f498966e5f7c608c3b86bd1c0f1d748ea1c487db8dac335&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;019.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;677ec871700acd0e0ce6b0e1f3068109438f88ce3d0cd39b895ae53c000c9042&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;020.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;283f9dba470570467c661b18dbba9cf1007d7342334e8187437ff9ea7fe2429a&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;021.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;54b63d61782c384e4bed74b7b0e984f4d7ac6e954f649f8542450cd074060366&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;022.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;32f8e76a8973c98b1400634c84917c5d6ef1468dfbbd44f271823e3cca708f42&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;023.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;bc2396495058e8b02717a58be4fad9d1c14ddcf4319e611093d30b5736851083&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;024.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;a123d84525160846f58bb2551e6a01091c871f10e835f9bb65299734bbbcabec&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;025.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;70a0678489b8dc88b63803110ec8d1b8b34888607da479b5d7b102bb6725a759&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;026.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5ef67a9a3b0f7c1f404f82f17365fe1991f44a94d85f84eeee651c252bae4575&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;027.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e553fbb2d611ec2fc617c5b5e4f4e08e5b8094b55ac594191b6e1e4c4eea4d13&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;028.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7cd5ca48fca223a182bc10e0730247e85e4694e21f19444382c23f6df90912c3&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;029.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;119bf2d66f4226b8309dfc1e3763de5061bea8bec3379f76a17a12380db0fc7e&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;030.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3e2863569378a3c1ad574352e5c040ace6146956f1fd70f7b03c52f292bce673&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;031.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8db8a962144e815483844703ac04e5668b994289a631f4a47ac436b9d2bc5a20&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;032.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1a29041185e7ceaa3684f91edcfead59a17b9b392e0aa21c97a340e4e01abb8e&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;033.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;54402ef3e746e4fafe11b8e62851f37901e3186277f75227d346d8007f2f9fe6&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;034.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;952a3b521a166c9a0298ecd6b4b6c984e64dd230cc2780d3b7eb0e74207e9956&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;035.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e4fa96b54edd334969c1befabc50642caf4ea317f34b4c6137353b58a20c3a7f&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;036.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;95a1dc9c7b613f7692d12cb9af04b9148fdafe122cea4b4bce72cf582c96e43c&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;037.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8a121ea8fe8a812f70e25d39eac401e4e76d6dd7097a3be33b23b8d1de47008e&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;038.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;51e688aa7eba6be0fec1986f23b3a621ac8186c2d26bbe9955e58063713d5599&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;039.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f63c4e097b374e37256e5343a5d6c7258fd0403ce3e7e635baa6f949c4be37cc&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;040.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f8fe607f1299b595fc6284fa9f806b1214ff4fab6eae45f07a162d884dbdf378&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;041.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ad29d72b517e64d96553ade02aa3d9a315f539c84bed72c904a70398754a2f67&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;042.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1941f33daa2ed8ed046d449bf1e30bfa7b0b89bc55f4561d667c2147997df53d&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;043.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4f2e8ccafa0b37ee96729e4510f32d9f945dc5fdf46059f90d96cdb233883fe5&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;044.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cfade6a2cf26ea6b398605510d1365d17968439d70f4eede484e4a74a0dfd083&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;045.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;743e154ee31a780647770869fe1e81985430a403bf3d876932a34d309524970d&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;046.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5d2d7a738f6f7f2434e412ae13ff698e7e630f128db597ec7af219616d3a41ff&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;047.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4ae608c262f4a3690f76b6a4c43ce670b2a156be00dce90d1430fbadc21b1d68&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;048.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;575ef9765c2545e85391e608fdf9cd0f514f92bad34e6f8eb52ad4a6e3877750&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;049.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f5bc9f8cc2ed62e53dcb29c3cd8085c4015d2fbd59551dafd6ff0ef35b9efe9b&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;050.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f8a57d0643609ff2b7dd29a1a6b1a04a866540422d5d2113c717968147da157e&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;051.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9c47048b9f4cb927639a50b5ccec067f77b44eef7097cf827d6dd537066a4bd7&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;052.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e38209e2ad3df0b5c36b8cbf408d7063cca58c8e256686452535829d38aedf28&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;053.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ddaea6d062b8d2b5cf2c5a8971d6a5e90670c7b3181478b348f17feab8c0ac50&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;054.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;b2a813f44fda174f4dc553b9dea1f0349f526e3cde54ce0b09f7c30ad61349ef&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;055.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;43a721782cf0aa8153dd1208d96df75913b7cc1c4fa36e7c26160d7b1a3892bb&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;056.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4096de8557452cd4340a39f490d83d73db063379a1faa0c3aca56c676c3c358e&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;057.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6b2173ac8b74273df65bc6198ed78fe0ffa974a512ffe2a2ca219ccedc0fccd1&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;058.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;c0ec02162ead5297f463abcdc21d10f391f3e3f53f0520253407cd6f37fb0008&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;059.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f4881a1ddd87ae81366f9b67548fc62f9f27617d2c1b7599c7ec2cf164cf8976&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;060.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;69a1f40718d35c4c5cd3394b6063e2c9f0160d3610210d4ee9d222f3fa12f393&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;061.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;63919b22fdff3796c193bf7c22e8ef5f230088a62b3053fee5b865ebe0331a6d&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;062.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6f408488ab51d95d4b88ee3c3f950e4d30e096b7a8ee30b04e46e5719eafbaee&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;063.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f223e40609779931c233d3e520281083427d8dd21c767a837f283f9b354d9b2b&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;064.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;34c60e55adc557b77bda9a6bad312de6aa6d0cb5d9fd0ddecf83be2eaa82edf8&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;065.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6f70487ffb30962d737d3580ffcdeb0e980c93af9e015fa79d7f799f593967fb&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;066.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5e3fdc8a1c6348d990bcc164d0513d504d20d29374e3f2cff28b68eb18b02c57&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;067.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e16e05553c6f69260b463a16077a6601071bbde3ec9bdceae72f1066d25c871f&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;068.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9dc9d7d8476883476e517cfbcb9a3b56fc793d464403cb222f72696ab4034791&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;069.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dd5cae541faaaa5e51e649699838278e2374f4b496169756236a3c67b3b2d1e2&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;070.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ad7ffba7bae55a0772b4fdf74f960c687170a9c381c3781d7a332ab72340a873&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;071.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;b879856dc38bf5a0de6955ffc872811254f81783f47bf78449f771c598ce4066&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;072.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;17ba314bf7b7d5537edd42f1c5d93c2a25f3ba7af65487aa1bfbf9ca1b030ca0&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;073.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f0f3e4f2f2bc57a49d4d761ac603d4a079fac7702396dcb0ee3cb1c7fd1d893d&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;074.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ec915beb9e12f32d467298388ba678d933ba539cf92e104aaa2b281a5b3fe083&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;075.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;b1069fee3cdc995f2f93447501af29cdc8bbb8c8ee690f66757f6ab3415c89d6&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;076.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6e3baf882e5d310cdb59d95de5fd71baf6345b68c99d4eb2a205fea5f4759407&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;077.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;f5eecbd13cd597ee214ab788ccf9574f6d4ecb7d0da845678b0cf4605f8abebe&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;078.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2341b398277d2211453e6a8a4df61a6480a1643c5bee639bee3dbcedfca754cf&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;079.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7188c9059aabedcbd01770ba34184fd7ed3d7f02c5d6cadb29fd441b7c932602&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;080.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;49ad230c6c11ac9124768566f6b3cb57350a2648609251ddaebe5a5793eee2af&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;081.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9fb35e59bed3ada2069b707047a30c77d2fc4b5c5ccc0fc6aa15846564dcc8fa&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;082.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2383505b28b2b5e01d2457d646e50aa06843880607c54c957c2e5fe6d28b158f&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;083.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e0c55fbca33757cdde58c28a073e2ec6d8d18fb89f522c9a0e344b3c1939149d&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;084.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7c705703060c68b8af61dadcadaf497ef90541681711af66d2e41c6976516f8c&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;085 - A Key Too Familiar(ko,en).docx&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;70bf4cf76692accca06779b384d2281b3d96a9386ac593d75b3d7da55fac9a22&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;086.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;15d43227afc5cdbba30e36cd68c521d8132859d09a1e4c6963e61fe4f07a7f8b&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;087.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;26c866c5e9bdeaf211d52dbca62113bd167f5ef6f3226e0604639e8a35d1e6c3&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;088.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1a3ffe670cbe0603b53e2be18349578807495b0c4e92abea2f7c0f06e8df5b4c&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;089.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;76caa577d7f8a72bc16121f94ae9d8639353e354f52d5ade6de5114117cb1f38&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;090.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;c9dcd8d000bab94e0e4694d1fae8d52c09e91a55778dd6f28ae3f0b04ebf3c44&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;091.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ad8e0b8ee16970db43d683d82f5463eab8ae3dad260f8f51a924c71291821ac8&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;092.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;cf2e5b962894e317a139d8fcc66fcbcceec0c8e8d62c9627cb402f28e86f35c6&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;093.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;66e787c1d66cab51602ed86b3efe9b445105b1f624627f5203a46c8aff9b12b8&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;094.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;04b4b5b135e1da4848697bb7baef7cd8332a3b3d3e0ed716fa24ac7721a23046&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;095.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;e66a9a404bb8980e4bd498b8533bb6cdce4bf9a260e9692f07e5aad4414843ea&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;096.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2d228defbfafa7ba082be19dd25a51196d5136acde510fcc997b4523e96a6afe&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;097.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;0d1a2f1354b0a13ef2f6c66b2b7465f749d18aa24b64d8870788e60a078b30ab&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;098.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;848e1b11a6030a4d61672b9ad3fbba1309abd978e42f66f17016274e3c173f76&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;099.jpg&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;9bdc53c96af007c5887c33dbf8dfa5aee4e81a928ae3a9e8b4514cc02169ab0b&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Forensics/DFC</category>
      <category>DFC</category>
      <category>DFC2026</category>
      <category>디지털포렌식</category>
      <category>디지털포렌식챌린지</category>
      <category>디포챌</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/596</guid>
      <comments>https://pental.tistory.com/596#entry596comment</comments>
      <pubDate>Mon, 20 Apr 2026 20:58:15 +0900</pubDate>
    </item>
    <item>
      <title>[2025 DFC] 2025 디지털포렌식 챌린지 - 201 - Look at the Quote</title>
      <link>https://pental.tistory.com/595</link>
      <description>&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;background-color: #002060;&quot; width=&quot;601&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ffffff;&quot;&gt;Step-by-step methodology:&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;341&quot; data-origin-height=&quot;65&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKFw9n/dJMcacCQipH/KjVzMoA9E55kfLooWT6po1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKFw9n/dJMcacCQipH/KjVzMoA9E55kfLooWT6po1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKFw9n/dJMcacCQipH/KjVzMoA9E55kfLooWT6po1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKFw9n%2FdJMcacCQipH%2FKjVzMoA9E55kfLooWT6po1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;341&quot; height=&quot;65&quot; data-origin-width=&quot;341&quot; data-origin-height=&quot;65&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&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;355&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mufSh/dJMcacCQipR/QAFToO2UEJ6So7yEsz7bF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mufSh/dJMcacCQipR/QAFToO2UEJ6So7yEsz7bF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mufSh/dJMcacCQipR/QAFToO2UEJ6So7yEsz7bF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmufSh%2FdJMcacCQipR%2FQAFToO2UEJ6So7yEsz7bF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;123&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; hashtab &lt;/span&gt;을 사용한 &lt;span&gt;nal_unit.zip&lt;span&gt; &lt;/span&gt;&lt;/span&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;355&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/shyxo/dJMcaciwQIl/FK45IkV2bSbp1oZUYSiA2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/shyxo/dJMcaciwQIl/FK45IkV2bSbp1oZUYSiA2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/shyxo/dJMcaciwQIl/FK45IkV2bSbp1oZUYSiA2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fshyxo%2FdJMcaciwQIl%2FFK45IkV2bSbp1oZUYSiA2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;355&quot; height=&quot;126&quot; data-origin-width=&quot;355&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;&lt;span&gt;hashtab &lt;/span&gt;을 사용한 &lt;span&gt;sps-pps.zip &lt;/span&gt;의 해시 값&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대회에서 주어진 해시값과 다운 받은 파일을 &lt;span&gt;HashTab&lt;/span&gt;을 통해 해시값이 동일함을 확인하였다&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&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;453&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GnxMZ/dJMcaiC1zd4/UQfYJBo867jcdhKRa5BpKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GnxMZ/dJMcaiC1zd4/UQfYJBo867jcdhKRa5BpKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GnxMZ/dJMcaiC1zd4/UQfYJBo867jcdhKRa5BpKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGnxMZ%2FdJMcaiC1zd4%2FUQfYJBo867jcdhKRa5BpKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;177&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 4&lt;span&gt; nal-unit.zip &lt;/span&gt;압축 해제 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;nal-unit,zip&lt;/span&gt;을 압축 해제하면&lt;span&gt; 2&lt;/span&gt;개의 파일을 확인 할 수 있으며&lt;span&gt;, &lt;/span&gt;각각 파일에 대한 정보는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;FileName&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;problem1.avi&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;FileSize&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;9,717,752 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;00E3BCFC9FA9961F53999B6D836C5070&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt; problem1.avi &lt;/span&gt;&lt;span&gt;파일 정보&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;FileName&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;problem2.mp4&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;FileSize&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;6,194,586 &lt;/span&gt;바이트&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;MD5&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;0596CB493827E7F830B6D3EA3EE70D6D&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;비디오 길이&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;00:02:34&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;데이터 속도&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;252kbps&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;총 비트 전송률&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;253kbps&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;프레임 속도&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;301&quot;&gt;&lt;span&gt;&lt;span&gt;15.00 &lt;/span&gt;프레임&lt;span&gt;/&lt;/span&gt;초&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span&gt; problem2.mp4 &lt;/span&gt;파일 정보&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 파일 모두 재생이 불가능한 상태를 나타내고 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;sps-pps.zip &lt;/span&gt;파일을 압축 해제하면&lt;span&gt; 30&lt;/span&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;450&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOaxsJ/dJMcahqB5SL/Pe6RmO9hKvTKgtYzkI2kjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOaxsJ/dJMcahqB5SL/Pe6RmO9hKvTKgtYzkI2kjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOaxsJ/dJMcahqB5SL/Pe6RmO9hKvTKgtYzkI2kjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOaxsJ%2FdJMcahqB5SL%2FPe6RmO9hKvTKgtYzkI2kjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;196&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 5&lt;span&gt; sps-pps.zip &lt;/span&gt;압축 해제 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 풀이에 앞서&lt;span&gt; H.264 &lt;/span&gt;코덱의 설명은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;H.264/AVC(Advanced Video Coding)&lt;/span&gt;는&lt;span&gt; ITU-T Video Coding Experts Group&lt;/span&gt;과&lt;span&gt; ISO/IEC Moving Picture Experts Group&lt;/span&gt;에 의해 공동 개발된 비디오 압축 표준이다&lt;span&gt;. H.264&lt;/span&gt;는 이전 표준 대비 약&lt;span&gt; 50%&lt;/span&gt;의 비트레이트 절약을 제공하면서도 동일한 화질을 유지할 수 있는 고효율 압축 기술이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;특징&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;설명&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;계층적 구조&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;&lt;span&gt;Network Abstraction Layer(NAL)&lt;/span&gt;와&lt;span&gt; Video Coding Layer(VCL)&lt;/span&gt;로 분리&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;유연한 참조 프레임&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;다중 참조 프레임 지원으로 압축 효율성 향상&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;적응적 인트라 예측&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;&lt;span&gt;9&lt;/span&gt;가지&lt;span&gt; 4&amp;times;4 &lt;/span&gt;예측 모드와&lt;span&gt; 4&lt;/span&gt;가지&lt;span&gt; 16&amp;times;16 &lt;/span&gt;예측 모드&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;가변 블록 크기&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;&lt;span&gt;16&amp;times;16&lt;/span&gt;부터&lt;span&gt; 4&amp;times;4&lt;/span&gt;까지 다양한 블록 크기 지원&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;141&quot;&gt;&lt;span&gt;엔트로피 코딩&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;460&quot;&gt;&lt;span&gt;&lt;span&gt;CAVLC(Context Adaptive Variable Length Coding)&lt;/span&gt;와&lt;span&gt; CABAC(Context Adaptive Binary Arithmetic Coding) &lt;/span&gt;지원&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 3&lt;span&gt; H.264&lt;/span&gt;&lt;span&gt;의 특징 정리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;H.264/AVC&lt;/span&gt;는 현대 비디오 코덱의 표준 중 하나로&lt;span&gt;, &lt;/span&gt;디코딩을 위해서는&lt;span&gt; SPS/PPS&lt;/span&gt;와 같은 메타데이터가 반드시 필요하다&lt;span&gt;. &lt;/span&gt;전송&lt;span&gt;/&lt;/span&gt;저장 과정에서 이들&lt;span&gt; Parameter Set&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;b&gt;&lt;span&gt;1. SPS&lt;/span&gt;&lt;/b&gt;는 영상의 해상도&lt;span&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;&lt;b&gt;&lt;span&gt;2. PPS&lt;/span&gt;&lt;/b&gt;는 슬라이스 단위의 디코딩 파라미터&lt;span&gt;(&lt;/span&gt;엔트로피 코딩 모드&lt;span&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;이 두 메타데이터가 누락될 경우 디코더는 올바른 프레임 해석이 불가능해져&lt;span&gt;, &lt;/span&gt;화질 손상 또는 디코딩 불능 상태에 이르게 된다&lt;span&gt;. &lt;/span&gt;특히 네트워크 전송 과정이나 컨테이너 추출 과정에서&lt;span&gt; SPS/PPS&lt;/span&gt;가 손실되는 사례가 발생할 수 있으며&lt;span&gt;, &lt;/span&gt;이 경우 원본 스트림은 존재하더라도 재생이 불가능하다&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 문제풀이를 위해서 컨테이너 레벨에서&lt;span&gt; H.264 NAL &lt;/span&gt;스트림은 존재하나&lt;span&gt; SPS/PPS&lt;/span&gt;가 빠진 케이스를 대상으로&lt;span&gt;, &lt;/span&gt;외부에서 수집한&lt;span&gt; Parameter Set &lt;/span&gt;후보&lt;span&gt;(HED &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;b&gt;&lt;span&gt;Question 1. &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;첫 번째로 주어진 &lt;span&gt;H.264(problem1.avi)&lt;/span&gt;의 &lt;span&gt;SPS, PPS&lt;/span&gt;가 없는&lt;span&gt; NAL &lt;/span&gt;유닛을 디코딩 하여 영상에 기록된 철학자의 이름과 명언을 적어 제출 하시요&lt;span&gt;.(50 points)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;problem1.avi &lt;/span&gt;분석과정은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&lt;span&gt; ffprobe&lt;/span&gt;를 통해서 다음과 같은 특징을 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;$ ./ffprobe.exe -v quiet -print_format json -show_format -show_streams nal_unit/problem1.avi&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 4&lt;span&gt; ffprobe&lt;/span&gt;&lt;span&gt;를 이용한 &lt;span&gt;problem1.avi &lt;/span&gt;특징 분석 명령어&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;streams&quot;: [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;index&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_name&quot;: &quot;h264&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_long_name&quot;: &quot;H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_type&quot;: &quot;video&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag_string&quot;: &quot;x264&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag&quot;: &quot;0x34363278&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;width&quot;: 1280,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;height&quot;: 720,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;coded_width&quot;: 1280,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;coded_height&quot;: 720,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;has_b_frames&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;level&quot;: -99,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;refs&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;is_avc&quot;: &quot;false&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nal_length_size&quot;: &quot;0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;r_frame_rate&quot;: &quot;25/1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;avg_frame_rate&quot;: &quot;25/1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;time_base&quot;: &quot;1/25&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_pts&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration_ts&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;disposition&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;default&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dub&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;original&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;comment&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;lyrics&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;karaoke&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;forced&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;hearing_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;visual_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;clean_effects&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;attached_pic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;timed_thumbnails&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;non_diegetic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;captions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;descriptions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;metadata&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dependent&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;still_image&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;multilayer&quot;: 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;index&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_name&quot;: &quot;adpcm_ima_wav&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_long_name&quot;: &quot;ADPCM IMA WAV&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_type&quot;: &quot;audio&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag_string&quot;: &quot;[17][0][0][0]&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag&quot;: &quot;0x0011&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;sample_fmt&quot;: &quot;s16p&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;sample_rate&quot;: &quot;8000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;channels&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bits_per_sample&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;initial_padding&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;r_frame_rate&quot;: &quot;0/0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;avg_frame_rate&quot;: &quot;0/0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;time_base&quot;: &quot;8/125&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_pts&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bit_rate&quot;: &quot;32000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;extradata_size&quot;: 2,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;disposition&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;default&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dub&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;original&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;comment&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;lyrics&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;karaoke&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;forced&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;hearing_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;visual_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;clean_effects&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;attached_pic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;timed_thumbnails&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;non_diegetic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;captions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;descriptions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;metadata&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dependent&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;still_image&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;multilayer&quot;: 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;],&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;filename&quot;: &quot;nal_unit/problem1.avi&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_streams&quot;: 2,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_programs&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_stream_groups&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format_name&quot;: &quot;avi&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format_long_name&quot;: &quot;AVI (Audio Video Interleaved)&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;size&quot;: &quot;9717752&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;probe_score&quot;: 100&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 5&lt;span&gt; ffprobe&lt;/span&gt;를 통한&lt;span&gt; problem1.avi &lt;/span&gt;결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 결과를 요약하면 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너&lt;span&gt;: AVI (format_name: avi), &lt;/span&gt;파일 크기 &lt;span&gt;&amp;asymp;&lt;/span&gt;&lt;span&gt; 9.7 MB.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;비디오&lt;span&gt;: H.264 (codec_tag x264), 1280&amp;times;720, 25 fps, has_b_frames=0, refs=1.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;비디오 메타 특이&lt;span&gt;: is_avc: &quot;false&quot;, nal_length_size: &quot;0&quot;, level: -99 (FFprobe&lt;/span&gt;가&lt;span&gt; level&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;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;오디오&lt;span&gt;: adpcm_ima_wav (ADPCM IMA WAV), 8 kHz, mono, bit_rate 32000 (&lt;/span&gt;&lt;span&gt;&amp;asymp;&lt;/span&gt;&lt;span&gt;32 kbps), bits_per_sample 4.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;문제표시&lt;span&gt;: duration&lt;/span&gt;이&lt;span&gt; 0.000000&lt;/span&gt;으로 나옴 즉&lt;span&gt;, &lt;/span&gt;컨테이너에 타이밍&lt;span&gt;(index/PTS) &lt;/span&gt;정보가 없거나&lt;span&gt; FFprobe&lt;/span&gt;가 읽지 못함&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AVI &lt;/span&gt;컨테이너에서 순수&lt;span&gt; H.264 &lt;/span&gt;스트림을 추출하여&lt;span&gt; NAL Unit &lt;/span&gt;구조를 분석했다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;$ ./ffmpeg -i nal_unit/problem1.avi -c copy -bsf:v h264_mp4toannexb extracted_h264&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;.h264&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 6&lt;span&gt; ffmpeg&lt;/span&gt;를 통해 &lt;span&gt;H.264 &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;451&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpeUt4/dJMcafGkqG4/APR8Dd74yAYCR3iZgB1PaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpeUt4/dJMcafGkqG4/APR8Dd74yAYCR3iZgB1PaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpeUt4/dJMcafGkqG4/APR8Dd74yAYCR3iZgB1PaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpeUt4%2FdJMcafGkqG4%2FAPR8Dd74yAYCR3iZgB1PaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;129&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 6&lt;span&gt; ffmpeg&lt;/span&gt;를 통한 스트림 추출 과정 사진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ffmpeg&lt;/span&gt;의&lt;span&gt; h264_mp4toannexb &lt;/span&gt;비트스트림 필터로&lt;span&gt; AVI &lt;/span&gt;컨테이너에서 원시&lt;span&gt; H.264 &lt;/span&gt;스트림을 성공적으로 추출하였다&lt;span&gt;. &lt;/span&gt;추출 과정에서&lt;span&gt; &amp;lsquo;non-existing PPS 0 referenced&amp;rsquo; &lt;/span&gt;경고가 다수 발생했는데&lt;span&gt;, &lt;/span&gt;이는 입력 스트림에 필수&lt;span&gt; Parameter Set(SPS/PPS)&lt;/span&gt;이 포함되지 않았음을 의미하며&lt;span&gt;, &lt;/span&gt;디코딩 불능의 원인을 확인해 준다&lt;span&gt;. &lt;/span&gt;결과물&lt;span&gt; extracted_h264.h264&lt;/span&gt;는&lt;span&gt; Annex-B &lt;/span&gt;형식의 원시 스트림으로&lt;span&gt;, &lt;/span&gt;이후 외부&lt;span&gt; HED &lt;/span&gt;파일의&lt;span&gt; SPS/PPS&lt;/span&gt;를&lt;span&gt; prepend&lt;/span&gt;하여 디코딩 가능성을 브루트포스로 검증하는 단계로 진행하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;SPS/PPS &lt;/span&gt;누락으로 디코딩이 불가한&lt;span&gt; H.264 &lt;/span&gt;스트림에 대해&lt;span&gt;, &lt;/span&gt;외부 후보&lt;span&gt;(HED &lt;/span&gt;파일&lt;span&gt;)&lt;/span&gt;의&lt;span&gt; SPS&amp;middot;PPS&lt;/span&gt;를 모든 조합으로 대입하여 올바른 파라미터 세트를 탐색하는 절차를 코드로 구현하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;1.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;후보 집합&lt;span&gt;: sps-pps/ &lt;/span&gt;디렉터리 내&lt;span&gt; HED &lt;/span&gt;파일&lt;span&gt; 30&lt;/span&gt;개&lt;span&gt;(&lt;/span&gt;각각&lt;span&gt; SPS+PPS &lt;/span&gt;포함&lt;span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;2.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;총 조합 수&lt;span&gt;: 30 &amp;times; 30 = 900 (SPS 30&lt;/span&gt;개&lt;span&gt; &amp;times; PPS 30&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;&lt;span&gt;&lt;span&gt;3.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;접근 방식&lt;span&gt;: &lt;/span&gt;각 조합에 대해&lt;span&gt; Start Code(Annex&lt;/span&gt;&lt;span&gt;‑&lt;/span&gt;&lt;span&gt;B) &lt;/span&gt;방식으로&lt;span&gt; SPS, PPS&lt;/span&gt;를 원시&lt;span&gt; H.264 &lt;/span&gt;스트림 앞에&lt;span&gt; prepend &lt;/span&gt;후 디코딩 시도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방식을 통해 코드를 작성하면 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;import os&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import subprocess&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from pathlib import Path&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def setup_folders():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; folders = ['videos', 'thumbnails']&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; for folder in folders:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Path(folder).mkdir(exist_ok=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def test_h264(problem_file, sps_file, pps_file, problem_num, use_length_prefix=False):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &quot;&quot;&quot;H.264 &lt;/span&gt;조합 테스트&lt;span&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # &lt;/span&gt;파일 읽기&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with open(sps_file, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sps_data = f.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with open(pps_file, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pps_data = f.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with open(problem_file, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; video_data = f.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # &lt;/span&gt;파일명 생성&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sps_num = Path(sps_file).stem&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pps_num = Path(pps_file).stem&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; video_file = f&quot;videos/problem{problem_num}_sps{sps_num}_pps{pps_num}.h264&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; thumb_file = f&quot;thumbnails/problem{problem_num}_sps{sps_num}_pps{pps_num}.png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # H.264 &lt;/span&gt;파일 생성&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with open(video_file, 'wb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if use_length_prefix:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Length prefix &lt;/span&gt;방식&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(len(sps_data).to_bytes(4, 'big'))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(sps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(len(pps_data).to_bytes(4, 'big'))&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(pps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Start code &lt;/span&gt;방식&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(b'\x00\x00\x00\x01')&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(sps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(b'\x00\x00\x00\x01')&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(pps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f.write(video_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ffmpeg&lt;/span&gt;로 썸네일 생성&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; cmd = ['./ffmpeg.exe', '-y', '-i', video_file, '-vframes', '1', '-loglevel', 'quiet', thumb_file]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; result = subprocess.run(cmd, capture_output=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if result.returncode == 0 and os.path.exists(thumb_file):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;Problem {problem_num}: SPS={sps_num}, PPS={pps_num}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return True&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # &lt;/span&gt;실패하면 파일 삭제&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if os.path.exists(video_file):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; os.remove(video_file)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if os.path.exists(thumb_file):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; os.remove(thumb_file)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return False&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; except Exception:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return False&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def main():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; setup_folders()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # &lt;/span&gt;파일 목록&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; hed_files = sorted([f for f in os.listdir(&quot;sps-pps&quot;) if f.endswith('.hed')])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(f&quot;Found {len(hed_files)} HED files&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; success_count = 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; total_tests = 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; # Problem 1 (Start code)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; print(&quot;\nProblem 1 (Start code)&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; for sps_file in hed_files:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for pps_file in hed_files:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; total_tests += 1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sps_path = f&quot;sps-pps/{sps_file}&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pps_path = f&quot;sps-pps/{pps_file}&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f&quot;[{total_tests:3d}] SPS:{sps_file} + PPS:{pps_file}&quot;, end=&quot; &quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if test_h264(&quot;nal_unit/problem1.avi&quot;, sps_path, pps_path, 1, False):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; success_count += 1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if __name__ == &quot;__main__&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; main()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 7&lt;span&gt; problem1.avi &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;453&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5JRpq/dJMcahc3Izq/hXFti6yeYfs3w9xvTlOSRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5JRpq/dJMcahc3Izq/hXFti6yeYfs3w9xvTlOSRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5JRpq/dJMcahc3Izq/hXFti6yeYfs3w9xvTlOSRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5JRpq%2FdJMcahc3Izq%2FhXFti6yeYfs3w9xvTlOSRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;196&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 7&lt;span&gt; &lt;/span&gt;표&lt;span&gt; 7&lt;/span&gt;을 수행 한 결과 &lt;span&gt;thumnails&lt;/span&gt;에 저장된 사진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 실행하면&lt;span&gt; thumbnails &lt;/span&gt;폴더에 각각의 사진이 추출된다&lt;span&gt;. &lt;/span&gt;다음은 성공 판별 기준을 통하여 얻은 파일의 조합 목록이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;b&gt;파일명&lt;span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;SPS&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;PPS&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps01_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;01&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps02_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;02&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps03_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;03&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps04_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;04&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps05_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;05&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps06_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;06&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps07_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;07&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps08_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;08&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps09_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;09&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps10_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps11_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps12_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps13_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps14_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps15_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps16_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps17_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps18_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps19_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;19&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps20_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps21_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;21&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps22_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;22&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps23_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;23&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps03.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;03&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps06.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;06&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps10.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps11.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps27.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps24_pps30.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps25_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;25&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps26_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;26&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps27_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps28_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;28&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps29_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;29&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;problem1_sps30_pps24.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 8&lt;span&gt; &lt;/span&gt;&lt;span&gt;복구에 성공한 &lt;span&gt;SPS, PPS &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;452&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mDyeE/dJMcaayfYdB/9gdAORabiM9ioenRyG14aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mDyeE/dJMcaayfYdB/9gdAORabiM9ioenRyG14aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mDyeE/dJMcaayfYdB/9gdAORabiM9ioenRyG14aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmDyeE%2FdJMcaayfYdB%2F9gdAORabiM9ioenRyG14aK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;452&quot; height=&quot;254&quot; data-origin-width=&quot;452&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 8&lt;span&gt; &lt;/span&gt;복구된 &lt;span&gt;problem1.avi&lt;/span&gt;에서 발견된 명언&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;132&quot;&gt;&lt;span&gt;철학자 이름&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;469&quot;&gt;&lt;span&gt;&lt;span&gt;Immanuel Kant&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;132&quot;&gt;&lt;span&gt;명언&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;469&quot;&gt;&lt;span&gt;&lt;span&gt;Thoughts without content are empty, intuitions without concepts are blind&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 9&lt;span&gt; Question 1&lt;/span&gt;&lt;span&gt;의 정답&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;Question 2. &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;두 번째로 주어진 &lt;span&gt;H.264(problem2.mp4)&lt;/span&gt;의 &lt;span&gt;SPS, PPS&lt;/span&gt;가 없는&lt;span&gt; NAL &lt;/span&gt;유닛을 디코딩 하여 영상에 기록된 철학자의 이름과 명언을 적어 제출 하시요&lt;span&gt;.(150 points)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;problem2.mp4 &lt;/span&gt;분석과정은 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&lt;span&gt; ffprobe&lt;/span&gt;를 통해서 다음과 같은 특징을 확인 할 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;$ ./ffprobe.exe -v quiet -print_format json -show_format -show_streams nal_unit/problem2.mp4&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ffprobe&lt;/span&gt;를 통해 &lt;span&gt;problem2.mp4 &lt;/span&gt;파일 분석 명령어&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;streams&quot;: [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;index&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_name&quot;: &quot;pcm_mulaw&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_long_name&quot;: &quot;PCM mu-law / G.711 mu-law&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_type&quot;: &quot;audio&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag_string&quot;: &quot;ulaw&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag&quot;: &quot;0x77616c75&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;sample_fmt&quot;: &quot;s16&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;sample_rate&quot;: &quot;8000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;channels&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bits_per_sample&quot;: 8,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;initial_padding&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;id&quot;: &quot;0x1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;r_frame_rate&quot;: &quot;0/0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;avg_frame_rate&quot;: &quot;0/0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;time_base&quot;: &quot;1/8000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_pts&quot;: 3688,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.461000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration_ts&quot;: 1235560,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration&quot;: &quot;154.445000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bit_rate&quot;: &quot;63964&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_frames&quot;: &quot;3859&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;extradata_size&quot;: 4,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;disposition&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;default&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dub&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;original&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;comment&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;lyrics&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;karaoke&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;forced&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;hearing_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;visual_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;clean_effects&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;attached_pic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;timed_thumbnails&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;non_diegetic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;captions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;descriptions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;metadata&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dependent&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;still_image&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;multilayer&quot;: 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;tags&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;language&quot;: &quot;eng&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;handler_name&quot;: &quot;ADPCM Audio Handle&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;vendor_id&quot;: &quot;[0][0][0][0]&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;index&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_name&quot;: &quot;h264&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_long_name&quot;: &quot;H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_type&quot;: &quot;video&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag_string&quot;: &quot;avc1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;codec_tag&quot;: &quot;0x31637661&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;width&quot;: 1920,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;height&quot;: 1080,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;coded_width&quot;: 1920,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;coded_height&quot;: 1080,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;closed_captions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;film_grain&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;has_b_frames&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;level&quot;: -99,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;refs&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;is_avc&quot;: &quot;true&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nal_length_size&quot;: &quot;4&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;id&quot;: &quot;0x2&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;r_frame_rate&quot;: &quot;15/1&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;avg_frame_rate&quot;: &quot;6948000/463157&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;time_base&quot;: &quot;1/90000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_pts&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration_ts&quot;: 13894710,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration&quot;: &quot;154.385667&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bit_rate&quot;: &quot;252210&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_frames&quot;: &quot;2316&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;extradata_size&quot;: 53,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;disposition&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;default&quot;: 1,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dub&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;original&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;comment&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;lyrics&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;karaoke&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;forced&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;hearing_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;visual_impaired&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;clean_effects&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;attached_pic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;timed_thumbnails&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;non_diegetic&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;captions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;descriptions&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;metadata&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;dependent&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;still_image&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;multilayer&quot;: 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;tags&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;language&quot;: &quot;eng&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;handler_name&quot;: &quot;AVC Video Handler&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;vendor_id&quot;: &quot;[0][0][0][0]&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&quot;encoder&quot;: &quot;AVC Coding&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;],&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;filename&quot;: &quot;/Users/pental/Downloads/201_attachments/nal_unit/problem2.mp4&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_streams&quot;: 2,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_programs&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;nb_stream_groups&quot;: 0,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format_name&quot;: &quot;mov,mp4,m4a,3gp,3g2,mj2&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;format_long_name&quot;: &quot;QuickTime / MOV&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;start_time&quot;: &quot;0.000000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;duration&quot;: &quot;154.906000&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;size&quot;: &quot;6194586&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;bit_rate&quot;: &quot;319914&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;probe_score&quot;: 100,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;tags&quot;: {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;major_brand&quot;: &quot;mobi&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;minor_version&quot;: &quot;0&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&quot;compatible_brands&quot;: &quot;mobiavc1mp42isom&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 11&lt;span&gt; ffprobe&lt;/span&gt;를 통한 &lt;span&gt;problem2.mp4 &lt;/span&gt;분석 결과&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ffprobe &lt;/span&gt;분석 결과&lt;span&gt; avcC(AVC configuration box)&lt;/span&gt;에&lt;span&gt; SPS/PPS &lt;/span&gt;메타데이터는 존재하지만 샘플 단위&lt;span&gt;(NAL)&lt;/span&gt;에는&lt;span&gt; SPS/PPS NAL&lt;/span&gt;이 포함되지 않은 전형적인 케이스였다&lt;span&gt;. &lt;/span&gt;또한 비디오의 전체 비트레이트가&lt;span&gt; 1080p &lt;/span&gt;대비 매우 낮고&lt;span&gt;(&lt;/span&gt;약&lt;span&gt; 252 kbps), &lt;/span&gt;오디오 트랙은&lt;span&gt; G.711 &amp;mu;-law(8kHz)&lt;/span&gt;로 시작 시간이 약&lt;span&gt; 0.461&lt;/span&gt;초 지연되어 있어&lt;span&gt; AV &lt;/span&gt;동기 관련 특이점이 관찰되었다&lt;span&gt;. &lt;/span&gt;이런 특성 때문에&lt;span&gt; raw H.264(Annex-B)&lt;/span&gt;로 단순 추출&lt;span&gt;/&lt;/span&gt;재생하면&lt;span&gt; SPS/PPS &lt;/span&gt;누락으로 디코더가 프레임을 제대로 해석하지 못하고 재생 실패 또는 깨진 화면이 발생할 수 있었다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재의 문제점을 요약하면 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. SPS/PPS&lt;/span&gt;가 스트림 내부에 없고&lt;span&gt; avcC&lt;/span&gt;에만 존재&lt;span&gt;: MP4 &lt;/span&gt;내부&lt;span&gt; avcC&lt;/span&gt;에&lt;span&gt; SPS/PPS &lt;/span&gt;정보만 들어 있고 각 프레임 앞에&lt;span&gt; SPS/PPS&lt;/span&gt;가 붙어 있지 않으면 일부 플레이어나 파싱 도구가 초기화 정보를 찾지 못하고 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2. NAL &lt;/span&gt;포맷 차이&lt;span&gt;(AVCC vs Annex-B): MP4&lt;/span&gt;는 길이정보&lt;span&gt;(4&lt;/span&gt;바이트 길이 프리픽스&lt;span&gt;) &lt;/span&gt;방식&lt;span&gt;(AVCC)&lt;/span&gt;을 사용하므로&lt;span&gt; raw Annex-B(0x00000001 start code) &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;&lt;span&gt;3. &lt;/span&gt;메타 불일치 표시&lt;span&gt;: ffprobe&lt;/span&gt;에서&lt;span&gt; level=-99 &lt;/span&gt;등 레벨 정보가 비정상으로 표기되어&lt;span&gt; SPS &lt;/span&gt;내부의&lt;span&gt; level_idc&lt;/span&gt;를 정상적으로 읽지 못한 흔적이 있다&lt;span&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;&lt;span&gt;4. &lt;/span&gt;오디오 시작 지연&lt;span&gt;(AV &lt;/span&gt;오프셋&lt;span&gt;): &lt;/span&gt;오디오&lt;span&gt; start_time=0.461&lt;/span&gt;으로 영상과의 초기 동기 차이가 존재할 수 있다&lt;span&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;&lt;span&gt;5. &lt;/span&gt;저비트레이트&lt;span&gt;(&lt;/span&gt;화질 저하 우려&lt;span&gt;): 1080p &lt;/span&gt;해상도에 대해 비트레이트가 낮아 화질이 거칠 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;따라서 해결 방법을 다음과 같이 진행하였다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 아이디어는 올바른&lt;span&gt; SPS/PPS&lt;/span&gt;를 비디오 비트스트림 앞에 넣어 디코더가 초기화하도록 만드는 것이다&lt;span&gt;. SPS/PPS &lt;/span&gt;후보를 다수&lt;span&gt;(&lt;/span&gt;브루트포스&lt;span&gt;)&lt;/span&gt;로 조합해 넣어보고&lt;span&gt;, &lt;/span&gt;각 조합으로 생성한&lt;span&gt; raw H.264 &lt;/span&gt;파일을&lt;span&gt; ffmpeg&lt;/span&gt;로 디코딩해 썸네일&lt;span&gt;(&lt;/span&gt;프레임 이미지&lt;span&gt;)&lt;/span&gt;을 얻어&lt;span&gt; &amp;lsquo;&lt;/span&gt;의미 있는 프레임&lt;span&gt;&amp;rsquo;&lt;/span&gt;을 판별함으로써 올바른&lt;span&gt; SPS/PPS &lt;/span&gt;조합을 찾는 방법을 택했다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; SPS/PPS&lt;/span&gt;가 손상되었거나 원본&lt;span&gt; avcC &lt;/span&gt;내 값이 정확치 않을 때 유용하다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;span&gt;mp4 &lt;/span&gt;파일을 &lt;span&gt;Annex-B&lt;/span&gt;로 변환하는 과정을 진행하였다&lt;span&gt;. &lt;/span&gt;다음은 변환에 사용한 명령어이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;ffmpeg -i nal_unit/problem2.mp4 -c copy -bsf:v h264_mp4toannexb nal_unit/extracted_h264.h264&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; ffmpeg&lt;/span&gt;를 통한 &lt;span&gt;mp4&lt;/span&gt;파일을 &lt;span&gt;Annex-B&lt;/span&gt;로 변환하는 명령어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령은&lt;span&gt; MP4 &lt;/span&gt;내부의&lt;span&gt; AVCC(&lt;/span&gt;길이 프리픽스&lt;span&gt;) &lt;/span&gt;기반&lt;span&gt; NAL&lt;/span&gt;들을&lt;span&gt; start-code(0x00000001) &lt;/span&gt;방식&lt;span&gt;(Annex-B)&lt;/span&gt;로 변환해&lt;span&gt; extracted_h264.h264&lt;/span&gt;에 저장한다&lt;span&gt;. &lt;/span&gt;다만&lt;span&gt; avcC &lt;/span&gt;내&lt;span&gt; SPS/PPS&lt;/span&gt;가 별도 박스에만 존재하는 경우&lt;span&gt;(&lt;/span&gt;또는 샘플에 포함되어있지 않은 경우&lt;span&gt;) &lt;/span&gt;변환 후에도 유효한&lt;span&gt; SPS/PPS&lt;/span&gt;가 앞에 붙어있지 않을 수 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추출된&lt;span&gt; Annex-B &lt;/span&gt;파일&lt;span&gt;(extracted_h264.h264)&lt;/span&gt;은 이후 브루트포스 조합의 대상이 된다&lt;span&gt;. &lt;/span&gt;이 단계에서는 여러 개의&lt;span&gt; HED &lt;/span&gt;파일에서 분리해낸&lt;span&gt; SPS&lt;/span&gt;와&lt;span&gt; PPS &lt;/span&gt;후보들을 서로 조합하여&lt;span&gt;, &lt;/span&gt;각각을&lt;span&gt; Annex-B &lt;/span&gt;스트림의 맨 앞에 삽입한 새로운&lt;span&gt; H.264 &lt;/span&gt;파일을 생성한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 조합된&lt;span&gt; H.264 &lt;/span&gt;파일은&lt;span&gt; FFmpeg&lt;/span&gt;을 이용해 첫 번째 프레임을 이미지로 덤프하고&lt;span&gt;, &lt;/span&gt;이어서&lt;span&gt; Pillow &lt;/span&gt;라이브러리로 분석된다&lt;span&gt;. &lt;/span&gt;분석 과정에서는 고유 색상 수&lt;span&gt;, &lt;/span&gt;이미지 해상도&lt;span&gt;, &lt;/span&gt;파일 해시와 같은 메타데이터가 계산된다&lt;span&gt;. &lt;/span&gt;이렇게 얻어진 지표를 기준으로 실제 영상 프레임인지 여부를 판별한다&lt;span&gt;. &lt;/span&gt;예를 들어&lt;span&gt;, &lt;/span&gt;색상 수가 일정 기준&lt;span&gt;(&lt;/span&gt;예&lt;span&gt;: 100 &lt;/span&gt;이상&lt;span&gt;)&lt;/span&gt;을 넘으면 의미 있는 결과로 간주하며&lt;span&gt;, 500 &lt;/span&gt;이상이면 매우 신뢰할 수 있는 성공 사례로 판단한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공으로 판정된 조합은&lt;span&gt; bruteforce_results/successful &lt;/span&gt;디렉터리에&lt;span&gt; .h264&lt;/span&gt;와&lt;span&gt; .png &lt;/span&gt;형태로 보존되며&lt;span&gt;, &lt;/span&gt;각 결과는 조합명&lt;span&gt;(spsXX_ppsYY), &lt;/span&gt;생성 시각&lt;span&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;사용한 코드는 다음과 같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;span&gt;import subprocess&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from pathlib import Path&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from PIL import Image&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;import hashlib&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;from datetime import datetime&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;class H264BruteForce:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def __init__(self):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.sps_pps_dir = Path(&quot;sps-pps&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.h264_file = Path(&quot;nal_unit/extracted_h264.h264&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.base_output_dir = Path(&quot;bruteforce_results&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.videos_dir = self.base_output_dir / &quot;videos&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.thumbnails_dir = self.base_output_dir / &quot;thumbnails&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.successful_dir = self.base_output_dir / &quot;successful&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for directory in [self.videos_dir, self.thumbnails_dir, self.successful_dir]:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;directory.mkdir(parents=True, exist_ok=True)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.results = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.successful_combinations = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def read_hed_file(self, hed_path):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with open(hed_path, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;data = f.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;nal_units = []&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;i = 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;while i &amp;lt; len(data) - 4:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if data[i:i+4] == b'\x00\x00\x00\x01':&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;nal_start = i + 4&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;nal_type = data[nal_start] &amp;amp; 0x1F&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;next_start = len(data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;for j in range(i + 4, len(data) - 3):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if data[j:j+4] == b'\x00\x00\x00\x01':&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;next_start = j&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;break&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;nal_data = data[i:next_start]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;nal_units.append({&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'type': nal_type,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'data': nal_data,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'size': len(nal_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;})&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;i = next_start&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;i += 1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return nal_units&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def extract_sps_pps(self, nal_units):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;sps_data = None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pps_data = None&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for nal in nal_units:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if nal['type'] == 7:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;sps_data = nal['data']&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;elif nal['type'] == 8:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;pps_data = nal['data']&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return sps_data, pps_data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def create_combined_h264(self, sps_data, pps_data, sps_num, pps_num):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with open(self.h264_file, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;h264_data = f.read()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;combined_data = bytearray()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;combined_data.extend(sps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;combined_data.extend(pps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;combined_data.extend(h264_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;output_path = self.videos_dir / f&quot;sps{sps_num:02d}_pps{pps_num:02d}.h264&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with open(output_path, 'wb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;f.write(combined_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return output_path, len(combined_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def generate_thumbnail(self, h264_path, sps_num, pps_num):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;thumbnail_path = self.thumbnails_dir / f&quot;sps{sps_num:02d}_pps{pps_num:02d}.png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;cmd = [&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'ffmpeg', '-y', '-v', 'quiet',&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'-i', str(h264_path),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'-vframes', '1',&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'-f', 'image2',&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;str(thumbnail_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result = subprocess.run(cmd, capture_output=True, timeout=30)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return thumbnail_path, result.returncode == 0 and thumbnail_path.exists(), result.stderr.decode() if result.stderr else &quot;Unknown error&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return thumbnail_path, False, &quot;Timeout or error&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def analyze_thumbnail(self, thumbnail_path):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;img = Image.open(thumbnail_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if img.mode == 'RGB':&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;colors = img.getcolors(maxcolors=256*256*256)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;img_rgb = img.convert('RGB')&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;colors = img_rgb.getcolors(maxcolors=256*256*256)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;unique_colors = len(colors) if colors else 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;with open(thumbnail_path, 'rb') as f:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;file_hash = hashlib.md5(f.read()).hexdigest()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'resolution': img.size,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'unique_colors': unique_colors,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'file_hash': file_hash,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'file_size': thumbnail_path.stat().st_size,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'is_meaningful': unique_colors &amp;gt; 100,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'is_highly_meaningful': unique_colors &amp;gt; 500,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'mode': img.mode&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def copy_successful_files(self, sps_num, pps_num, analysis):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if not analysis.get('is_meaningful', False):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;combo_name = f&quot;sps{sps_num:02d}_pps{pps_num:02d}&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;video_src = self.videos_dir / f&quot;{combo_name}.h264&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;thumbnail_src = self.thumbnails_dir / f&quot;{combo_name}.png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;video_dst = self.successful_dir / f&quot;{combo_name}_{analysis['unique_colors']}colors.h264&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;thumbnail_dst = self.successful_dir / f&quot;{combo_name}_{analysis['unique_colors']}colors.png&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;import shutil&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if video_src.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;shutil.copy2(video_src, video_dst)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if thumbnail_src.exists():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;shutil.copy2(thumbnail_src, thumbnail_dst)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def test_single_combination(self, sps_num, pps_num, sps_data, pps_data):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;&lt;/span&gt;테스트 중&lt;span&gt;: SPS{sps_num:02d} + PPS{pps_num:02d}&quot;, end=&quot; ... &quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;h264_path, h264_size = self.create_combined_h264(sps_data, pps_data, sps_num, pps_num)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;thumbnail_path, thumbnail_success, error = self.generate_thumbnail(h264_path, sps_num, pps_num)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result = {&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'sps_num': sps_num,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'pps_num': pps_num,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'combination': f&quot;sps{sps_num:02d}_pps{pps_num:02d}&quot;,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'h264_path': str(h264_path),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'h264_size': h264_size,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'thumbnail_path': str(thumbnail_path),&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'thumbnail_success': thumbnail_success,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;'timestamp': datetime.now().isoformat()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if thumbnail_success:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;analysis = self.analyze_thumbnail(thumbnail_path)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result.update(analysis)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.copy_successful_files(sps_num, pps_num, analysis)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;colors = analysis.get('unique_colors', 0)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if analysis.get('is_highly_meaningful', False):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;print(f&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; {colors}&lt;/span&gt;개 색상&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;self.successful_combinations.append(result)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;elif analysis.get('is_meaningful', False):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;print(f&quot;&lt;/span&gt;&lt;span&gt;✅&lt;/span&gt;&lt;span&gt; {colors}&lt;/span&gt;개 색상&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;self.successful_combinations.append(result)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;print(f&quot;&lt;/span&gt;&lt;span&gt;⚪&lt;/span&gt;&lt;span&gt; {colors}&lt;/span&gt;개 색상&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;&lt;/span&gt;&lt;span&gt;❌&lt;/span&gt;&lt;span&gt; &lt;/span&gt;실패&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;result['error'] = error&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.results.append(result)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return result&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;def run_bruteforce_analysis(self):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(&quot;H.264 &lt;/span&gt;브루트포스 분석 시작&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(&quot;=&quot; * 60)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hed_files = {}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for hed_file in sorted(self.sps_pps_dir.glob(&quot;*.hed&quot;)):&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;file_num = int(hed_file.stem)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;nal_units = self.read_hed_file(hed_file)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hed_files[file_num] = nal_units&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;HED &lt;/span&gt;파일&lt;span&gt;: {len(hed_files)}&lt;/span&gt;개&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;file_numbers = sorted(hed_files.keys())&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;total_combinations = len(file_numbers) ** 2&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;&lt;/span&gt;총 조합&lt;span&gt;: {total_combinations}&lt;/span&gt;개&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(&quot;=&quot; * 60)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;tested = 0&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for sps_num in file_numbers:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;for pps_num in file_numbers:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;tested += 1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;progress = (tested / total_combinations) * 100&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;print(f&quot;[{tested:3d}/{total_combinations}] ({progress:5.1f}%) &quot;, end=&quot;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;sps_data, _ = self.extract_sps_pps(hed_files[sps_num])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;_, pps_data = self.extract_sps_pps(hed_files[pps_num])&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;if sps_data and pps_data:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;self.test_single_combination(sps_num, pps_num, sps_data, pps_data)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;/span&gt;else:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&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;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;SPS{sps_num:02d} + PPS{pps_num:02d} ... &lt;/span&gt;&lt;span&gt;❌&lt;/span&gt;&lt;span&gt; &lt;/span&gt;데이터 추출 실패&lt;span&gt;&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(&quot;=&quot; * 60)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(&quot;&lt;/span&gt;분석 완료&lt;span&gt;!&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;def main():&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bf = H264BruteForce()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bf.run_bruteforce_analysis()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;except Exception as e:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;print(f&quot;&lt;/span&gt;오류&lt;span&gt;: {e}&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;if __name__ == &quot;__main__&quot;:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;main()&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 13&lt;span&gt; problem2.mp4 &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;453&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tqOOF/dJMb997aGwd/J3l6SYZ33aZ70rQjHe9Q21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tqOOF/dJMb997aGwd/J3l6SYZ33aZ70rQjHe9Q21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tqOOF/dJMb997aGwd/J3l6SYZ33aZ70rQjHe9Q21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtqOOF%2FdJMb997aGwd%2FJ3l6SYZ33aZ70rQjHe9Q21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;149&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 9&lt;span&gt;&amp;nbsp;&lt;/span&gt;표&lt;span&gt; 13 &lt;/span&gt;코드를 수행하는 과정 사진&lt;span&gt; 1&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;453&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PNhLT/dJMcadhqzbZ/UhjWaNJJ9dXXSLAhKWb6V0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PNhLT/dJMcadhqzbZ/UhjWaNJJ9dXXSLAhKWb6V0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PNhLT/dJMcadhqzbZ/UhjWaNJJ9dXXSLAhKWb6V0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPNhLT%2FdJMcadhqzbZ%2FUhjWaNJJ9dXXSLAhKWb6V0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;453&quot; height=&quot;285&quot; data-origin-width=&quot;453&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;표&lt;span&gt; 13 &lt;/span&gt;코드를 수행하는 과정 사진 &lt;span&gt;2&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;451&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFjYiT/dJMcaduTPDE/q4mpknKfETL4akN0dgRwN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFjYiT/dJMcaduTPDE/q4mpknKfETL4akN0dgRwN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFjYiT/dJMcaduTPDE/q4mpknKfETL4akN0dgRwN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFjYiT%2FdJMcaduTPDE%2Fq4mpknKfETL4akN0dgRwN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;272&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/span&gt;&lt;span&gt; bruteforce_results/thumnails &lt;/span&gt;폴더에 저장된 사진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 실행하면 &lt;span&gt;bruteforce_results/thumnails &lt;/span&gt;폴더에 각각의 사진이 추출된다&lt;span&gt;. &lt;/span&gt;다음은 성공 판별 기준을 통하여 얻은 파일의 조합 목록이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;파일명&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;SPS&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;PPS&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;sps20_pps05.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;05&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;sps20_pps06.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;06&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;sps20_pps12.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;sps20_pps27.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;sps20_pps29.png&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;200&quot;&gt;&lt;span&gt;&lt;span&gt;29&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;명언을 확인 할 수 있는 &lt;span&gt;SPS, PPS &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;451&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYlhWc/dJMcagrGiZe/U4VdlmSK99JYGlATxrRqUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYlhWc/dJMcagrGiZe/U4VdlmSK99JYGlATxrRqUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYlhWc/dJMcagrGiZe/U4VdlmSK99JYGlATxrRqUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYlhWc%2FdJMcagrGiZe%2FU4VdlmSK99JYGlATxrRqUk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;254&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그림 &lt;span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;복구된&lt;span&gt; problem2.mp4&lt;/span&gt;에서 발견된 명언&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;132&quot;&gt;&lt;span&gt;철학자 이름&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;469&quot;&gt;&lt;span&gt;&lt;span&gt;Baruch Spinoza&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width=&quot;132&quot;&gt;&lt;span&gt;명언&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td width=&quot;469&quot;&gt;&lt;span&gt;&lt;span&gt;The highest activity a human being can attain is learning for understanding, because to understand is to be free.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;표 &lt;span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/span&gt;&lt;span&gt; Question2&lt;/span&gt;의 정답&lt;/p&gt;</description>
      <category>Forensics/DFC</category>
      <category>DFC</category>
      <category>DFC2026</category>
      <category>디지털 포렌식 챌린지</category>
      <category>디지털포렌식</category>
      <category>디지털포렌식챌린지</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/595</guid>
      <comments>https://pental.tistory.com/595#entry595comment</comments>
      <pubDate>Mon, 20 Apr 2026 20:55:31 +0900</pubDate>
    </item>
    <item>
      <title>palera1n을 통한 아이폰 탈옥 및 SSH 접근</title>
      <link>https://pental.tistory.com/594</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우연치 않게 아이폰 X를 구하게 되어서 오랜만에 탈옥을 진행해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 탈옥은 palera1n 및 도파민을 통해서 많이 진행한다고 하며, 이 포스팅에서는 palera1n을 통해서 탈옥을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://palera.in/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://palera.in/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1771771506501&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;palera1n&quot; data-og-description=&quot;palera1n includes tools like dropbear (port 44), a (rather insecure) telnet option if specified, and a binpack with basic command line utilities&quot; data-og-host=&quot;palera.in&quot; data-og-source-url=&quot;https://palera.in/&quot; data-og-url=&quot;https://palera.in/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ctAM9f/dJMb84XVysO/CH4eE447oQjhPwJgK30kh0/img.png?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128,https://scrap.kakaocdn.net/dn/ckQyeh/dJMb88F1GTF/zikyewH1oh7Z6hwvRCVHn1/img.png?width=1276&amp;amp;height=878&amp;amp;face=0_0_1276_878&quot;&gt;&lt;a href=&quot;https://palera.in/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://palera.in/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ctAM9f/dJMb84XVysO/CH4eE447oQjhPwJgK30kh0/img.png?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128,https://scrap.kakaocdn.net/dn/ckQyeh/dJMb88F1GTF/zikyewH1oh7Z6hwvRCVHn1/img.png?width=1276&amp;amp;height=878&amp;amp;face=0_0_1276_878');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;palera1n&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;palera1n includes tools like dropbear (port 44), a (rather insecure) telnet option if specified, and a binpack with basic command line utilities&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;palera.in&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;1068&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kEOFP/dJMcagEyVbH/6OjmZgyI13VXgUQseQ7dp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kEOFP/dJMcagEyVbH/6OjmZgyI13VXgUQseQ7dp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kEOFP/dJMcagEyVbH/6OjmZgyI13VXgUQseQ7dp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkEOFP%2FdJMcagEyVbH%2F6OjmZgyI13VXgUQseQ7dp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1068&quot; height=&quot;585&quot; data-origin-width=&quot;1068&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1771771559940&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo /bin/sh -c &quot;$(curl -fsSL https://static.palera.in/scripts/install.sh)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/P5E9N/dJMcahKezS8/SYLpd7P3mwZFhM4VfBcZ00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/P5E9N/dJMcahKezS8/SYLpd7P3mwZFhM4VfBcZ00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/P5E9N/dJMcahKezS8/SYLpd7P3mwZFhM4VfBcZ00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FP5E9N%2FdJMcahKezS8%2FSYLpd7P3mwZFhM4VfBcZ00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;853&quot; height=&quot;255&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;255&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되면 터미널에서 palera1n 명령을 통해서 실행시킬수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elH5mR/dJMcacoBhsY/svDl8aVsNeV9cCSBcjLygk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elH5mR/dJMcacoBhsY/svDl8aVsNeV9cCSBcjLygk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elH5mR/dJMcacoBhsY/svDl8aVsNeV9cCSBcjLygk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelH5mR%2FdJMcacoBhsY%2FsvDl8aVsNeV9cCSBcjLygk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;587&quot; height=&quot;220&quot; data-origin-width=&quot;587&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이폰을 연결하고, palera1n을 실행시키면 다음과 같이 작동한다.&lt;br /&gt;하지만 -f (rootful)의 경우는 필자는 잘 작동하지 않았다. -l 옵션인 rootless를 통해서 탈옥을 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1P7w8/dJMcagdujsC/bqEZbr6ieKPlEcpLByQFQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1P7w8/dJMcagdujsC/bqEZbr6ieKPlEcpLByQFQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1P7w8/dJMcagdujsC/bqEZbr6ieKPlEcpLByQFQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1P7w8%2FdJMcagdujsC%2FbqEZbr6ieKPlEcpLByQFQ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;592&quot; height=&quot;222&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동으로 리커버리모드에 진입하고, 리커버리모드에 진입했을때, 직접 DFU 모드로 들어가줘야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7793.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2B7BZ/dJMcabQKF2G/i5m5TYtPQwkOskSG9kQQn0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2B7BZ/dJMcabQKF2G/i5m5TYtPQwkOskSG9kQQn0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2B7BZ/dJMcabQKF2G/i5m5TYtPQwkOskSG9kQQn0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2B7BZ%2FdJMcabQKF2G%2Fi5m5TYtPQwkOskSG9kQQn0%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;500&quot; height=&quot;667&quot; data-filename=&quot;IMG_7793.jpg&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;아이폰 X의 DFU 접근방법은 볼륨아래 + 전원 5초 누르고, 5초후 전원버튼만 떼고 볼륨 아래 버튼만 누르고 있으면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;656&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deblx5/dJMcah4woI4/U6o0kS48iX1yjrVN6Ps0h1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deblx5/dJMcah4woI4/U6o0kS48iX1yjrVN6Ps0h1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deblx5/dJMcah4woI4/U6o0kS48iX1yjrVN6Ps0h1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdeblx5%2FdJMcah4woI4%2FU6o0kS48iX1yjrVN6Ps0h1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;989&quot; height=&quot;656&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;656&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;palera1n 자체에서 직접 탈옥을 진행해주고, 이때 아이폰 X에서는 실시간으로 통신이 진행된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_7795.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLadvU/dJMcah4woNR/0TAjzhTxUKgezwWrK5FheK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLadvU/dJMcah4woNR/0TAjzhTxUKgezwWrK5FheK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLadvU/dJMcah4woNR/0TAjzhTxUKgezwWrK5FheK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLadvU%2FdJMcah4woNR%2F0TAjzhTxUKgezwWrK5FheK%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;500&quot; height=&quot;667&quot; data-filename=&quot;IMG_7795.jpg&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;탈옥이 완료되면 탈옥된 폰에서는 palera1n 앱을 확인할 수 있고, 실행해서 Sileo, Zebra를 설치한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0074.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JfrKc/dJMb996um0Q/11yHPnLb6FlotvCmjkTB2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JfrKc/dJMb996um0Q/11yHPnLb6FlotvCmjkTB2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JfrKc/dJMb996um0Q/11yHPnLb6FlotvCmjkTB2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJfrKc%2FdJMb996um0Q%2F11yHPnLb6FlotvCmjkTB2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1083&quot; data-filename=&quot;IMG_0074.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0075.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKKbq/dJMcaivyflo/74P0b7GkwVqKvQOf0YZJxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKKbq/dJMcaivyflo/74P0b7GkwVqKvQOf0YZJxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKKbq/dJMcaivyflo/74P0b7GkwVqKvQOf0YZJxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKKbq%2FdJMcaivyflo%2F74P0b7GkwVqKvQOf0YZJxk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1083&quot; data-filename=&quot;IMG_0075.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후 Sileo를 실행시켜, SSH 서버를 구성한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0076.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAaKc7/dJMcagkd3Db/v9K6kQpVkqcoautZxZanYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAaKc7/dJMcagkd3Db/v9K6kQpVkqcoautZxZanYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAaKc7/dJMcagkd3Db/v9K6kQpVkqcoautZxZanYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAaKc7%2FdJMcagkd3Db%2Fv9K6kQpVkqcoautZxZanYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1083&quot; data-filename=&quot;IMG_0076.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0077.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvTutv/dJMcaaqNgJJ/hhAfx02g5rqi4080GzFSZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvTutv/dJMcaaqNgJJ/hhAfx02g5rqi4080GzFSZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvTutv/dJMcaaqNgJJ/hhAfx02g5rqi4080GzFSZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvTutv%2FdJMcaaqNgJJ%2FhhAfx02g5rqi4080GzFSZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1083&quot; data-filename=&quot;IMG_0077.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 패키지는 설치 후 설정 - Wifi - 연결된 Wifi 상세보기 후 탈옥된 폰에 연결된 ip주소를 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_0078.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cogqqv/dJMcabQKGdl/cOZqajZhikuwNhZn8dKBp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cogqqv/dJMcabQKGdl/cOZqajZhikuwNhZn8dKBp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cogqqv/dJMcabQKGdl/cOZqajZhikuwNhZn8dKBp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcogqqv%2FdJMcabQKGdl%2FcOZqajZhikuwNhZn8dKBp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1083&quot; data-filename=&quot;IMG_0078.PNG&quot; data-origin-width=&quot;1125&quot; data-origin-height=&quot;2436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 탈옥된 폰에서는 192.168.1.63을 사용하고 있고, ssh mobile@192.168.1.63 을 통해서 SSH를 접근한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;49&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5qmrl/dJMcaaYB8PZ/KHsVohkqmpgBE4jyJLDUg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5qmrl/dJMcaaYB8PZ/KHsVohkqmpgBE4jyJLDUg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5qmrl/dJMcaaYB8PZ/KHsVohkqmpgBE4jyJLDUg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5qmrl%2FdJMcaaYB8PZ%2FKHsVohkqmpgBE4jyJLDUg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;482&quot; height=&quot;49&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;49&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;palera1n에서 미리 sudo 비밀번호를 설정해줘야한다. 그리고 바로 ssh root@192.168.1.63은 케바케로 안될 확률이 높고, mobile 계정으로 접근 후 su 를 통해서 권한 상승을 진행한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nIxU4/dJMcadudMRU/raZ9k4MED1ipUGduAbysQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nIxU4/dJMcadudMRU/raZ9k4MED1ipUGduAbysQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nIxU4/dJMcadudMRU/raZ9k4MED1ipUGduAbysQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnIxU4%2FdJMcadudMRU%2FraZ9k4MED1ipUGduAbysQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;853&quot; height=&quot;78&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;루트로 접근이 됐으면 passwd를 통해서 sudo 비밀번호를 새로 지정한다. (root로 직접 접근 하는 가장 쉬운 방법이라고 생각된다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GDhVp/dJMcagqZV0D/77D6k1b6ZxBJkuAxSeJ0M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GDhVp/dJMcagqZV0D/77D6k1b6ZxBJkuAxSeJ0M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GDhVp/dJMcagqZV0D/77D6k1b6ZxBJkuAxSeJ0M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGDhVp%2FdJMcagqZV0D%2F77D6k1b6ZxBJkuAxSeJ0M1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;853&quot; height=&quot;230&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sudo 비밀번호 재설정이 완료되면, root로 접근을 진행해본다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLhtke/dJMcafr5rZi/CCHKlLhzW3IRum4fS8kdFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLhtke/dJMcafr5rZi/CCHKlLhzW3IRum4fS8kdFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLhtke/dJMcafr5rZi/CCHKlLhzW3IRum4fS8kdFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLhtke%2FdJMcafr5rZi%2FCCHKlLhzW3IRum4fS8kdFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;536&quot; height=&quot;58&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근이 정상적으로 되는것을 확인할 수 있고, scp를 통해서 파일을 빼보는 작업을 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9uZpX/dJMcagLj2Ex/SG9JoC3QfklPKtbbAKE04K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9uZpX/dJMcagLj2Ex/SG9JoC3QfklPKtbbAKE04K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9uZpX/dJMcagLj2Ex/SG9JoC3QfklPKtbbAKE04K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9uZpX%2FdJMcagLj2Ex%2FSG9JoC3QfklPKtbbAKE04K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;854&quot; height=&quot;137&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1771772588593&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scp -r root@[IP주소]:[경로]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 커맨드를 통해서 파일 추출이 정상적으로 가능한 것을 확인 할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Forensics/Iphone Forensics</category>
      <category>Forensics</category>
      <category>palera1n</category>
      <category>아이폰</category>
      <category>아이폰 jailbreak</category>
      <category>아이폰 X</category>
      <category>아이폰 탈옥</category>
      <category>아이폰 파일 추출</category>
      <category>아이폰 포렌식</category>
      <category>탈옥</category>
      <category>포렌식</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/594</guid>
      <comments>https://pental.tistory.com/594#entry594comment</comments>
      <pubDate>Mon, 23 Feb 2026 00:04:18 +0900</pubDate>
    </item>
    <item>
      <title>[25년 2회차] 제11회 빅데이터분석기사 합격 후기 (필기 &amp;amp; 실기)</title>
      <link>https://pental.tistory.com/593</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;175&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dMeNqF/dJMcai2WKr2/9Sqspu1h7knt4v3caZk58K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dMeNqF/dJMcai2WKr2/9Sqspu1h7knt4v3caZk58K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dMeNqF/dJMcai2WKr2/9Sqspu1h7knt4v3caZk58K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdMeNqF%2FdJMcai2WKr2%2F9Sqspu1h7knt4v3caZk58K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;994&quot; height=&quot;175&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;175&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어쩌다보니 응시하게 된 &quot;빅데이터분석기사&quot; 어떨결에 합격했다. 이로써 정보처리기사, 정보보안기사, 빅데이터분석기사 총 3개의 기사를 가지게 되었다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아래는 내가 가지고 있는 자격 목록들,,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;정보처리기사, 정보보안기사, 빅데이터분석기사&lt;br /&gt;디지털포렌식 전문가 2급&lt;br /&gt;컴퓨터활용능력 1급, 워드프로세서&lt;br /&gt;리눅스마스터 2급, SQLD, FTK Ace v6,7&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;자격증 리스트가 계속해서 추가되고 있다,,,, 자격증이 하나둘 추가되다 보니 &amp;ldquo;이제 뭐가 본업인지 모르겠다&amp;rdquo;는 생각도 가끔 들지만, 그래도&amp;nbsp;그&amp;nbsp;과정&amp;nbsp;자체는&amp;nbsp;분명&amp;nbsp;의미가&amp;nbsp;있었다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 &lt;b&gt;빅데이터분석기사 필기&amp;middot;실기를 한 번에 합격하면서 느낀 점&lt;/b&gt;&lt;span&gt;, &lt;/span&gt;그리고 &lt;span&gt;&lt;b&gt;짧게나마 공부 방법과 소소한 팁&lt;/b&gt;&lt;/span&gt;을 기록용으로 남겨보려 한다. 앞으로 준비하시는 분들께 조금이나마 도움이 되길 바란다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;빅데이터분석기사의 과목이랑 내용은 다음과 같다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;빅데이터분석기사 자격시험은 필기시험과 실기시험으로 구성되어 있으며 필기시험 합격기준 및 응시자격 요건을 충족하면 실기시험에 응시할 수 있다. 실기시험은 CBT(Computer Based Test) 방식의 시험으로 자격을 검정하며, 실기시험의 합격자는 최종합격자로 분류되어 빅데이터분석기사 자격이 부여된다. 검정 과목 및 내용은 아래와 같다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빅데이터분석기사&amp;nbsp;자격시험은&amp;nbsp;필기시험&amp;nbsp;+&amp;nbsp;실기시험으로&amp;nbsp;구성되어&amp;nbsp;있다.&lt;br /&gt;- 필기시험 합격 기준을 충족하면 실기시험 응시 가능&lt;br /&gt;- 실기시험은 CBT(Computer Based Test) 방식&lt;br /&gt;- 실기시험 합격 시 최종합격으로 자격증이 부여된다&lt;br /&gt;즉, 필기만 붙어도 끝이 아니라 실기까지 통과해야 진짜 합격이다. (기사 자격시험의 특성)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필기시험 출제 문항 수 및 합격 기준&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;과목당 &lt;span&gt;&lt;b&gt;20문항&lt;/b&gt;&lt;/span&gt;, 총 &lt;span&gt;&lt;b&gt;80문항&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;객관식 4지선다형&lt;/li&gt;
&lt;li&gt;&lt;span&gt;과목별 &lt;/span&gt;&lt;b&gt;40점 이상&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;전 과목 평균 &lt;span&gt;&lt;b&gt;60점 이상&lt;/b&gt;&lt;/span&gt; 시 합격&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 과목이라도 40점 미만이면 &lt;span&gt;&lt;b&gt;과락&lt;/b&gt;&lt;/span&gt;이라 특정 과목만 파고들기보다는 &lt;span&gt;&lt;b&gt;전 과목 균형&lt;/b&gt;&lt;/span&gt;이 중요하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;필기 공부 방법&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부기간 : 약 2-3주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필기 책 : 2025 이기적 빅데이터분석기사 필기 기본서 (&lt;a href=&quot;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=344700450&amp;amp;srsltid=AfmBOooVbivYv_y2vfdJ2PY51DAwOD0lgvX63s68NE91Vge7NGhd30vh&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=344700450&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개념 위주로 빠르게 1회독&lt;br /&gt;- 기출문제 반복&lt;br /&gt;- 애매한 통계&amp;middot;모델 개념만 따로 정리&lt;br /&gt;&lt;br /&gt;  정보처리기사, SQLD 경험이 있다면 필기&amp;nbsp;난이도는&amp;nbsp;크게&amp;nbsp;부담되지&amp;nbsp;않는&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;1065&quot; data-origin-height=&quot;646&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vdMTP/dJMcacoa941/vYwSWoA2G9PAqzcQwWCI6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vdMTP/dJMcacoa941/vYwSWoA2G9PAqzcQwWCI6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vdMTP/dJMcacoa941/vYwSWoA2G9PAqzcQwWCI6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvdMTP%2FdJMcacoa941%2FvYwSWoA2G9PAqzcQwWCI6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1065&quot; height=&quot;646&quot; data-origin-width=&quot;1065&quot; data-origin-height=&quot;646&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 노션에 정리하면서 푸는 방식으로 진행했으며, 기출문제를 거의 3회독 하고 갔다. 3회독 하면서 어디 과목이 문제인디 점수가 어떻게 되는지 확인하면서 진행했고, 대부분의 기사시험이나 자격증은 기출문제 3회독은 하고 가자는 마인드를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3회독을 하면서 어느 과목이 약한지, 평균 점수가 어느 정도 나오는지를 계속 체크했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 대부분의 기사시험이나 자격증은 &amp;ldquo;&lt;b&gt;기출문제 3회독은 하고 가자&lt;/b&gt;&amp;rdquo;라는 마인드를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어차피 개념이 제대로 잡히지 않은 문제는 몇 번을 풀어도 다시 틀리게 되어 있다. 그래서 오답 노트를 따로 만들어 &lt;b&gt;틀린 문제만 집중적으로 반복&lt;/b&gt;&lt;span&gt;하는 방식으로 보완했다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실기 공부 방법&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부기간 : 약 2~3주&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실기 책 : 2025 이기적 빅데이터분석기사 실기 Python (&lt;a href=&quot;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=361150212&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=361150212&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 전처리 흐름 이해 (결측치, 이상치)&lt;br /&gt;- 기본적인 pandas 코드 해석&lt;br /&gt;- 평가 지표 의미 정리 (Accuracy, Precision, Recall 등)&lt;br /&gt;- 회귀, 분류 확인 (Classifier, Regressor)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  코드를 외우기보다는 읽을 수 있어야 한다는 점이 핵심인것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPtPU8/dJMcaiu7ucv/1DH6UkxRpHb2FItGlCNGOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPtPU8/dJMcaiu7ucv/1DH6UkxRpHb2FItGlCNGOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPtPU8/dJMcaiu7ucv/1DH6UkxRpHb2FItGlCNGOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPtPU8%2FdJMcaiu7ucv%2F1DH6UkxRpHb2FItGlCNGOK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1088&quot; height=&quot;650&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;실기도 마찬가지로 노션에 정리하면서 진행했다. 작업형 1유형부분은 데이터 전처리 등을 다루고 있어서 데이터마님에 있는 문제로 열심히 풀었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;2유형은 거즘 짜진 템플릿이 있어서 해당 템플릿을 외워갔고, 거의 무적공식이라고 불리던 코드에 배신당했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이번회차 2유형에서는 랜덤포레스트 + 분류를 단순히 진행하면 25/40 밖에 주지 않았고, 이로 인해서 커뮤니티에서는 왜 25점밖에 안나오냐, 같은 모델을 썼는데 누군 왜 30점이냐,, 이런식의 반응이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  이 경험을 통해 느낀 점은 &amp;ldquo;템플릿은 안전장치일 뿐, 절대 정답은 아니다&amp;rdquo;라는 것. 앞으로는 템플릿을 외우되, &lt;b&gt;문제에서 요구하는 맥락을 더 잘 읽는 연습이 필요&lt;/b&gt;&lt;span&gt;하다고 느꼈다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;내가 사용한 코드는 아래와 같은 형식이었다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1766589110384&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score

train = pd.read_csv(&quot;train.csv&quot;)
test = pd.read_csv(&quot;test.csv&quot;)

le = LabelEncoder()
train['type'] = le.fit_transform(train['type'])
test['type'] = le.transform(test['type'])

x_tr, x_val, y_tr, y_val = train_test_split(train, y, test_size=0.2, random_state=42)
rf = RandomForestClassifier(random_state=42)
rf.fit(x_tr, y_tr)
pred = rf.predict(x_val)
print(f1_score(y_val, pred)

result = rf.predict(test)
submit = pd.DataFrame({&quot;pred&quot; : result}).to_csv(&quot;result.csv&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;3유형은 진짜 공부를 열심히 해야한다고 느꼈다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;어쩌다 시작했지만, &lt;span&gt;결과적으로는 &lt;/span&gt;&lt;b&gt;나름 만족스러운 자격증&lt;/b&gt;&lt;span&gt;이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;빅데이터분석기사를 준비하고 계신 분들 모두 너무 겁먹지 말고, &lt;span&gt;&lt;b&gt;기본 개념 + 기출 중심&lt;/b&gt;&lt;/span&gt;으로 차근차근 준비하시면 분명 좋은 결과가 있을 거라 생각한다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 글이 누군가에게 조금이라도 참고 자료가 되길 바라며, 준비하시는 모든 분들 &lt;span&gt;&lt;b&gt;합격을 응원합니다&lt;/b&gt;&lt;/span&gt;  &lt;/p&gt;</description>
      <category>이것저것</category>
      <category>11회 빅데이터분석기사</category>
      <category>기사 자격증</category>
      <category>빅데이터분석기사</category>
      <category>빅데이터분석기사 실기</category>
      <category>빅데이터분석기사 필기</category>
      <category>빅데이터분석기사 후기</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/593</guid>
      <comments>https://pental.tistory.com/593#entry593comment</comments>
      <pubDate>Thu, 25 Dec 2025 00:13:09 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 2703 - Cryptoquote (파이썬)</title>
      <link>https://pental.tistory.com/592</link>
      <description>&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;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0uMAP/dJMcahphl4B/GtfgvxkigzRTMBT2abbQak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0uMAP/dJMcahphl4B/GtfgvxkigzRTMBT2abbQak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0uMAP/dJMcahphl4B/GtfgvxkigzRTMBT2abbQak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0uMAP%2FdJMcahphl4B%2FGtfgvxkigzRTMBT2abbQak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;472&quot; data-origin-width=&quot;1150&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1763546602312&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys

t = int(sys.stdin.readline().strip())

for _ in range(t):
    encrypted = sys.stdin.readline().rstrip(&quot;\n&quot;)
    rule = sys.stdin.readline().strip()

    result_chars = []

    for ch in encrypted:
        if ch == &quot; &quot;:
            result_chars.append(&quot; &quot;)
        else:
            idx = ord(ch) - ord('A')
            result_chars.append(rule[idx])

    print(&quot;&quot;.join(result_chars))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 2703</category>
      <category>백준 2703 파이썬</category>
      <category>백준 Cryptoquote</category>
      <category>백준 Cryptoquote 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/592</guid>
      <comments>https://pental.tistory.com/592#entry592comment</comments>
      <pubDate>Wed, 19 Nov 2025 19:04:00 +0900</pubDate>
    </item>
    <item>
      <title>[빅데이터분석기사] 실기 대비 4일차 - 기출문제 4회</title>
      <link>https://pental.tistory.com/591</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 글은 개인적으로 공부하려고 작성한 내용입니다.&lt;br /&gt;만일 저작권 및 다른 이유로 인해 문제가 발생할 소지가 있다면&lt;br /&gt;pental@kakao.com 으로 메일 또는 해당 게시물에 댓글을 달아주시면 처리하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 내용은 빅데이터분석기사-2차실기 / 장은진 교수님의 강의를 듣고 개인적으로 추가 공부가 필요한 내용에 대해서 정리한 글입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 작업형 1유형 문제 1 &lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;-&amp;nbsp;주어진&amp;nbsp;데이터의&amp;nbsp;age&amp;nbsp;컬럼의&amp;nbsp;3사분위수와&amp;nbsp;1사분위수의&amp;nbsp;차를&amp;nbsp;절대값으로&amp;nbsp;구하고&amp;nbsp;정수형태로&amp;nbsp;출력하시오 &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;-&amp;nbsp;data&amp;nbsp;:&amp;nbsp;basic1.csv&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;먼저 import pandas 와 같이 기본적인 작업을 진행하고 데이터의 정보를 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393194714&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
df = pd.read_csv(&quot;./bigdata_csvfile/basic1.csv&quot;)
df

id	age	city	f1	f2	f3	f4	f5
0	id01	2.0	서울	NaN	0	NaN	ENFJ
1	id02	9.0	서울	70.0	1	NaN	ENFJ
2	id03	27.0	서울	61.0	1	NaN	ISTJ
3	id04	75.0	서울	NaN	2	NaN	INFP
4	id05	24.0	서울	85.0	2	NaN	ISFJ
...	...	...	...	...	...	...	...
95	id96	92.0	경기	53.0	1	NaN	ENTJ
96	id97	100.0	경기	NaN	0	NaN	INFP
97	id98	39.0	경기	58.0	2	NaN	INFP
98	id99	1.0	경기	47.0	0	NaN	ESFJ
99	id100	47.0	경기	53.0	0	vip	ESFP&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 100개의 행이 있으며 8개의 컬럼으로 이루어져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서는 age컬럼의 3사분위수와 1사분위수의 차의 절대값으로 구하라 했기에, quantile 함수를 통해서 3사분위수와 1사분위의를 구한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393229082&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Q3 = df['age'].quantile(0.75)
Q1 = df['age'].quantile(0.25)
# print(Q3) # 77.0
# print(Q1) # 26.875&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절대값 및 정수로 출력하기 위해서 다음과 같이 진행하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393239978&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = int(abs(Q3 - Q1)) # 50
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답 : 50&lt;/p&gt;
&lt;pre id=&quot;code_1762393255210&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 다른 답안
Q3 = df.age.quantile(.75)
Q1 = df.age.quantile(.25)
result = abs(Q3 - Q1)
print(int(result))&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 작업형 1유형 문제 2 &lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주어진 소셜 데이터에서 (loves 컬럼 + wows 컬럼) / (reactions 컬럼) 비율이 0.4보다 크고 0.5보다 작으면서, type = 'video'인 데이터의 개수를 구하시오&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;data : fb.csv&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762393297850&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
df = pd.read_csv(&quot;./bigdata_csvfile/fb.csv&quot;)
display(df)

id	type	reactions	comments	shares	likes	loves	wows	hahas	sads	angrys
0	1	video	529	512	262	432	92	3	1	1
1	2	photo	150	0	0	150	0	0	0	0
2	3	video	227	236	57	204	21	1	1	0
3	4	photo	111	0	0	111	0	0	0	0
4	5	photo	213	0	0	204	9	0	0	0
...	...	...	...	...	...	...	...	...	...	...
7045	7046	photo	89	0	0	89	0	0	0	0
7046	7047	photo	16	0	0	14	1	0	1	0
7047	7048	photo	2	0	0	1	1	0	0	0
7048	7049	photo	351	12	22	349	2	0	0	0
7049	7050	photo	17	0	0	17	0	0	0	0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;데이터는&amp;nbsp;7050행,&amp;nbsp;11개의&amp;nbsp;컬럼으로&amp;nbsp;이루어져&amp;nbsp;있다. &lt;br /&gt;&lt;br /&gt;먼저&amp;nbsp;문제에서&amp;nbsp;주어진&amp;nbsp;것처럼&amp;nbsp;데이터를&amp;nbsp;계산하기&amp;nbsp;위해서&amp;nbsp;`calc`&amp;nbsp;컬럼을&amp;nbsp;새로&amp;nbsp;만들어&amp;nbsp;(loves&amp;nbsp;+&amp;nbsp;wows)&amp;nbsp;/&amp;nbsp;reactions&amp;nbsp;의&amp;nbsp;값을&amp;nbsp;계산해주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393307338&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['calc'] = (df['loves'] + df['wows']) / df['reactions']
display(df['calc'])

0       0.179584
1       0.000000
2       0.096916
3       0.000000
4       0.042254
          ...   
7045    0.000000
7046    0.062500
7047    0.500000
7048    0.005698
7049    0.000000
Name: calc, Length: 7050, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 문제에서 주어진 조건식을 세워주었다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393316346&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond1 = df['calc'] &amp;gt; 0.4
cond2 = df['calc'] &amp;lt; 0.5
cond3 = df['type'] == 'video'
print(len(df[cond1 &amp;amp; cond2 &amp;amp; cond3])) # 50&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는&amp;nbsp;cond를&amp;nbsp;따로&amp;nbsp;나누어&amp;nbsp;조건식을&amp;nbsp;세웠지만&amp;nbsp;loc로도&amp;nbsp;작업이&amp;nbsp;가능하다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393332763&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.loc[(df['calc'] &amp;gt; 0.4) &amp;amp; (df['calc'] &amp;lt; 0.5) &amp;amp; (df['type'] == 'video')]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답 : 50&lt;/p&gt;
&lt;pre id=&quot;code_1762393343786&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 다른 풀이
df['ratio'] = (df.loves + df.wows) / df.reactions
result = (df.type == 'video') &amp;amp; (df.ratio &amp;gt; 0.4) &amp;amp; (df.ratio &amp;lt; 0.5) 
print(result.sum())&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 작업형 1유형 문제 3 &lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주어진 미디어 데이터에서 data_added가 2018년 1월 이면서 country가 United Kingdom 단독 제작인 데이터의 개수를 구하시오&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;data : nf.csv&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762393374434&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
df = pd.read_csv(&quot;./bigdata_csvfile/nf.csv&quot;)

display(df)

show_id	type	title	director	cast	country	date_added	release_year	rating	duration	listed_in
0	s1	Movie	Dick Johnson Is Dead	Kirsten Johnson	NaN	United States	September 25, 2021	2020	PG-13	90 min
1	s2	TV Show	Blood &amp;amp; Water	NaN	Ama Qamata, Khosi Ngema, Gail Mabalane, Thaban...	South Africa	September 24, 2021	2021	TV-MA	2 Seasons
2	s3	TV Show	Ganglands	Julien Leclercq	Sami Bouajila, Tracy Gotoas, Samuel Jouy, Nabi...	NaN	September 24, 2021	2021	TV-MA	1 Season
3	s4	TV Show	Jailbirds New Orleans	NaN	NaN	NaN	September 24, 2021	2021	TV-MA	1 Season
4	s5	TV Show	Kota Factory	NaN	Mayur More, Jitendra Kumar, Ranjan Raj, Alam K...	India	September 24, 2021	2021	TV-MA	2 Seasons
...	...	...	...	...	...	...	...	...	...	...
8802	s8803	Movie	Zodiac	David Fincher	Mark Ruffalo, Jake Gyllenhaal, Robert Downey J...	United States	November 20, 2019	2007	R	158 min
8803	s8804	TV Show	Zombie Dumb	NaN	NaN	NaN	July 1, 2019	2018	TV-Y7	2 Seasons&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&amp;nbsp;date_added&amp;nbsp;컬럼을&amp;nbsp;pd.to_datetime&amp;nbsp;함수를&amp;nbsp;통해서&amp;nbsp;pandas에서&amp;nbsp;자동으로&amp;nbsp;날짜&amp;nbsp;형식으로&amp;nbsp;변환시키도록&amp;nbsp;한다,&lt;/p&gt;
&lt;pre id=&quot;code_1762393388866&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['date_added'] = pd.to_datetime(df['date_added'])
display(df['date_added'])

0      2021-09-25
1      2021-09-24
2      2021-09-24
3      2021-09-24
4      2021-09-24
          ...    
8802   2019-11-20
8803   2019-07-01
8804   2019-11-01
8805   2020-01-11
8806   2019-03-02
Name: date_added, Length: 8807, dtype: datetime64[ns]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&amp;nbsp;되면&amp;nbsp;`df[&amp;rsquo;date_added&amp;rsquo;]`&amp;nbsp;컬럼은&amp;nbsp;데이터타입이&amp;nbsp;`datetime64`로&amp;nbsp;변하게&amp;nbsp;된다.&amp;nbsp;&amp;larr;&amp;nbsp;이건&amp;nbsp;중요 &lt;br /&gt;&lt;br /&gt;또한&amp;nbsp;연과&amp;nbsp;월을&amp;nbsp;구해야하기&amp;nbsp;때문에&amp;nbsp;`df[&amp;rsquo;date_added_month&amp;rsquo;]`,&amp;nbsp;`df[&amp;rsquo;date_added_year&amp;rsquo;]`&amp;nbsp;컬럼을&amp;nbsp;새로&amp;nbsp;생성해주었다.&amp;nbsp;이때,&amp;nbsp;`.dt.month`,&amp;nbsp;`.dt.year`을&amp;nbsp;사용하여&amp;nbsp;연과&amp;nbsp;월을&amp;nbsp;계산했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393399850&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['date_added_month'] = df['date_added'].dt.month
df['date_added_year'] = df['date_added'].dt.year&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한&amp;nbsp;조건식을&amp;nbsp;3개&amp;nbsp;세워서&amp;nbsp;2018년이면서&amp;nbsp;1월,&amp;nbsp;그리고&amp;nbsp;국가가&amp;nbsp;United&amp;nbsp;Kingdom&amp;nbsp;인&amp;nbsp;경우의&amp;nbsp;조건&amp;nbsp;3개를&amp;nbsp;세워줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393408522&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond1 = df['date_added_month'] == 1
cond2 = df['date_added_year'] == 2018
cond3 = df['country'] == &quot;United Kingdom&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건식에&amp;nbsp;&amp;amp;&amp;nbsp;필터링을&amp;nbsp;걸어서&amp;nbsp;계산한&amp;nbsp;결과를&amp;nbsp;출력한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393416458&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = df[cond1 &amp;amp; cond2 &amp;amp; cond3]
print(len(result)) # 6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답 : 6&lt;/p&gt;
&lt;pre id=&quot;code_1762393424434&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 다른 풀이
df.date_added = pd.to_datetime(df.date_added)
con1 = df['date_added'].dt.year == 2018
con2 = df['date_added'].dt.month == 1
con3 = df['country'] == &quot;United Kingdom&quot;

result = con1 &amp;amp; con2 &amp;amp; con3
print(result.sum())&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 2유형&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주어진 데이터를 활용하여 목표 변수 Segmentation에 대해 ID별로 Segmentation의 클래스를 예측해서 저장 후 제출하시오.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;단, 제출 데이터 컬럼은 ID와 Segmentation 두 개만 존재해야하고, index는 포함하지 않는다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;평가지표는 macro f1 score로 하고, 제출 파일 이름은 4th_test_type2.csv로 한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;train data : test4_type2_train.csv&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;test data : test4_type2_test.csv&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762393464762&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd

train = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_train.csv&quot;)
test = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_test.csv&quot;)

# EDA
display(train.head())
display(test.head())

ID	Gender	Ever_Married	Age	Graduated	Profession	Work_Experience	Spending_Score	Family_Size	Var_1	Segmentation
0	464357	Male	No	40	Yes	Artist	7.0	Low	1.0	Cat_6
1	459624	Male	No	18	No	Healthcare	NaN	Low	5.0	Cat_4
2	462672	Male	No	25	No	Healthcare	7.0	Low	4.0	Cat_4
3	463360	Female	Yes	46	Yes	Artist	2.0	Low	1.0	Cat_6
4	462420	Male	No	27	Yes	Healthcare	1.0	Low	3.0	Cat_6

	ID	Gender	Ever_Married	Age	Graduated	Profession	Work_Experience	Spending_Score	Family_Size	Var_1
0	460406	Male	Yes	36	Yes	Healthcare	3.0	Low	2.0	Cat_6
1	466890	Male	Yes	47	Yes	Artist	0.0	Average	6.0	Cat_7
2	466145	Male	Yes	56	No	Entertainment	1.0	Average	3.0	Cat_6
3	465805	Male	Yes	50	Yes	Engineer	NaN	Low	1.0	Cat_3
4	466137	Female	NaN	31	No	Healthcare	0.0	Low	4.0	Cat_6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각&amp;nbsp;`train`,&amp;nbsp;`test`의&amp;nbsp;`head`를&amp;nbsp;보여주고&amp;nbsp;있다.&amp;nbsp;`탐색적&amp;nbsp;EDA`를&amp;nbsp;진행한다.&amp;nbsp;(기본&amp;nbsp;정보&amp;nbsp;및&amp;nbsp;결측값&amp;nbsp;확인) &lt;br /&gt;&lt;br /&gt;먼저&amp;nbsp;결측값을&amp;nbsp;확인했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393489858&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(train.isnull().sum())
print()
print(test.isnull().sum())

ID                   0
Gender               0
Ever_Married        96
Age                  0
Graduated           51
Profession          64
Work_Experience    513
Spending_Score       0
Family_Size        192
Var_1               50
Segmentation         0
dtype: int64

ID                   0
Gender               0
Ever_Married        22
Age                  0
Graduated           16
Profession          23
Work_Experience    142
Spending_Score       0
Family_Size         68
Var_1               12
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재&amp;nbsp;train과&amp;nbsp;test&amp;nbsp;모두&amp;nbsp;결측값이&amp;nbsp;다량&amp;nbsp;존재한다.&amp;nbsp;이&amp;nbsp;값들을&amp;nbsp;모두&amp;nbsp;제거하기로&amp;nbsp;한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393502370&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 결측값은 제거

train.dropna(axis = 0, inplace = True)
test.dropna(axis = 0, inplace = True)

print(train.isnull().sum())
print(test.isnull().sum())


ID                 0
Gender             0
Ever_Married       0
Age                0
Graduated          0
Profession         0
Work_Experience    0
Spending_Score     0
Family_Size        0
Var_1              0
Segmentation       0
dtype: int64
ID                 0
Gender             0
Ever_Married       0
Age                0
Graduated          0
Profession         0
Work_Experience    0
Spending_Score     0
Family_Size        0
Var_1              0
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`dropna`&amp;nbsp;및&amp;nbsp;`axis&amp;nbsp;=&amp;nbsp;0`을&amp;nbsp;통해서&amp;nbsp;결측값&amp;nbsp;행을&amp;nbsp;모두&amp;nbsp;삭제해주었다.&amp;nbsp;이로&amp;nbsp;인해서&amp;nbsp;행&amp;nbsp;갯수가&amp;nbsp;변하게&amp;nbsp;되었다. &lt;br /&gt;&lt;br /&gt;`train`의&amp;nbsp;경우&amp;nbsp;결측값&amp;nbsp;제거전&amp;nbsp;4881개의&amp;nbsp;행,&amp;nbsp;결측값&amp;nbsp;제거&amp;nbsp;후&amp;nbsp;&amp;nbsp;4018행을&amp;nbsp;나타내고&amp;nbsp;있다.&amp;nbsp;대략&amp;nbsp;800개의&amp;nbsp;행이&amp;nbsp;제거되었다. &lt;br /&gt;&lt;br /&gt;`info`&amp;nbsp;함수를&amp;nbsp;통해서&amp;nbsp;라벨인코딩&amp;nbsp;전&amp;nbsp;어떤&amp;nbsp;값이&amp;nbsp;`object`&amp;nbsp;타입인지&amp;nbsp;알기&amp;nbsp;위해서&amp;nbsp;진행했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393515682&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(train.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
Index: 4018 entries, 0 to 4879
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   ID               4018 non-null   int64  
 1   Gender           4018 non-null   object 
 2   Ever_Married     4018 non-null   object 
 3   Age              4018 non-null   int64  
 4   Graduated        4018 non-null   object 
 5   Profession       4018 non-null   object 
 6   Work_Experience  4018 non-null   float64
 7   Spending_Score   4018 non-null   object 
 8   Family_Size      4018 non-null   float64
 9   Var_1            4018 non-null   object 
 10  Segmentation     4018 non-null   object 
dtypes: float64(2), int64(2), object(7)
memory usage: 376.7+ KB
None&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;object&amp;nbsp;타입인&amp;nbsp;친구들을&amp;nbsp;미리&amp;nbsp;알아두고&amp;nbsp;라벨인코딩을&amp;nbsp;진행한다.&amp;nbsp;라벨인코딩의&amp;nbsp;경우&amp;nbsp;sklearn의&amp;nbsp;LabelEncoder을&amp;nbsp;사용했다.&amp;nbsp;아래는&amp;nbsp;사용한&amp;nbsp;코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393524386&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.preprocessing import LabelEncoder
cols = ['Gender', 'Ever_Married', &quot;Graduated&quot;, &quot;Profession&quot;, &quot;Spending_Score&quot;, &quot;Var_1&quot;]

le = LabelEncoder()

for col in cols :
    le.fit(train[col])
    train[col] = le.transform(train[col])
    test[col] = le.transform(test[col])

print(train.info())
print(test.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
Index: 4018 entries, 0 to 4879
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   ID               4018 non-null   int64  
 1   Gender           4018 non-null   int64  
 2   Ever_Married     4018 non-null   int64  
 3   Age              4018 non-null   int64  
 4   Graduated        4018 non-null   int64  
 5   Profession       4018 non-null   int64  
 6   Work_Experience  4018 non-null   float64
 7   Spending_Score   4018 non-null   int64  
 8   Family_Size      4018 non-null   float64
 9   Var_1            4018 non-null   int64  
 10  Segmentation     4018 non-null   object 
dtypes: float64(2), int64(8), object(1)
memory usage: 376.7+ KB
None
&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
Index: 1288 entries, 0 to 1541
Data columns (total 10 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   ID               1288 non-null   int64  
...
 9   Var_1            1288 non-null   int64  
dtypes: float64(2), int64(8)
memory usage: 110.7 KB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&amp;nbsp;놓치기&amp;nbsp;쉬운점은&amp;nbsp;`train`에&amp;nbsp;대해서만&amp;nbsp;라벨인코딩을&amp;nbsp;진행하는것이&amp;nbsp;아닌&amp;nbsp;`test`&amp;nbsp;데이터에도&amp;nbsp;라벨&amp;nbsp;인코딩을&amp;nbsp;진행해야한다. &lt;br /&gt;&lt;br /&gt;모든&amp;nbsp;`object`&amp;nbsp;타입들이&amp;nbsp;`int64`로&amp;nbsp;변경된것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;이제&amp;nbsp;본격적으로&amp;nbsp;학습을&amp;nbsp;진행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393535554&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.model_selection import train_test_split
X = train.drop(columns = [&quot;Segmentation&quot;, &quot;ID&quot;])
y = train[&quot;Segmentation&quot;]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

(3214, 9) (804, 9) (3214,) (804,)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;X는&amp;nbsp;독립변수&amp;nbsp;y는&amp;nbsp;종속변수이다.&amp;nbsp;X에&amp;nbsp;`Segmentation`은&amp;nbsp;삭제하는게&amp;nbsp;당연하다.&amp;nbsp;종속변수이기&amp;nbsp;때문이다.&amp;nbsp;그런데&amp;nbsp;ID는&amp;nbsp;삭제한&amp;nbsp;이유는&amp;nbsp;학습에&amp;nbsp;도움이&amp;nbsp;되지&amp;nbsp;않는&amp;nbsp;값이기&amp;nbsp;때문에&amp;nbsp;`Segmentation`과&amp;nbsp;`ID`&amp;nbsp;모두&amp;nbsp;삭제했다. &lt;br /&gt;&lt;br /&gt;y는&amp;nbsp;종속변수이기에&amp;nbsp;`train[&amp;rdquo;Segmentation&amp;rdquo;]`의&amp;nbsp;단일&amp;nbsp;열을&amp;nbsp;가지도록&amp;nbsp;한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393547282&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(n_estimators = 95, max_depth = 6, random_state = 123)
rfc.fit(X_train, y_train)
pred = rfc.predict(X_test)
print(pred[:5])

['A' 'C' 'C' 'D' 'A']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랜덤포레스트를&amp;nbsp;통해서&amp;nbsp;학습을&amp;nbsp;진행한다.&amp;nbsp;문제에서는&amp;nbsp;f1_score의&amp;nbsp;결과를&amp;nbsp;평가지표로&amp;nbsp;사용한다&amp;nbsp;했기에&amp;nbsp;f1&amp;nbsp;값을&amp;nbsp;계산한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393556498&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.metrics import f1_score, accuracy_score

f1 = f1_score(pred, y_test, average = &quot;macro&quot;)
print(&quot;f1: &quot;, f1) # f1:  0.505136752530129

acc = accuracy_score(pred, y_test)
print(&quot;acc : &quot;, acc) # acc :  0.5211442786069652&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;accuracy_score는&amp;nbsp;그냥&amp;nbsp;정확도&amp;nbsp;확인을&amp;nbsp;위해서&amp;nbsp;사용했다. &lt;br /&gt;&lt;br /&gt;여기서&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;test&amp;nbsp;데이터에서도&amp;nbsp;동일하게&amp;nbsp;ID를&amp;nbsp;삭제한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393564442&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;data = test.drop(columns = &quot;ID&quot;)
result = rfc.predict(data)
df = pd.DataFrame(
    {
        &quot;ID&quot; : test[&quot;ID&quot;],
        &quot;Segentation&quot; : result
    }
).to_csv(&quot;4th_test_type2.csv&quot;, index = False)

display(pd.read_csv(&quot;4th_test_type2.csv&quot;))

ID	Segentation
0	460406	D
1	466890	C
2	466145	B
3	467572	C
4	460767	B
...	...	...
1283	463734	A
1284	466055	B
1285	465689	D
1286	460401	A
1287	465215	B
1288 rows &amp;times; 2 columns&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한&amp;nbsp;`ID`&amp;nbsp;및&amp;nbsp;`Segmentation`을&amp;nbsp;제출하라&amp;nbsp;했기에,&amp;nbsp;`test[&amp;rdquo;ID&amp;rdquo;]`를&amp;nbsp;통해서&amp;nbsp;ID값을&amp;nbsp;추가했다. &lt;br /&gt;&lt;br /&gt;근데&amp;nbsp;모델의&amp;nbsp;평가지표가&amp;nbsp;너무&amp;nbsp;낮아서&amp;nbsp;모델&amp;nbsp;향상을&amp;nbsp;진행해보려고&amp;nbsp;한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393576234&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd

train = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_train.csv&quot;)
test = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_test.csv&quot;)

cols = ['Ever_Married', &quot;Graduated&quot;, &quot;Profession&quot;, &quot;Work_Experience&quot;, &quot;Family_Size&quot;, &quot;Var_1&quot;]

for col in cols :
    train[col] = train[col].fillna(train[col].mode()[0])
    test[col] = test[col].fillna(test[col].mode()[0])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결측값을&amp;nbsp;제거하는&amp;nbsp;것이&amp;nbsp;아닌&amp;nbsp;최빈값으로&amp;nbsp;대체하는&amp;nbsp;방법을&amp;nbsp;사용해보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393585538&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;train.info()

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 4881 entries, 0 to 4880
Data columns (total 11 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   ID               4881 non-null   int64  
 1   Gender           4881 non-null   object 
 2   Ever_Married     4881 non-null   object 
 3   Age              4881 non-null   int64  
 4   Graduated        4881 non-null   object 
 5   Profession       4881 non-null   object 
 6   Work_Experience  4881 non-null   float64
 7   Spending_Score   4881 non-null   object 
 8   Family_Size      4881 non-null   float64
 9   Var_1            4881 non-null   object 
 10  Segmentation     4881 non-null   object 
dtypes: float64(2), int64(2), object(7)
memory usage: 419.6+ KB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 동일하게 라벨인코딩을 진행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393593330&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.preprocessing import LabelEncoder
cols = [&quot;Gender&quot;, &quot;Ever_Married&quot;, &quot;Graduated&quot;, &quot;Profession&quot; ,&quot;Spending_Score&quot;, &quot;Var_1&quot;]

le = LabelEncoder()
for col in cols :
    le.fit(train[col])
    train[col] = le.transform(train[col])
    test[col] = le.transform(test[col])&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762393599514&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.model_selection import train_test_split
X = train.drop(columns = [&quot;ID&quot;, &quot;Segmentation&quot;])
y = train[&quot;Segmentation&quot;]

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)

from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(n_estimators = 95, max_depth = 6, random_state = 42)
rfc.fit(X_train, y_train)
pred = rfc.predict(X_test)

from sklearn.metrics import f1_score, accuracy_score

f1 = f1_score(pred, y_test, average = 'macro')
acc = accuracy_score(pred, y_test)
print(&quot;F1 : &quot;, f1) # F1 :  0.4509502343284842
print(&quot;ACC : &quot;, acc) # ACC :  0.46980552712384854&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결측값을&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;있다.&amp;nbsp;~~이러면&amp;nbsp;나가리인데~~ &lt;br /&gt;&lt;br /&gt;다음은&amp;nbsp;`LabelEncoder`을&amp;nbsp;사용하지&amp;nbsp;않고,&amp;nbsp;`pd.get_dummies()`함수를&amp;nbsp;사용해보고자&amp;nbsp;한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762393630745&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd

train = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_train.csv&quot;)
test = pd.read_csv(&quot;./bigdata_csvfile/test4_type2_test.csv&quot;)

cols = ['Ever_Married', &quot;Graduated&quot;, &quot;Profession&quot;, &quot;Work_Experience&quot;, &quot;Family_Size&quot;, &quot;Var_1&quot;]

for col in cols :
    train[col] = train[col].fillna(train[col].mode()[0])
    test[col] = test[col].fillna(test[col].mode()[0])
    
cols = [&quot;Gender&quot;, 'Ever_Married', &quot;Graduated&quot;, &quot;Profession&quot;, &quot;Spending_Score&quot;, &quot;Var_1&quot;]
train = pd.get_dummies(train, columns = cols)
test = pd.get_dummies(test, columns = cols)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 42)
from sklearn.metrics import f1_score, accuracy_score
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators = 95, max_depth = 6, random_state=42)
rf.fit(X_train, y_train)
pred = rf.predict(X_test)

f1 = f1_score(pred, y_test, average = 'macro')
acc = accuracy_score(pred, y_test)
print(f1, acc) # 0.4509502343284842 0.46980552712384854&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같다..&amp;nbsp;이러면&amp;nbsp;LabelEncoder와&amp;nbsp;pd.get_dummies()가&amp;nbsp;같은건가,,?&lt;/p&gt;</description>
      <category>Programming/빅데이터분석기사 실기</category>
      <category>빅데이터분석기사</category>
      <category>빅데이터분석기사 기출문제</category>
      <category>빅데이터분석기사 실기</category>
      <category>빅데이터분석기사 실기 기출문제</category>
      <category>빅분기</category>
      <category>빅분기 실기</category>
      <category>빅분기 실기 기출</category>
      <category>빅분기 실기 기출문제</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/591</guid>
      <comments>https://pental.tistory.com/591#entry591comment</comments>
      <pubDate>Thu, 6 Nov 2025 10:48:01 +0900</pubDate>
    </item>
    <item>
      <title>[빅데이터분석기사] 실기 대비 3일차 - 기출문제 3회</title>
      <link>https://pental.tistory.com/590</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 글은 개인적으로 공부하려고 작성한 내용입니다.&lt;br /&gt;만일 저작권 및 다른 이유로 인해 문제가 발생할 소지가 있다면&lt;br /&gt;pental@kakao.com 으로 메일 또는 해당 게시물에 댓글을 달아주시면 처리하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 내용은 빅데이터분석기사-2차실기 / 장은진 교수님의 강의를 듣고 개인적으로 추가 공부가 필요한 내용에 대해서 정리한 글입니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 1&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;주어진&amp;nbsp;데이터&amp;nbsp;중&amp;nbsp;컬럼들의&amp;nbsp;결측값을&amp;nbsp;전부&amp;nbsp;제거한&amp;nbsp;후&amp;nbsp;데이터를&amp;nbsp;처음부터&amp;nbsp;순서대로&amp;nbsp;70%를&amp;nbsp;추출하여&amp;nbsp;housing_median_age&amp;nbsp;컬럼의&amp;nbsp;1분위수를&amp;nbsp;산출해라. &lt;/b&gt;&lt;br /&gt;&lt;b&gt;(단,&amp;nbsp;출력&amp;nbsp;결과는&amp;nbsp;정수형태로&amp;nbsp;한다.)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1762307251101&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
df = pd.read_csv(&quot;./bigdata_csvfile/california_housing.csv&quot;)
display(df.head())

longitude	latitude	housing_median_age	total_rooms	total_bedrooms	population	households	median_income	median_house_value	ocean_proximity
0	-122.23	37.88	41.0	880.0	129.0	322.0	126.0	8.3252	452600.0
1	-122.22	37.86	21.0	7099.0	1106.0	2401.0	1138.0	8.3014	358500.0
2	-122.24	37.85	52.0	1467.0	190.0	496.0	177.0	7.2574	352100.0
3	-122.25	37.85	52.0	1274.0	235.0	558.0	219.0	5.6431	341300.0
4	-122.25	37.85	52.0	1627.0	280.0	565.0	259.0	3.8462	342200.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pd를 통해서 데이터를 읽어온다. california_housing.csv 파일.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;켈리포니아&amp;nbsp;하우스&amp;nbsp;데이터는&amp;nbsp;어디서나&amp;nbsp;쓰이는거&amp;nbsp;같은데,,,&amp;nbsp;좀더&amp;nbsp;분석해두면&amp;nbsp;좋을&amp;nbsp;것&amp;nbsp;같다. &lt;br /&gt;&lt;br /&gt;먼저&amp;nbsp;문제에서&amp;nbsp;결측값을&amp;nbsp;전부&amp;nbsp;제거하라&amp;nbsp;했기&amp;nbsp;때문에&amp;nbsp;`.isnull()`&amp;nbsp;함수를&amp;nbsp;통해서&amp;nbsp;결측값을&amp;nbsp;모두&amp;nbsp;제거한다.&amp;nbsp;먼저&amp;nbsp;결측값의&amp;nbsp;데이터를&amp;nbsp;확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307276589&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(df.isnull().sum())

longitude               0
latitude                0
housing_median_age      0
total_rooms             0
total_bedrooms        207
population              0
households              0
median_income           0
median_house_value      0
ocean_proximity         0
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터&amp;nbsp;분석&amp;nbsp;결과&amp;nbsp;total_bedrooms&amp;nbsp;컬럼에서&amp;nbsp;207개의&amp;nbsp;결측값이&amp;nbsp;확인&amp;nbsp;되었다.&amp;nbsp;이&amp;nbsp;값을&amp;nbsp;모두&amp;nbsp;날리기&amp;nbsp;위해서&amp;nbsp;.dropna()&amp;nbsp;함수를&amp;nbsp;통해서&amp;nbsp;결측값을&amp;nbsp;제거한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307287949&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = df.dropna(axis = 0)
print(df.isnull().sum())

longitude             0
latitude              0
housing_median_age    0
total_rooms           0
total_bedrooms        0
population            0
households            0
median_income         0
median_house_value    0
ocean_proximity       0
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재&amp;nbsp;위&amp;nbsp;isnull&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;len()&amp;nbsp;함수를&amp;nbsp;통해&amp;nbsp;확인하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307297381&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(len(df)) # 전체 : 20433&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 행 갯수는 20433개로 확인되었으며 아래와 같이 70%로 나누기 위해서 전체 행 * 0.7을 통해서 70%의 행을 계산했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307309781&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(len(df) * 0.7) # 70% 행 : 14303.09999999&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;70% 행을 슬라이싱 하기 위해서 iloc을 통해 14303개의 행만 따로 분리 후 quantile을 통해서 1분위수를 산출한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307321045&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = df.iloc[:14303, :]
print(int(df['housing_median_age'].quantile(0.25))) # 19&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 19&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 2&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 4개년도 (2000, 2006, 2012, 2021)에 대한 국가별 기아의 수치 데이터에서 2000년 전체 기아 수치의 평균을 구하고, 2000년 데이터를 대상으로 연산된 평균보다 큰 값을 갖는 국가의 수를 산출하시오&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762307350469&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/global_hunger_data.csv&quot;)
display(df.head())

Entity	Code	Year	Global Hunger Index
0	Afghanistan	AFG	2000
1	Afghanistan	AFG	2006
2	Afghanistan	AFG	2012
3	Afghanistan	AFG	2021
4	Albania	ALB	2000&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기아의&amp;nbsp;수치&amp;nbsp;데이터에서&amp;nbsp;2000년&amp;nbsp;전체&amp;nbsp;기아수치의&amp;nbsp;평균을&amp;nbsp;구하기&amp;nbsp;위해서&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;조건식을&amp;nbsp;세운다. &lt;br /&gt;&lt;br /&gt;조건식을&amp;nbsp;세우고&amp;nbsp;`Global&amp;nbsp;Hunger&amp;nbsp;Index`&amp;nbsp;컬럼의&amp;nbsp;평균을&amp;nbsp;계산한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307368997&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond = df['Year'] == 2000
hunger_avg = (df[cond]['Global Hunger Index'].mean())
print(hunger_avg) # 24.439285714285717&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;결과&amp;nbsp;24.439285714285717라는&amp;nbsp;수치가&amp;nbsp;나왔으며&amp;nbsp;이&amp;nbsp;값은&amp;nbsp;hunger_avg&amp;nbsp;변수에&amp;nbsp;저장한다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;평균을&amp;nbsp;구했기&amp;nbsp;때문에&amp;nbsp;2000년&amp;nbsp;이며&amp;nbsp;평균&amp;nbsp;수치보다&amp;nbsp;큰&amp;nbsp;국가의&amp;nbsp;갯수를&amp;nbsp;계산하기&amp;nbsp;위해서&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;조건식&amp;nbsp;2개를&amp;nbsp;세운다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307380934&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond1 = df['Year'] == 2000
cond2 = df['Global Hunger Index'] &amp;gt; hunger_avg

print(len(df[cond1 &amp;amp; cond2])) # 50&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답&amp;nbsp;:&amp;nbsp;50&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 풀이로는 다음과 같이 짤수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307393229&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 다른 답안
df = pd.read_csv(&quot;./bigdata_csvfile/global_hunger_data.csv&quot;)
df.sort_values('Year', ascending = True, inplace = True)
data_2000 = df.loc[df['Year'] == 2000]
mean = data_2000['Global Hunger Index'].mean()
# print(mean)
result = data_2000['Entity'].loc[data_2000['Global Hunger Index'] &amp;gt; mean].size
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 3&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 주어진 데이터의 컬럼별로 결측값들의 비율을 확인하여 결측값의 비율이 가장 높은 변수명을 출력하시오&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1762307422125&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/titanic.csv&quot;)
display(df.head())

PassengerId	Survived	Pclass	Name	Sex	Age	SibSp	Parch	Ticket	Fare	Cabin	Embarked
0	1	0	3	Braund, Mr. Owen Harris	male	22.0	1	0	A/5 21171	7.2500	NaN
1	2	1	1	Cumings, Mrs. John Bradley (Florence Briggs Th...	female	38.0	1	0	PC 17599	71.2833	C85
2	3	1	3	Heikkinen, Miss. Laina	female	26.0	0	0	STON/O2. 3101282	7.9250	NaN
3	4	1	1	Futrelle, Mrs. Jacques Heath (Lily May Peel)	female	35.0	1	0	113803	53.1000	C123
4	5	0	3	Allen, Mr. William Henry	male	35.0	0	0	373450	8.0500	NaN&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결측값을 확인하기 위해서 isnull() 함수를 사용했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307435789&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(df.isnull().sum())

PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762307440997&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;info의 갯수에서 총 891개의 행이 존재하며, cabin 컬럼에서는 687개의 결측값이 존재한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 답은 Cabin 컬럼에서 결측값이 제일 많이 때문에 Cabin 컬럼이 정답이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307450277&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;age_data = (sum(df['Age'].isna()) / 891) * 100
print(age_data) # 19.865319865319865
cabin_data = (sum(df['Cabin'].isna()) / 891) * 100
print(cabin_data) # 77.10437710437711
embarked_data = (sum(df['Embarked'].isna()) / 891) * 100
print(embarked_data) # 0.22446689113355783&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 2유형&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음은&amp;nbsp;여행객&amp;nbsp;정보&amp;nbsp;데이터를&amp;nbsp;기반으로&amp;nbsp;여행보험&amp;nbsp;상품가입&amp;nbsp;여부(TravelInsurance)가&amp;nbsp;1일&amp;nbsp;확률을&amp;nbsp;예측하시오. &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;단,&amp;nbsp;평가지표는&amp;nbsp;roc_auc_score로&amp;nbsp;하고,&amp;nbsp;제출&amp;nbsp;파일의&amp;nbsp;컬름은&amp;nbsp;cust_id(인덱스&amp;nbsp;번호),&amp;nbsp;Insurance(가입여부)&amp;nbsp;두&amp;nbsp;개만&amp;nbsp;존재해야&amp;nbsp;하며,&amp;nbsp;제출&amp;nbsp;파일&amp;nbsp;이름은&amp;nbsp;3rd_test_type2.csv로&amp;nbsp;한다. &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;train&amp;nbsp;=&amp;nbsp;test3_type2_train.csv &lt;/b&gt;&lt;br /&gt;&lt;b&gt;test&amp;nbsp;=&amp;nbsp;test3_type2_test.csv&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 train과 test 데이터를 불러온다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307482541&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd

train = pd.read_csv(&quot;./bigdata_csvfile/test3_type2_train.csv&quot;)
test = pd.read_csv(&quot;./bigdata_csvfile/test3_type2_test.csv&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로&amp;nbsp;EDA&amp;nbsp;를&amp;nbsp;진행하여,&amp;nbsp;결측값,&amp;nbsp;이상치&amp;nbsp;등을&amp;nbsp;모두&amp;nbsp;확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307498285&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(train.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 1490 entries, 0 to 1489
Data columns (total 10 columns):
 #   Column               Non-Null Count  Dtype 
---  ------               --------------  ----- 
 0   ID                   1490 non-null   int64 
 1   Age                  1490 non-null   int64 
 2   Employment Type      1490 non-null   object
 3   GraduateOrNot        1490 non-null   object
 4   AnnualIncome         1490 non-null   int64 
 5   FamilyMembers        1490 non-null   int64 
 6   ChronicDiseases      1490 non-null   int64 
 7   FrequentFlyer        1490 non-null   object
 8   EverTravelledAbroad  1490 non-null   object
 9   TravelInsurance      1490 non-null   int64 
dtypes: int64(6), object(4)
memory usage: 116.5+ KB
None

print(test.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 497 entries, 0 to 496
Data columns (total 9 columns):
 #   Column               Non-Null Count  Dtype 
---  ------               --------------  ----- 
 0   ID                   497 non-null    int64 
 1   Age                  497 non-null    int64 
 2   Employment Type      497 non-null    object
 3   GraduateOrNot        497 non-null    object
 4   AnnualIncome         497 non-null    int64 
 5   FamilyMembers        497 non-null    int64 
 6   ChronicDiseases      497 non-null    int64 
 7   FrequentFlyer        497 non-null    object
 8   EverTravelledAbroad  497 non-null    object
dtypes: int64(5), object(4)
memory usage: 35.1+ KB
None

print(train.isnull().sum())

ID                     0
Age                    0
Employment Type        0
GraduateOrNot          0
AnnualIncome           0
FamilyMembers          0
ChronicDiseases        0
FrequentFlyer          0
EverTravelledAbroad    0
TravelInsurance        0
dtype: int64

print(test.isnull().sum())

ID                     0
Age                    0
Employment Type        0
GraduateOrNot          0
AnnualIncome           0
FamilyMembers          0
ChronicDiseases        0
FrequentFlyer          0
EverTravelledAbroad    0
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결측값도 이상이 없고, 다른 특이적인 EDA는 발견되지 않았기에 학습 준비를 시작한다. 문제에서도&amp;nbsp;주어졌듯이&amp;nbsp;`roc_auc_score`를&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;br /&gt;&lt;br /&gt;`train.info()`&amp;nbsp;결과에서&amp;nbsp;`object`타입으로&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;데이터들의&amp;nbsp;`value_counts`를&amp;nbsp;계산해&amp;nbsp;보았다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307517613&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cols = [&quot;Employment Type&quot;, &quot;GraduateOrNot&quot;, &quot;FrequentFlyer&quot;, &quot;EverTravelledAbroad&quot;]
for col in cols :
    print(train[col].value_counts())

Employment Type
Private Sector/Self Employed    1061
Government Sector                429
Name: count, dtype: int64
GraduateOrNot
Yes    1262
No      228
Name: count, dtype: int64
FrequentFlyer
No     1185
Yes     305
Name: count, dtype: int64
EverTravelledAbroad
No     1207
Yes     283
Name: count, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의&amp;nbsp;컬럼에서는&amp;nbsp;0&amp;nbsp;또는&amp;nbsp;1로&amp;nbsp;분류될수&amp;nbsp;있는&amp;nbsp;데이터들로&amp;nbsp;이루어져있기&amp;nbsp;때문에&amp;nbsp;sklearn의&amp;nbsp;preprocessing의&amp;nbsp;LabelEncoder를&amp;nbsp;사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307530709&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.preprocessing import LabelEncoder

for col in cols :
    le = LabelEncoder()
    le.fit(train[col])
    train[col] = le.transform(train[col])

for col in cols :
    le = LabelEncoder()
    le.fit(test[col])
    test[col] = le.transform(test[col])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한&amp;nbsp;점은&amp;nbsp;train데이터에&amp;nbsp;라벨인코딩을&amp;nbsp;할&amp;nbsp;경우,&amp;nbsp;test&amp;nbsp;데이터에도&amp;nbsp;동일하게&amp;nbsp;라벨인코딩을&amp;nbsp;진행해주어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이부분에서 잘못됐다. train과 test를 합치고 라벨인코딩하고 다시 합쳤어야했다고 한다.&lt;br /&gt;&lt;br /&gt;그리고&amp;nbsp;종속변수와&amp;nbsp;독립변수를&amp;nbsp;나눈다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307568261&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.model_selection import train_test_split
X = train.drop(columns = [&quot;TravelInsurance&quot;])
y = train['TravelInsurance']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;train_test_split&amp;nbsp;함수를&amp;nbsp;통해서&amp;nbsp;X_train,&amp;nbsp;X_test,&amp;nbsp;y_train,&amp;nbsp;y_test를&amp;nbsp;나누고,&amp;nbsp;RandomForestClassifier을&amp;nbsp;통해서&amp;nbsp;분류를&amp;nbsp;진행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307577797&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
print(X_train.shape, X_test.shape, y_train.shape, y_test. shape)
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier(n_estimators = 200, max_depth = 25, random_state = 123)
rfc.fit(X_train, y_train)
pred = rfc.predict_proba(X_test)[:, 1]
from sklearn.metrics import roc_auc_score
roc = roc_auc_score(y_test, pred)
print(roc)

(1192, 9) (298, 9) (1192,) (298,)
0.8137515644555694&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;81%라는&amp;nbsp;높은&amp;nbsp;정확도를&amp;nbsp;가지고&amp;nbsp;있으며,&amp;nbsp;여기서&amp;nbsp;중요한점은&amp;nbsp;1일&amp;nbsp;확률을&amp;nbsp;계산하라&amp;nbsp;했기&amp;nbsp;때문에&amp;nbsp;`predict_proba`를&amp;nbsp;통해서&amp;nbsp;예측하였다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;이때&amp;nbsp;진짜&amp;nbsp;중요한점은&amp;nbsp;`predict(X_test)`와&amp;nbsp;달리&amp;nbsp;`predict_proba(X_test)[:,&amp;nbsp;1]`이&amp;nbsp;되어야&amp;nbsp;한다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;그&amp;nbsp;이유는&amp;nbsp;`predict_proba`는&amp;nbsp;이딴식으로&amp;nbsp;되어&amp;nbsp;있기&amp;nbsp;때문,,,&amp;nbsp;아마&amp;nbsp;0일&amp;nbsp;확률을&amp;nbsp;계산하라&amp;nbsp;했으면&amp;nbsp;`[:,&amp;nbsp;0]`&amp;nbsp;이&amp;nbsp;되어야&amp;nbsp;할것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762307589300&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;array([[0.875     , 0.125     ],
       [0.71      , 0.29      ],
       [0.89      , 0.11      ],
       [0.9       , 0.1       ],
       [0.69      , 0.31      ],
       [0.82      , 0.18      ],&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762307595349&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pred = rfc.predict_proba(test)[:, 1]
pd.DataFrame(
    {
        'cust_id' : test.index,
        'insurance' : pred
    }
).to_csv(&quot;3rd_test_type2.csv&quot;, index = False)

print(pd.read_csv(&quot;3rd_test_type2.csv&quot;).head())

   cust_id  insurance
0        0      0.240
1        1      0.260
2        2      0.345
3        3      0.135
4        4      0.415&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;train데이터로 진행을 했으니 test데이터로 마지막 과정을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;test.index 메모.&lt;/p&gt;</description>
      <category>Programming/빅데이터분석기사 실기</category>
      <category>빅데이터분석기사</category>
      <category>빅데이터분석기사 기출문제</category>
      <category>빅데이터분석기사 실기</category>
      <category>빅데이터분석기사 실기 기출문제</category>
      <category>빅분기</category>
      <category>빅분기 실기</category>
      <category>빅분기 실기 기출</category>
      <category>빅분기 실기 기출문제</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/590</guid>
      <comments>https://pental.tistory.com/590#entry590comment</comments>
      <pubDate>Wed, 5 Nov 2025 10:53:54 +0900</pubDate>
    </item>
    <item>
      <title>[빅데이터분석기사] 실기 대비 2일차 - 기출문제 2회</title>
      <link>https://pental.tistory.com/589</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 글은 개인적으로 공부하려고 작성한 내용입니다.&lt;br /&gt;만일 저작권 및 다른 이유로 인해 문제가 발생할 소지가 있다면&lt;br /&gt;pental@kakao.com 으로 메일 또는 해당 게시물에 댓글을 달아주시면 처리하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #222222; text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 내용은 빅데이터분석기사-2차실기 / 장은진 교수님의 강의를 듣고 개인적으로 추가 공부가 필요한 내용에 대해서 정리한 글입니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #222222; text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 1번&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;주어진 Dataset에서 'CRIM' 값이 가장 큰 10개의 지역을 구하고 10개의 지역의 'CRIM' 값을 그 중 가장 작은 값으로 대체한 후, 'AGE' 컬럼 값이 80이상인 행의 'CRIM' 평균을 구하시오 (단, 출력 결과는 정수형으로 한다.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1762150185792&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
df = pd.read_csv(&quot;./bigdata_csvfile/boston_housing_data.csv&quot;)
df&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터는 총 506개의 행, 14개의 열로 이루어져있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서는 CRIM 값이 가장 큰 10개의 지역을 구하라고 했기에 sort_values 함수를 이용해서 내림차순 정렬을 진행했다. (내림차순의 경우 ascending = False 옵션을 통해 진행한다.)&lt;/p&gt;
&lt;pre id=&quot;code_1762150212687&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.sort_values(&quot;CRIM&quot;, ascending = False, inplace = True)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬 결과를 df 자체에 결과하기 위해서 inplace = True 옵션을 통해서 df에 바로 반영되도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10개의 지역이 뽑혔기 때문에, 이 중 CRIM 값이 제일 작은것은 9번 인덱스에 있는 행일 것이다. 그에 따라 iloc[9]을 통해서 최소 CRIM을 따로 변수에 저장한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150224655&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;min_crim = df.iloc[9]['CRIM']&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&amp;nbsp;이&amp;nbsp;최소&amp;nbsp;CRIM&amp;nbsp;값을&amp;nbsp;가장&amp;nbsp;큰&amp;nbsp;10개의&amp;nbsp;지역에&amp;nbsp;모두&amp;nbsp;대체해야&amp;nbsp;하기&amp;nbsp;때문에&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;iloc를&amp;nbsp;통해서&amp;nbsp;min_crim으로&amp;nbsp;대체했다.&amp;nbsp;[:10,&amp;nbsp;0]&amp;nbsp;을&amp;nbsp;사용한&amp;nbsp;이유는&amp;nbsp;10개까지의&amp;nbsp;행에&amp;nbsp;대해서&amp;nbsp;0번&amp;nbsp;컬럼(CRIM)의&amp;nbsp;값을&amp;nbsp;min_crim&amp;nbsp;으로&amp;nbsp;대체한다는&amp;nbsp;것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150242983&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.iloc[:10, 0] = min_crim
result = df.loc[df['AGE'] &amp;gt;= 80, 'CRIM'].mean()
print(int(result))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 5&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 2번&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;주어진 Dataset에서 첫번째 행 부터 순서대로 80% 까지의 데이터를 추출 후'total_bedrooms' 컬럼의 중앙값으로 해당 컬럼의 중앙값으로 행당 컬럼의 결측치를 대체하고 'total_bedrooms' 컬럼의 대치 전후의 표준편차 차이를 구하시오&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1762150265183&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/california_housing.csv&quot;)
df.head()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 데이터를 불러오고 어떻게 생겼는지 확인한다. 일단 80%의 데이터를 추출해야하기 때문에 전체 행의 갯수에서 0.8을 통해서 자를 위치를 구했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150282255&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;len(df) * 0.8 # 16512.0
df = df.iloc[:16512, :]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;df.iloc를 통해서 전체 열에 대해서 16512행까지의 결과를 df에 저장한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150293559&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std1 = df['total_bedrooms'].std()
median = df['total_bedrooms'].median()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고나서&amp;nbsp;표준편차와&amp;nbsp;중앙값을&amp;nbsp;구하기&amp;nbsp;위해서&amp;nbsp;.std(),&amp;nbsp;.median()&amp;nbsp;을&amp;nbsp;사용했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150304591&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['total_bedrooms'] = df['total_bedrooms'].fillna(median)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구한&amp;nbsp;median&amp;nbsp;값을&amp;nbsp;결측값에&amp;nbsp;대치하기&amp;nbsp;위해서&amp;nbsp;.fillna()를&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;.std()를&amp;nbsp;사용해서&amp;nbsp;표준편차를&amp;nbsp;계산한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150315223&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std2 = df['total_bedrooms'].std()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 구해놓은 std1과 std2의 차를 계산한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150322335&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(std1 - std2)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 1.975147291645726&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 1유형 문제 3번&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;주어진 데이터의 population 컬럼의 평균으로부터 1.5x표준편차를 벗어나는 영역을 이상치라 판단하고 이상치들의 합을 구하시오. (단, 출력 결과는 정수형태로 하고 이상치는 '평균 - 1.5x표준편차 미만' 또는 '평균 + 1.5x표준편차 초과' 로 연산한다.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 먼저 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150358191&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/california_housing.csv&quot;)
df.head()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762150364711&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;std = df['population'].std()
mean = df['population'].mean()
print(std, mean) # np.float64(1132.462121765341), np.float64(1425.4767441860465)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표준편차를&amp;nbsp;계산하기&amp;nbsp;위해서&amp;nbsp;df[&amp;rsquo;population&amp;rsquo;].std()를&amp;nbsp;통해서&amp;nbsp;표준편차를&amp;nbsp;계산했고,&amp;nbsp;평균을&amp;nbsp;구하기&amp;nbsp;위해서는&amp;nbsp;.mean()&amp;nbsp;함수를&amp;nbsp;사용했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150373399&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;lower = mean - 1.5 * std
upper = mean + 1.5 * std

print(lower, upper) # -273.2164384619648 3124.169926834058&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 비슷한 유형으로 IQR 이상치 계산이 나오는걸로 기억하는데, 이 문제는 특이하게도 평균 - 1.5*표준편차 식으로 계산하라고 되어 있다. 따라서 lower와 upper 변수를 생성하여 이상치의 범위를 미리 계산해두었다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150382223&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond1 = df['population'] &amp;lt; lower
cond2 = df['population'] &amp;gt; upper&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산 해둔 결과르 바탕으로 조건식을 세운다. 평균 +- 1.5 * 표준편차의 조건을 총 2개를 세웠다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150390550&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(int(df[cond1 | cond2]['population'].sum())) # 5607295&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 `OR` 연산일 경우는 `|` 를 쓴다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;다른&amp;nbsp;방법으로&amp;nbsp;조건&amp;nbsp;계산하는&amp;nbsp;식이&amp;nbsp;있지만&amp;nbsp;나는&amp;nbsp;별로&amp;nbsp;좋아하는&amp;nbsp;방법은&amp;nbsp;아니다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150413814&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 다른 방법 조건 계산
result = df['population'].loc[(df['population'] &amp;gt; upper) | (df['population'] &amp;lt; lower)].sum()
print(int(result)) # 5607295&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답만 잘 나오면 장땡 아닌교~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답 : 5607295&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;작업형 2유형&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주어진 E-Commerce_Shipping 데이터를 사용해서 고객이 주문한 물품의 제시간 도착여부(Reached.on.Time_Y.N)를 예측하는 분류 모델을 생성하여 결과를 제출하시오.&lt;/li&gt;
&lt;li&gt;단, 평가기준은 roc_auc_score이고, 제출 형태는 'cust_id' : id, 'reached_ontime' : value로 하며, 제출 파일 이름은 2nd_test_type2.csv로 한다.&lt;/li&gt;
&lt;li&gt;단, 학습데이터와 테스트 데이터는 각각 10000개, 999개로 나눈다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1762150441759&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/E-Commerce_Shipping.csv&quot;)
display(df.head())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&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;난이도&amp;nbsp;떡상~&lt;/p&gt;
&lt;pre id=&quot;code_1762150451518&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 10999 entries, 0 to 10998
Data columns (total 12 columns):
 #   Column               Non-Null Count  Dtype 
---  ------               --------------  ----- 
 0   ID                   10999 non-null  int64 
 1   Warehouse_block      10999 non-null  object
 2   Mode_of_Shipment     10999 non-null  object
 3   Customer_care_calls  10999 non-null  int64 
 4   Customer_rating      10999 non-null  int64 
 5   Cost_of_the_Product  10999 non-null  int64 
 6   Prior_purchases      10999 non-null  int64 
 7   Product_importance   10999 non-null  object
 8   Gender               10999 non-null  object
 9   Discount_offered     10999 non-null  int64 
 10  Weight_in_gms        10999 non-null  int64 
 11  Reached.on.Time_Y.N  10999 non-null  int64 
dtypes: int64(8), object(4)
memory usage: 1.0+ MB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&amp;nbsp;10999개로&amp;nbsp;모두&amp;nbsp;동일&amp;nbsp;한것을&amp;nbsp;확인해보니&amp;nbsp;결측값은&amp;nbsp;없는것으로&amp;nbsp;확인된다.&amp;nbsp;단&amp;nbsp;4개의&amp;nbsp;컬럼에서&amp;nbsp;Dtype에&amp;nbsp;object로&amp;nbsp;되어&amp;nbsp;있는&amp;nbsp;것으로&amp;nbsp;보아&amp;nbsp;날리던지&amp;nbsp;One-Hot-Encoding을&amp;nbsp;하던지&amp;nbsp;고민해야하는&amp;nbsp;부분이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150461767&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.isnull().sum()

ID                     0
Warehouse_block        0
Mode_of_Shipment       0
Customer_care_calls    0
Customer_rating        0
Cost_of_the_Product    0
Prior_purchases        0
Product_importance     0
Gender                 0
Discount_offered       0
Weight_in_gms          0
Reached.on.Time_Y.N    0
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;혹시라도&amp;nbsp;결측값이&amp;nbsp;있는지에&amp;nbsp;대해서&amp;nbsp;확인해보려고&amp;nbsp;`df.isnull().sum()`을&amp;nbsp;사용했으며&amp;nbsp;위&amp;nbsp;결과와&amp;nbsp;같이&amp;nbsp;결측값은&amp;nbsp;존재하지&amp;nbsp;않는다. &lt;br /&gt;&lt;br /&gt;문제에서&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;br /&gt;&lt;br /&gt;&lt;b&gt;RMSE, MSE, F2 &amp;rarr; 회귀 문제, ROC, ACC &amp;rarr; 분류 문제&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762150478582&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['Reached.on.Time_Y.N'].value_counts()

Reached.on.Time_Y.N
1    6563
0    4436
Name: count, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단&amp;nbsp;분류를&amp;nbsp;총&amp;nbsp;몇가지로&amp;nbsp;해야하는지&amp;nbsp;확인하기&amp;nbsp;위해서&amp;nbsp;`.value_counts()`를&amp;nbsp;사용하였다. &lt;br /&gt;&lt;br /&gt;분류로&amp;nbsp;도출해야하는&amp;nbsp;종류는&amp;nbsp;0&amp;nbsp;또는&amp;nbsp;1로&amp;nbsp;딱&amp;nbsp;떨어지는&amp;nbsp;분류문제이다. &lt;br /&gt;&lt;br /&gt;일단&amp;nbsp;위에서&amp;nbsp;확인했던&amp;nbsp;`object`&amp;nbsp;타입에&amp;nbsp;대해서는&amp;nbsp;라벨&amp;nbsp;인코딩을&amp;nbsp;진행해야한다.&amp;nbsp;그&amp;nbsp;이유는&amp;nbsp;다음과&amp;nbsp;같다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150491366&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;columns = ['Warehouse_block', 'Mode_of_Shipment', 'Product_importance', 'Gender']
for col in columns :
    print(df[col].value_counts())
    
Warehouse_block
F    3666
D    1834
A    1833
B    1833
C    1833
Name: count, dtype: int64
Mode_of_Shipment
Ship      7462
Flight    1777
Road      1760
Name: count, dtype: int64
Product_importance
low       5297
medium    4754
high       948
Name: count, dtype: int64
Gender
F    5545
M    5454
Name: count, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각&amp;nbsp;단순히&amp;nbsp;2&amp;nbsp;~&amp;nbsp;5개&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;pre id=&quot;code_1762150500846&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

columns = ['Warehouse_block', 'Mode_of_Shipment', 'Product_importance', 'Gender']

for col in columns :
    le.fit(df[col])
    df[col] = le.transform(df[col])

print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 10999 entries, 0 to 10998
Data columns (total 12 columns):
 #   Column               Non-Null Count  Dtype
---  ------               --------------  -----
 0   ID                   10999 non-null  int64
 1   Warehouse_block      10999 non-null  int64
 2   Mode_of_Shipment     10999 non-null  int64
 3   Customer_care_calls  10999 non-null  int64
 4   Customer_rating      10999 non-null  int64
 5   Cost_of_the_Product  10999 non-null  int64
 6   Prior_purchases      10999 non-null  int64
 7   Product_importance   10999 non-null  int64
 8   Gender               10999 non-null  int64
 9   Discount_offered     10999 non-null  int64
 10  Weight_in_gms        10999 non-null  int64
 11  Reached.on.Time_Y.N  10999 non-null  int64
dtypes: int64(12)
memory usage: 1.0 MB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`pd.get_dummies()`와&amp;nbsp;뭐가&amp;nbsp;다른지도&amp;nbsp;확인이&amp;nbsp;필요하다.&amp;nbsp;(TODO) &lt;br /&gt;&lt;br /&gt;일단&amp;nbsp;전처리가&amp;nbsp;완료&amp;nbsp;되었으면,&amp;nbsp;문제&amp;nbsp;지문과&amp;nbsp;같이&amp;nbsp;`train`과&amp;nbsp;`test`&amp;nbsp;데이터를&amp;nbsp;각각&amp;nbsp;10000,&amp;nbsp;999개로&amp;nbsp;나눈다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150514998&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;train = df.iloc[0:10000]
test = df.iloc[10000:10999]

from sklearn.model_selection import train_test_split
X = train.drop(columns = ['ID', 'Reached.on.Time_Y.N'])
y = train['Reached.on.Time_Y.N']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한&amp;nbsp;`train_test_split`을&amp;nbsp;통해서&amp;nbsp;`X_train`,&amp;nbsp;`X_test`,&amp;nbsp;`y_train`,&amp;nbsp;`y_test`를&amp;nbsp;각각&amp;nbsp;나누어&amp;nbsp;주었다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;X의&amp;nbsp;경우는&amp;nbsp;독립변수로써,&amp;nbsp;우리가&amp;nbsp;구해야하는&amp;nbsp;`Reached.on.Time_Y.N`을&amp;nbsp;뺀&amp;nbsp;모든&amp;nbsp;컬럼이다.&amp;nbsp;(ID는&amp;nbsp;학습에&amp;nbsp;도움이&amp;nbsp;되지&amp;nbsp;않으니&amp;nbsp;뺐다.) &lt;br /&gt;&lt;br /&gt;y의&amp;nbsp;경우는&amp;nbsp;종속변수로써,&amp;nbsp;우리가&amp;nbsp;구해야하는&amp;nbsp;`Reached.on.Time_Y.N`만&amp;nbsp;가지고&amp;nbsp;있는다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150523894&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(n_estimators = 170, max_depth = 30, random_state = 123)
rfc.fit(X_train, y_train)
pred = rfc.predict(X_test)

from sklearn.metrics import roc_auc_score, accuracy_score
roc = roc_auc_score(y_test, pred)
acc = accuracy_score(y_test, pred)
print(roc)
print(acc)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연하게&amp;nbsp;`RandomForest`를&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;`RandomForestClassifier`을&amp;nbsp;사용했다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;또한&amp;nbsp;문제에서는&amp;nbsp;성능평가&amp;nbsp;지표로&amp;nbsp;`roc_auc_score`를&amp;nbsp;사용하라&amp;nbsp;했기에&amp;nbsp;`roc_auc_score`도&amp;nbsp;출력하고&amp;nbsp;정확도도&amp;nbsp;궁금하기&amp;nbsp;때문에&amp;nbsp;`accuracy_score`도&amp;nbsp;`import`해서&amp;nbsp;출력해봤다. &lt;br /&gt;&lt;br /&gt;근데&amp;nbsp;지금&amp;nbsp;`n_estimators`가&amp;nbsp;170,&amp;nbsp;`max_depth`가&amp;nbsp;30으로&amp;nbsp;줬을때&amp;nbsp;`roc`와&amp;nbsp;`acc`의&amp;nbsp;값는&amp;nbsp;각각&amp;nbsp;0.680,&amp;nbsp;0.681이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150533710&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier(random_state = 123)
rfc.fit(X_train, y_train)
pred = rfc.predict(X_test)

from sklearn.metrics import roc_auc_score, accuracy_score
roc = roc_auc_score(y_test, pred)
acc = accuracy_score(y_test, pred)
print(roc)
print(acc)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랜덤포레스트에&amp;nbsp;`하이퍼파라미터`&amp;nbsp;튜닝을&amp;nbsp;하지&amp;nbsp;않고&amp;nbsp;그냥&amp;nbsp;돌렸을때의&amp;nbsp;`roc`와&amp;nbsp;`acc`의&amp;nbsp;값은&amp;nbsp;0.684,&amp;nbsp;0.683이다.&amp;nbsp;(이러면&amp;nbsp;하이퍼파라미터&amp;nbsp;튜닝을&amp;nbsp;하지&amp;nbsp;않는게&amp;nbsp;더&amp;nbsp;좋은거&amp;nbsp;아닌가?) &lt;br /&gt;&lt;br /&gt;여기서&amp;nbsp;마치는게&amp;nbsp;아니라&amp;nbsp;이게&amp;nbsp;테스트&amp;nbsp;데이터에&amp;nbsp;대해서도&amp;nbsp;예측을&amp;nbsp;진행하고&amp;nbsp;저장까지&amp;nbsp;해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150542422&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;test_data_X = test.drop(columns = ['ID', 'Reached.on.Time_Y.N'])
test_data_y = test['Reached.on.Time_Y.N']
pred2 = rfc.predict(test_data_X)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서&amp;nbsp;test데이터에서&amp;nbsp;위에서&amp;nbsp;진행했던&amp;nbsp;train_test_split&amp;nbsp;전&amp;nbsp;종속,&amp;nbsp;독립&amp;nbsp;변수를&amp;nbsp;나눈것처럼&amp;nbsp;test에서도&amp;nbsp;동일하게&amp;nbsp;ID와&amp;nbsp;Reach.on.Time_Y.N을&amp;nbsp;날려준다.&amp;nbsp;그리고&amp;nbsp;기존에&amp;nbsp;생성해준&amp;nbsp;모델을&amp;nbsp;이용해서&amp;nbsp;test_data_X를&amp;nbsp;예측한다.&amp;nbsp;이때&amp;nbsp;예측에&amp;nbsp;사용되는&amp;nbsp;독립변수는&amp;nbsp;ID,&amp;nbsp;Reach.on.Time.Y_N을&amp;nbsp;제외한&amp;nbsp;모든&amp;nbsp;데이터이다.&lt;/p&gt;
&lt;pre id=&quot;code_1762150575238&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = pd.DataFrame(
    {
        'ID' : test['ID'],
        'reached_ontime' : pred2
    }
)
result.to_csv(&quot;2nd_test_type2.csv&quot;, index = False)
print(pd.read_csv('2nd_test_type2.csv').head())

      ID  reached_ontime
0  10001               1
1  10002               0
2  10003               0
3  10004               1
4  10005               0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를&amp;nbsp;저장할때,&amp;nbsp;ID도&amp;nbsp;포함해서&amp;nbsp;CSV를&amp;nbsp;생성하라&amp;nbsp;했기&amp;nbsp;때문에&amp;nbsp;`test[&amp;rsquo;ID&amp;rsquo;]`를&amp;nbsp;그대로&amp;nbsp;가져와서&amp;nbsp;사용했다.&amp;nbsp;다른&amp;nbsp;문제에서도&amp;nbsp;몇번&amp;nbsp;보이던&amp;nbsp;패턴이었고,&amp;nbsp;대체적으로&amp;nbsp;`pred`&amp;nbsp;열로&amp;nbsp;생성하라&amp;nbsp;하는데&amp;nbsp;이&amp;nbsp;문제는&amp;nbsp;특이하게도&amp;nbsp;`reached_ontime`의&amp;nbsp;이름으로&amp;nbsp;열을&amp;nbsp;생성하라&amp;nbsp;했다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;또한&amp;nbsp;`result.csv`&amp;nbsp;가&amp;nbsp;아닌&amp;nbsp;`2nd_test_type2.csv`로&amp;nbsp;저장하는것도&amp;nbsp;조금&amp;nbsp;특이한&amp;nbsp;부분이라&amp;nbsp;생각된다. &lt;br /&gt;&lt;br /&gt;즉,&amp;nbsp;문제를&amp;nbsp;제대로&amp;nbsp;확인해야&amp;nbsp;한다는&amp;nbsp;생각이&amp;nbsp;든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 공부해야하는 것&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 이 문제를 풀면서 생각된 것은 원핫인코딩과 라벨인코딩이 뭐가 다른것인지?&lt;br /&gt;2. sklearn.preprocessing.LabelEncoder과 pandas.get_dummies가 무엇이 다른지? &lt;br /&gt;3. 문제를 제대로 읽고 회귀인지 분류인지 파악하기 &lt;br /&gt;4. RMSE, MSE, F1, ACC, ROC 를 통해서 회귀인지 분류인지 파악할수 있다. &lt;br /&gt;5. 만약 그래도 모르겠다 싶으면 종속변수를 .value_counts를 통해서 1~4개 등으로 나타나는지 아니면 각각 다 다른값인지를 확인하면 회귀인지 분류인지 확인 할 수 있다. &lt;br /&gt;6. 학습데이터로 예측만하고 그 데이터를 그대로 제출하지 말고 test 데이터에 대해서 예측하고 결과 저장하고 확인까지 하기&lt;/p&gt;</description>
      <category>Programming/빅데이터분석기사 실기</category>
      <category>빅데이터분석기사</category>
      <category>빅데이터분석기사 기출문제</category>
      <category>빅데이터분석기사 실기</category>
      <category>빅데이터분석기사 실기 기출문제</category>
      <category>빅분기</category>
      <category>빅분기 실기</category>
      <category>빅분기 실기 기출</category>
      <category>빅분기 실기 기출문제</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/589</guid>
      <comments>https://pental.tistory.com/589#entry589comment</comments>
      <pubDate>Mon, 3 Nov 2025 15:17:49 +0900</pubDate>
    </item>
    <item>
      <title>[빅데이터분석기사] 실기 대비 1일차 - 모의고사</title>
      <link>https://pental.tistory.com/588</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 글은 개인적으로 공부하려고 작성한 내용입니다.&lt;br /&gt;만일 저작권 및 다른 이유로 인해 문제가 발생할 소지가 있다면&lt;br /&gt;pental@kakao.com 으로 메일 또는 해당 게시물에 댓글을 달아주시면 처리하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;본 내용은 빅데이터분석기사-2차실기 / 장은진 교수님의 강의를 듣고 개인적으로 추가 공부가 필요한 내용에 대해서 정리한 글입니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;작업형 1유형 1번 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;문제에 대한 정의는 따로 되어 있지 않았음, 단 코드상으로 예측한 문제는 다음과 같다.해당 정보를 바탕으로 사망자가 제일 많은 도시의 사망자와, 사망자가 뒤에서 5번째로 많은 도시의 사망자의 차이를 구하시오&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1762135177331&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import pandas as pd
import numpy as np
df = pd.read_csv(&quot;./bigdata_csvfile/covid_death_bycountry.csv&quot;)
display(df.head())&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot;&gt;&lt;code&gt;print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 217 entries, 0 to 216
Data columns (total 3 columns):
 #   Column   Non-Null Count  Dtype 
---  ------   --------------  ----- 
 0   Country  217 non-null    object
 1   Deaths   217 non-null    object
 2   Cases    217 non-null    int64 
dtypes: int64(1), object(2)
memory usage: 5.2+ KB
None
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사실 데이터의 마지막 부분에는 아래와 같이 &amp;ldquo;-&amp;rdquo; 으로 되어 있는 부분이 있다.&lt;/li&gt;
&lt;li&gt;해당 부분 때문에 info의 Deaths의 타입이 object로 나타나고 있다.따라서 해당 부분을 교체하고, 정수형으로 변경하기 위해서 다음과 같이 작업한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762135159440&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import pandas as pd
import numpy as np
df = pd.read_csv(&quot;./bigdata_csvfile/covid_death_bycountry.csv&quot;)
display(df.head())&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762134349760&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['Deaths'] = df['Deaths'].str.replace('&amp;mdash;', '0')
df['Deaths'] = df['Deaths'].astype(int)
print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 217 entries, 0 to 216
Data columns (total 3 columns):
 #   Column   Non-Null Count  Dtype 
---  ------   --------------  ----- 
 0   Country  217 non-null    object
 1   Deaths   217 non-null    int64 
 2   Cases    217 non-null    int64 
dtypes: int64(2), object(1)
memory usage: 5.2+ KB
None&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그 후 사망자가 제일 많은 순으로 정렬하기 위해서 df의 기본 함수인 sort_values를 사용하였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762134359979&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = df.sort_values('Deaths', ascending = False)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또한 최소 최대의 경우 sort_values를 통해서 이미 최소, 최대가 구해졌기 때문에 iloc을 통해서 첫번째 행과, -5번째 행의 결과를 가져온다. 이때 df[&amp;rsquo;Deaths&amp;rsquo;]에서 바로 iloc를 사용하면 값만 가져와 진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1762134314049&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;max = df['Deaths'].iloc[0]
min = df['Deaths'].iloc[-5]

result = max - min
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;답 : 1110232&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; 작업형 1유형 2번 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 2000년부터 2022년까지 국내의 지역별 출생률, 사망률, 이혼률, 혼인률, 자연 성장률에 대한 데이터이다.&lt;br /&gt;2008년 7월 1일 데이터 중 출생률이 가장 높은 지역의 이름을 출력하시오.&lt;br /&gt;(단, 결측값이 포함된 경우 결측값은 해당 컬럼의 중앙값으로 대체한다.)&lt;/p&gt;
&lt;pre id=&quot;code_1762134405600&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/Korean_demographics_2000-2022.csv&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762134412601&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.info()

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 4860 entries, 0 to 4859
Data columns (total 12 columns):
 #   Column               Non-Null Count  Dtype  
---  ------               --------------  -----  
 0   Date                 4860 non-null   object 
 1   Region               4860 non-null   object 
 2   Birth                4716 non-null   float64
 3   Birth_rate           4709 non-null   float64
 4   Death                4716 non-null   float64
 5   Death_rate           4709 non-null   float64
 6   Divorce              4716 non-null   float64
 7   Divorce_rate         4709 non-null   float64
 8   Marriage             4716 non-null   float64
 9   Marriage_rate        4709 non-null   float64
 10  Natural_growth       4716 non-null   float64
 11  Natural_growth_rate  4709 non-null   float64
dtypes: float64(10), object(2)
memory usage: 455.8+ KB

print(df.isnull().sum())

Date                     0
Region                   0
Birth                  144
Birth_rate             151
Death                  144
Death_rate             151
Divorce                144
Divorce_rate           151
Marriage               144
Marriage_rate          151
Natural_growth         144
Natural_growth_rate    151
dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결측값이&amp;nbsp;상당수&amp;nbsp;존재하는&amp;nbsp;것을&amp;nbsp;확인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있으며,&amp;nbsp;먼저&amp;nbsp;Date의&amp;nbsp;데이터&amp;nbsp;타입이&amp;nbsp;object로&amp;nbsp;되어&amp;nbsp;있기&amp;nbsp;때문에&amp;nbsp;해당&amp;nbsp;값을&amp;nbsp;pandas의&amp;nbsp;기본&amp;nbsp;함수인&amp;nbsp;to_datetime&amp;nbsp;을&amp;nbsp;통해서&amp;nbsp;Date&amp;nbsp;의&amp;nbsp;데이터&amp;nbsp;타입을&amp;nbsp;변경한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134424104&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['Date'] = pd.to_datetime(df['Date'])
print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 4860 entries, 0 to 4859
Data columns (total 12 columns):
 #   Column               Non-Null Count  Dtype         
---  ------               --------------  -----         
 0   Date                 4860 non-null   datetime64[ns]
 1   Region               4860 non-null   object        
 2   Birth                4716 non-null   float64       
 3   Birth_rate           4709 non-null   float64       
 4   Death                4716 non-null   float64       
 5   Death_rate           4709 non-null   float64       
 6   Divorce              4716 non-null   float64       
 7   Divorce_rate         4709 non-null   float64       
 8   Marriage             4716 non-null   float64       
 9   Marriage_rate        4709 non-null   float64       
 10  Natural_growth       4716 non-null   float64       
 11  Natural_growth_rate  4709 non-null   float64       
dtypes: datetime64[ns](1), float64(10), object(1)
memory usage: 455.8+ KB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;birth_rate부분에&amp;nbsp;결측값이&amp;nbsp;있기&amp;nbsp;때문에,&amp;nbsp;해당&amp;nbsp;값은&amp;nbsp;그&amp;nbsp;컬럼의&amp;nbsp;중앙값으로&amp;nbsp;채우라고&amp;nbsp;했기&amp;nbsp;때문에&amp;nbsp;median()을&amp;nbsp;통해서&amp;nbsp;중앙값으로&amp;nbsp;채워준다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134432824&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['Birth_rate'].fillna(df['Birth_rate'].median(), inplace = True)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후&amp;nbsp;cond라는&amp;nbsp;변수를&amp;nbsp;생성해&amp;nbsp;df[&amp;rsquo;Date&amp;rsquo;]&amp;nbsp;==&amp;nbsp;&amp;lsquo;2008-07-01&amp;rsquo;&amp;nbsp;의&amp;nbsp;조건을&amp;nbsp;추가하고&amp;nbsp;df2에&amp;nbsp;저장했다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134442001&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cond1 = df['Date'] == '2008-07-01'
print(len(df[cond1]))
display(df[cond1].head(5))
df2 = df[cond1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;df2를&amp;nbsp;sort_values&amp;nbsp;기능을&amp;nbsp;통해서&amp;nbsp;Birth_rate를&amp;nbsp;기준으로&amp;nbsp;내림차순&amp;nbsp;정렬&amp;nbsp;후&amp;nbsp;iloc을&amp;nbsp;통해서&amp;nbsp;도시&amp;nbsp;이름을&amp;nbsp;출력한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134450832&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df2 = df2.sort_values('Birth_rate', ascending = False)
display(df2.head())
print(df2['Region'].iloc[0])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : Gyeonggi-do&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;작업형&amp;nbsp;1유형&amp;nbsp;3번&amp;nbsp;문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주어진&amp;nbsp;수면&amp;nbsp;데이터에서&amp;nbsp;수면시간(Sleep&amp;nbsp;Duration)&amp;nbsp;컬럼과&amp;nbsp;가장&amp;nbsp;높은&amp;nbsp;상관계수를&amp;nbsp;갖는&amp;nbsp;변수의&amp;nbsp;최빈값을&amp;nbsp;출력하시오. &lt;br /&gt;(단,&amp;nbsp;Blood&amp;nbsp;pressure&amp;nbsp;컬럼과&amp;nbsp;Sleep&amp;nbsp;Disorder&amp;nbsp;컬럼은&amp;nbsp;분석에서&amp;nbsp;제외한다.)&lt;/p&gt;
&lt;pre id=&quot;code_1762134483424&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/Sleep_health_and_lifestyle_dataset.csv&quot;)
df = df.drop(columns = ['Blood Pressure', 'Sleep Disorder'])

one_hot_data = pd.get_dummies(df[['Gender', 'Occupation', 'BMI Category']])
df = pd.concat([df, one_hot_data], axis = 1)
df = df.drop(columns=['Gender', 'Occupation', 'BMI Category'])
print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 374 entries, 0 to 373
Data columns (total 25 columns):
 #   Column                           Non-Null Count  Dtype  
---  ------                           --------------  -----  
 0   Person ID                        374 non-null    int64  
 1   Age                              374 non-null    int64  
 2   Sleep Duration                   374 non-null    float64
 3   Quality of Sleep                 374 non-null    int64  
 4   Physical Activity Level          374 non-null    int64  
 5   Stress Level                     374 non-null    int64  
 6   Heart Rate                       374 non-null    int64  
 7   Daily Steps                      374 non-null    int64  
 8   Gender_Female                    374 non-null    bool   
 9   Gender_Male                      374 non-null    bool   
 10  Occupation_Accountant            374 non-null    bool   
 11  Occupation_Doctor                374 non-null    bool   
 12  Occupation_Engineer              374 non-null    bool   
 13  Occupation_Lawyer                374 non-null    bool   
 14  Occupation_Manager               374 non-null    bool   
 15  Occupation_Nurse                 374 non-null    bool   
 16  Occupation_Sales Representative  374 non-null    bool   
 17  Occupation_Salesperson           374 non-null    bool   
 18  Occupation_Scientist             374 non-null    bool   
 19  Occupation_Software Engineer     374 non-null    bool   
...
 24  BMI Category_Overweight          374 non-null    bool   
dtypes: bool(17), float64(1), int64(7)
memory usage: 29.7 KB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 불필요한 열 Blood_pressure, Sleep Disorder 열을 삭제해주고, one_hot 인코딩을 진행했다.&lt;br /&gt;그 후 concat으로 원핫인코딩된 데이터와 기존 데이터프레임을 합쳐주고, 원핫인코딩 전 데이터의 열을 삭제한다.&lt;br /&gt;그&amp;nbsp;후&amp;nbsp;상관&amp;nbsp;계수를&amp;nbsp;구하기&amp;nbsp;위해서&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;작성한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134507176&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;corr = df.corr()
print(corr)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sleep&amp;nbsp;Duration&amp;nbsp;컬럼과&amp;nbsp;가장&amp;nbsp;큰&amp;nbsp;상관&amp;nbsp;관계를&amp;nbsp;가지는&amp;nbsp;컬럼은&amp;nbsp;Quality&amp;nbsp;of&amp;nbsp;Sleep&amp;nbsp;이기&amp;nbsp;때문에&amp;nbsp;해당&amp;nbsp;값의&amp;nbsp;최빈&amp;nbsp;값을&amp;nbsp;가음과&amp;nbsp;같이&amp;nbsp;출력한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134518728&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = df['Quality of Sleep'].mode()[0]
print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 8&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;작업형 2유형&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 중고차 가격 관련 데이터셋이다. 다음과 같은 주의사항을 확인하고, 결과를 제출하도록 한다. used_cars_price_data.csv 전체 데이터 목록 4009행 중 3800행을 학습용 데이터로 사용하고, 나머지를 테스트 데이터로 사용할 수 있도록 데이터를 슬라이싱한다. 학습용 데이터를 활용하여 예측 모델을 모델링 하고, 테스트 데이터를 적용하여 목표변수(price)를 예측하고, 예측 결과를 제출한다. 모델 평가지표는 RMSE로 한다. 모델 예측 결과는 price 컬럼을 갖고, 예측 결과를 나타내며, index는 표시하지 않는다. 모델 예측 결과 파일명은 다음과 같이 하여 제출한다. (파일명 : result.csv)&lt;/p&gt;
&lt;pre id=&quot;code_1762134541080&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/used_cars_price_data.csv&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전처리가&amp;nbsp;필요함.&amp;nbsp;df.isnull().sum()에서&amp;nbsp;이상치가&amp;nbsp;있는&amp;nbsp;컬럼이&amp;nbsp;3개&amp;nbsp;있었고,&amp;nbsp;그&amp;nbsp;3개의&amp;nbsp;컬럼에&amp;nbsp;대해서&amp;nbsp;결측값을&amp;nbsp;최빈&amp;nbsp;값으로&amp;nbsp;fillna&amp;nbsp;함&lt;/p&gt;
&lt;pre id=&quot;code_1762134549320&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['fuel_type'].fillna(df['fuel_type'].mode()[0], inplace = True)
df['accident'].fillna(df['accident'].mode()[0], inplace = True)
df['clean_title'].fillna(df['clean_title'].mode()[0], inplace = True)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;price 부분에서는 $ / , 와 같은 특수문자가 있기 때문에 str.replace를 이용해서 모두 변경한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134558400&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df['price'] = df['price'].str.replace(&quot;$&quot;, &quot;&quot;)
df['price'] = df['price'].str.replace(&quot;,&quot;, &quot;&quot;)
df['price'] = df['price'].astype(int)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고&amp;nbsp;info를&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;pre id=&quot;code_1762134566168&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df.info()

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 4009 entries, 0 to 4008
Data columns (total 12 columns):
 #   Column        Non-Null Count  Dtype 
---  ------        --------------  ----- 
 0   brand         4009 non-null   object
 1   model         4009 non-null   object
 2   model_year    4009 non-null   int64 
 3   milage        4009 non-null   object
 4   fuel_type     4009 non-null   object
 5   engine        4009 non-null   object
 6   transmission  4009 non-null   object
 7   ext_col       4009 non-null   object
 8   int_col       4009 non-null   object
 9   accident      4009 non-null   object
 10  clean_title   4009 non-null   object
 11  price         4009 non-null   int64 
dtypes: int64(2), object(10)
memory usage: 376.0+ KB&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지&amp;nbsp;열에&amp;nbsp;대해서는&amp;nbsp;LabelEncoder를&amp;nbsp;돌면서&amp;nbsp;라벨인코딩을&amp;nbsp;진행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134576576&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

columns = ['brand', 'model', 'milage', 'fuel_type', 'engine', 'transmission', 'ext_col', 'int_col', 'accident', 'clean_title']

for col in columns :
    le.fit(df[col])
    df[col] = le.transform(df[col])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라벨인코딩을 하고, train과 test를 나누었다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134585817&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;train = df.iloc[:3800, :]
test = df.iloc[-209:, :]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sklearn.model_selection의 train_test_split을 통해서 X_train, X_test, y_train. y_test를 나눈다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134594128&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.model_selection import train_test_split
X = train.drop(columns = 'price') # 독립변수
y = train['price'] # 종속변수

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
X_train.shape, X_test.shape, y_train.shape, y_test.shape

((3040, 11), (760, 11), (3040,), (760,))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마법의 랜덤포렌스트회귀를 통해서 차량 가격에 대해서 예측한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134603952&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.ensemble import RandomForestRegressor
rfr = RandomForestRegressor(n_estimators = 150, max_depth = 20, random_state = 123)
rfr.fit(X_train, y_train)
pred = rfr.predict(X_test)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평가지표의 경우 rmse를 통해서 구했기 때문에 root_mean_squared_error을 통해서 rmse를 계산한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134613768&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.metrics import root_mean_squared_error
rmse = root_mean_squared_error(y_test, pred)
print('rmse', rmse)

rmse 38204.54661207414&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 제출읠 경우는 test에서 price 열을 날리고, 테스트 데이터에 대해서 예측한다.&lt;/p&gt;
&lt;pre id=&quot;code_1762134622024&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;test_X_data = test.drop(columns = 'price')
pred2 = rfr.predict(test_X_data)

pd.DataFrame({'pred' : pred2}).to_csv(&quot;result.csv&quot;, index = False)
print(pd.read_csv(&quot;result.csv&quot;).head())&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;작업형 3유형 1번 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공되는&amp;nbsp;심혈관&amp;nbsp;질환&amp;nbsp;데이터를&amp;nbsp;활용하여&amp;nbsp;심혈관&amp;nbsp;질환&amp;nbsp;발생&amp;nbsp;여부(cardio)를&amp;nbsp;예측하고자한다. &lt;br /&gt;각문항의&amp;nbsp;답을&amp;nbsp;제출형식에&amp;nbsp;맞게&amp;nbsp;제출하시오 &lt;br /&gt;data&amp;nbsp;=&amp;nbsp;cardiovascular_heart_disease_data.csv &lt;br /&gt;&lt;br /&gt;1.&amp;nbsp;alco,&amp;nbsp;cardio&amp;nbsp;변수&amp;nbsp;간의&amp;nbsp;독립성&amp;nbsp;검정을&amp;nbsp;실시할&amp;nbsp;때,&amp;nbsp;카이제곱&amp;nbsp;통계량을&amp;nbsp;구하시오. &lt;br /&gt;2.&amp;nbsp;gender,&amp;nbsp;weight,&amp;nbsp;smoke,&amp;nbsp;cholesterol을&amp;nbsp;독립변수로&amp;nbsp;사용하여&amp;nbsp;로지스틱&amp;nbsp;회귀모형으로&amp;nbsp;분석할&amp;nbsp;때,&amp;nbsp;smoke&amp;nbsp;변수의&amp;nbsp;계수&amp;nbsp;값을&amp;nbsp;구하시오 &lt;br /&gt;3.&amp;nbsp;2번&amp;nbsp;문제에서&amp;nbsp;생성한&amp;nbsp;로지스틱&amp;nbsp;회귀모형에서&amp;nbsp;gender&amp;nbsp;변수가&amp;nbsp;한&amp;nbsp;단위&amp;nbsp;증가할&amp;nbsp;때&amp;nbsp;심혈관&amp;nbsp;질환이&amp;nbsp;발생할&amp;nbsp;오즈비의&amp;nbsp;값을&amp;nbsp;구하시오, &lt;br /&gt;(단,&amp;nbsp;모든&amp;nbsp;문제의&amp;nbsp;정답은&amp;nbsp;반올림하여&amp;nbsp;소수점&amp;nbsp;네&amp;nbsp;자리까지&amp;nbsp;출력한다)&lt;/p&gt;
&lt;pre id=&quot;code_1762134678016&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/cardiovascular_heart_disease_data.csv&quot;)
display(df)
print(df.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 70000 entries, 0 to 69999
Data columns (total 14 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   index        70000 non-null  int64  
 1   id           70000 non-null  int64  
 2   age          70000 non-null  int64  
 3   gender       70000 non-null  int64  
 4   height       70000 non-null  int64  
 5   weight       70000 non-null  float64
 6   ap_hi        70000 non-null  int64  
 7   ap_lo        70000 non-null  int64  
 8   cholesterol  70000 non-null  int64  
 9   gluc         70000 non-null  int64  
 10  smoke        70000 non-null  int64  
 11  alco         70000 non-null  int64  
 12  active       70000 non-null  int64  
 13  cardio       70000 non-null  int64  
dtypes: float64(1), int64(13)
memory usage: 7.5 MB
None&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;alco,&amp;nbsp;cardio&amp;nbsp;변수&amp;nbsp;간의&amp;nbsp;독립성&amp;nbsp;검정을&amp;nbsp;실시할&amp;nbsp;때,&amp;nbsp;카이제곱&amp;nbsp;통계량을&amp;nbsp;구하시오. &lt;br /&gt;&amp;nbsp;카이제곱이 나온다? &amp;rarr; 무조건 scipy.stats의 chi2_contingency 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1762134697392&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from scipy.stats import chi2_contingency
data = pd.crosstab(df.alco, df.cardio)
print(data)

cardio      0      1
alco                
0       33080  33156
1        1941   1823&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카이 제곱 통계량 수행하기&lt;/p&gt;
&lt;pre id=&quot;code_1762134706792&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chi2, p_value, dof, exp = chi2_contingency(data)
print(round(chi2, 4))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 3.6965&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;gender, weight, smoke, cholesterol을 독립변수로 사용하여 로지스틱 회귀모형으로 분석할 때, smoke 변수의 계수 값을 구하시오&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 있으면 일단 로지스틱 회귀모형으로 분석하는거고 여기선 from statsmodels.formula.api import logit 사용하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 회귀식 작성할때, ~, + 잘 확인하기, 즉 여기서는 cardio를 0 또는 1로 분석하는데, cardio가 **종속변수** 그 외 &lt;b&gt;gender, weight, smoke, cholesterol&lt;/b&gt;을 독립변수로 사용하기에 + 붙여서 식 세우기&lt;/p&gt;
&lt;pre id=&quot;code_1762134751016&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from statsmodels.formula.api import logit
result = logit('cardio ~ gender + weight + smoke + cholesterol', data = df).fit().params

Optimization terminated successfully.
         Current function value: 0.654936
         Iterations 5
         
print(round(result.smoke, 4))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : -0.2174&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번 문제에서 생성한 로지스틱 회귀모형에서 gender 변수가 한 단위 증가할 때 심혈관 질환이 발생할 오즈비의 값을 구하시오,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우 np.exp 사용하기 &amp;rarr; np.exp(result)&lt;/p&gt;
&lt;pre id=&quot;code_1762134773760&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;answer = np.exp(result)
print(round(answer.gender, 4))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답 : 1.0002&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 3번 문제는 잘 이해가 안됨, 조금더 추가 공부 필요&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;작업형 3유형 2번 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제공되는 심장 질환 데이터를 활용하여 심장질환 발생 여부(target)를 예측하고자 한다. 각 문항의 답을 제출형식에 맞게 제출하시오. data = pd.read_csv(&quot;heart_disease_data.csv&quot;)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;독립변수를 exang, trestbps, ca로 하고, 목표변수를 target으로 하는 로지스틱 회귀분석을 진행했을 때, ca변수의 표준오차를 구하시오.&lt;/li&gt;
&lt;li&gt;fbs, thalach, chol, sex를 독립변수로 target을 분류하는 로지스틱 회귀분석 모형을 생성했을때, 학습(train) 데이터의 오분류율을 구하시오. (단, 전체 데이터 중 800행을 학습(train) 데이터로 사용하고, train_test_split의 test_size는 0.2로 하며, random_state는 123으로 한다.)&lt;/li&gt;
&lt;li&gt;2번 문제 모델의 심장질환 발생(1)에 대한 정밀도를 구하시오. (단, 모든 문제의 정답은 반올림하여 소수점 두 번째 자리까지 출력한다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;독립변수를 exang, trestbps, ca로 하고, 목표변수를 target으로 하는 로지스틱 회귀분석을 진행했을 때, ca변수의 표준오차를 구하시오.&lt;/p&gt;
&lt;pre id=&quot;code_1762134833536&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;df = pd.read_csv(&quot;./bigdata_csvfile/heart_disease_data.csv&quot;)
print(df.info())
display(df.head())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 1025 entries, 0 to 1024
Data columns (total 14 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       1025 non-null   int64  
 1   sex       1025 non-null   int64  
 2   cp        1025 non-null   int64  
 3   trestbps  1025 non-null   int64  
 4   chol      1025 non-null   int64  
 5   fbs       1025 non-null   int64  
 6   restecg   1025 non-null   int64  
 7   thalach   1025 non-null   int64  
 8   exang     1025 non-null   int64  
 9   oldpeak   1025 non-null   float64
 10  slope     1025 non-null   int64  
 11  ca        1025 non-null   int64  
 12  thal      1025 non-null   int64  
 13  target    1025 non-null   int64  
dtypes: float64(1), int64(13)
memory usage: 112.2 KB
None&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에서 독립변수를 ~~ 로 하고, 목표변수를 target으로 하는~~ 이런식으로 나왔기 때문에 얘도 동일하게 식 작성해야함&lt;/p&gt;
&lt;pre id=&quot;code_1762134847456&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from statsmodels.formula.api import logit
result = logit('target ~ exang + trestbps + ca', data = df).fit().summary()
print(result)

Optimization terminated successfully.
         Current function value: 0.516009
         Iterations 6
                           Logit Regression Results                           
==============================================================================
Dep. Variable:                 target   No. Observations:                 1025
Model:                          Logit   Df Residuals:                     1021
Method:                           MLE   Df Model:                            3
Date:                Thu, 30 Oct 2025   Pseudo R-squ.:                  0.2552
Time:                        09:48:21   Log-Likelihood:                -528.91
converged:                       True   LL-Null:                       -710.12
Covariance Type:            nonrobust   LLR p-value:                 3.046e-78
==============================================================================
                 coef    std err          z      P&amp;gt;|z|      [0.025      0.975]
------------------------------------------------------------------------------
Intercept      3.1733      0.598      5.305      0.000       2.001       4.346
exang         -2.1073      0.167    -12.629      0.000      -2.434      -1.780
trestbps      -0.0138      0.004     -3.095      0.002      -0.023      -0.005
ca            -0.8756      0.083    -10.574      0.000      -1.038      -0.713
==============================================================================&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답 : 0.083 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. fbs, thalach, chol, sex를 독립변수로 target을 분류하는 로지스틱 회귀분석 모형을 생성했을때, 학습(train) 데이터의 오분류율을 구하시오. (단, 전체 데이터 중 800행을 학습(train) 데이터로 사용하고, train_test_split의 test_size는 0.2로 하며, random_state는 123으로 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 갑자기 훈련 시키는거지? 문제가 원래 이렇게 나오나??&lt;/p&gt;
&lt;pre id=&quot;code_1762134873928&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Q2
train = df.iloc[:800, :]
test = df.iloc[-225:, :]
print(train.info())
print(test.info())

&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 800 entries, 0 to 799
Data columns (total 14 columns):
 #   Column    Non-Null Count  Dtype  
---  ------    --------------  -----  
 0   age       800 non-null    int64  
 1   sex       800 non-null    int64  
 2   cp        800 non-null    int64  
 3   trestbps  800 non-null    int64  
 4   chol      800 non-null    int64  
 5   fbs       800 non-null    int64  
 6   restecg   800 non-null    int64  
 7   thalach   800 non-null    int64  
 8   exang     800 non-null    int64  
 9   oldpeak   800 non-null    float64
 10  slope     800 non-null    int64  
 11  ca        800 non-null    int64  
 12  thal      800 non-null    int64  
 13  target    800 non-null    int64  
dtypes: float64(1), int64(13)
memory usage: 87.6 KB
None
&amp;lt;class 'pandas.core.frame.DataFrame'&amp;gt;
RangeIndex: 225 entries, 800 to 1024
Data columns (total 14 columns):
...
 13  target    225 non-null    int64  
dtypes: float64(1), int64(13)
memory usage: 24.7 KB
None&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762134880434&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, classification_report, roc_auc_score

X = train[['fbs', 'thalach', 'chol', 'sex']]
y = train['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 123)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)

(640, 4) (160, 4) (640,) (160,)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762134889840&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;lr = LogisticRegression()
lr.fit(X_train, y_train)
pred = lr.predict(X_test)

confussion = confusion_matrix(y_test, pred)
print(confussion)

roc = roc_auc_score(y_test, pred)
print(roc)

[[59 19]
 [28 54]]
0.7074734208880551&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1762134896256&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(round(1 - roc, 2))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 답 : 0.29&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 2번 문제 모델의 심장질환 발생(1)에 대한 정밀도를 구하시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정밀도의 경우 classification_report를 통해서 확인해야함.&lt;/p&gt;
&lt;pre id=&quot;code_1762134917488&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Q3 
cla_re = classification_report(y_test, pred)
print(cla_re)

              precision    recall  f1-score   support

           0       0.68      0.76      0.72        78
           1       0.74      0.66      0.70        82

    accuracy                           0.71       160
   macro avg       0.71      0.71      0.71       160
weighted avg       0.71      0.71      0.71       160&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답 : 0.74&lt;/b&gt;&lt;/p&gt;</description>
      <category>Programming/빅데이터분석기사 실기</category>
      <category>빅데이터분석기사</category>
      <category>빅데이터분석기사 실기</category>
      <category>빅데이터분석기사 실기 기출</category>
      <category>빅데이터분석기사 실기 대비</category>
      <category>빅분기</category>
      <category>빅분기 실기</category>
      <category>빅분기 실기 기출</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/588</guid>
      <comments>https://pental.tistory.com/588#entry588comment</comments>
      <pubDate>Mon, 3 Nov 2025 10:58:15 +0900</pubDate>
    </item>
    <item>
      <title>[포렌식] 카카오톡 수정된 메시지 및 삭제된 메시지 분석 및 복구 (25.10.07)</title>
      <link>https://pental.tistory.com/587</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;지금&amp;nbsp;보낸&amp;nbsp;그&amp;nbsp;메시지,&amp;nbsp;&amp;lsquo;수정&amp;rsquo;&amp;nbsp;버튼&amp;nbsp;한&amp;nbsp;번이면&amp;nbsp;싹&amp;nbsp;바뀔&amp;nbsp;수&amp;nbsp;있다.&amp;rdquo;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;최근 카카오톡의 대대적 업데이트 이후, 메시지 수정 기능이 새롭게 도입되면서 많은 이용자들이 기대와 우려 사이에 놓여 있다. 특히 이 기능이 &amp;ldquo;말 바꾸기&amp;rdquo; 또는 &amp;ldquo;증거 삭제&amp;rdquo;의 수단으로 악용될 가능성도 제기되며, 카카오톡이 가진 커뮤니케이션의 신뢰성에도 균열이 생길지 모른다는 목소리가 커지고 있다.&lt;br /&gt;&lt;br /&gt;실제로 일부 이용자들은 &amp;ldquo;그럼 앞으로 카톡을 증거로 사용할 수 없겠네&amp;hellip; 신뢰성 떨어진다&amp;rdquo; 라는 반응을 보이기도 했는데 이처럼 메시지 수정 기능은 단순한 편의성의 연장선이 아니라, 커뮤니케이션의 본질과 책임의 경계를 다시 묻게 만드는 변화다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 글에서는 카카오톡 업데이트의 핵심 변화와 더불어, 메시지 수정 기능이 초래할 수 있는 문제점들을 짚어보고자 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 최근 추가된 수정 기능에 대해서 시나리오를 하나 세워보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqIOml/btsQ3leQjrS/v1KXCZkgROKDNz1duLMnX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqIOml/btsQ3leQjrS/v1KXCZkgROKDNz1duLMnX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqIOml/btsQ3leQjrS/v1KXCZkgROKDNz1duLMnX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqIOml%2FbtsQ3leQjrS%2Fv1KXCZkgROKDNz1duLMnX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;411&quot; height=&quot;343&quot; data-origin-width=&quot;411&quot; data-origin-height=&quot;343&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 A가 상대방(이하 B라고 칭한다)에게 &lt;b&gt;&quot;나 10만원만 한국은행 1234-5678-90 으로 보내주라&quot;&lt;/b&gt; 라고 보낸 메시지이다. 이부분에서는 정상적으로 10만원을 빌려달라는 메시지가 정상적으로 보이게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;B는 A가 10만원을 보내달라는 메시지를 받고, 그 즉시 10만원을 송금한 것으로 확인된다. 하지만 이제 A가 이 문자 메시지를 변경하는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lEyPa/btsQ2bYbJhc/j9duDNyIPbz6T9kgW1l4SK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lEyPa/btsQ2bYbJhc/j9duDNyIPbz6T9kgW1l4SK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lEyPa/btsQ2bYbJhc/j9duDNyIPbz6T9kgW1l4SK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlEyPa%2FbtsQ2bYbJhc%2Fj9duDNyIPbz6T9kgW1l4SK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;416&quot; height=&quot;460&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;물론 &lt;b&gt;&quot;수정됨&quot;&lt;/b&gt; 이라는 문구와 함께, 메시지의 내용이 10만원에서 1만원으로 변경된 것을 확인 할 수 있으며, 이 부분에 대해서는 큰 문제가 발생할 수 있는 소지가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;문제는 단순히 &lt;b&gt;10만원 &amp;rarr; 1만원&lt;/b&gt;이 아니다. 만약 과거에 &lt;b&gt;&amp;ldquo;500만원을 빌려달라&amp;rdquo;&lt;/b&gt;는 메시지가 있었는데, 이후 &lt;b&gt;&amp;ldquo;50만원&amp;rdquo;&lt;/b&gt;으로 변경된다면 어떨까?&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 금전거래 증거로 제출된 메시지가 법적 분쟁 상황에서 효력을 상실할 수 있다. 또한, &lt;b&gt;&amp;ldquo;수정됨&amp;rdquo;&lt;/b&gt;이라는 표식이 있더라도 원문 내용이 확인되지 않는 이상, 상대방에게 불리하게 작용할 수 있다. 결과적으로 카카오톡 대화의 &lt;span&gt;&lt;b&gt;증거 신뢰성&lt;/b&gt;&lt;/span&gt;이 흔들리며, 분쟁 상황에서 악용될 소지가 커진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;나는 이 부분에 초점을 두고 분석을 진행하였다. 분석은 iOS 환경을 이용하여 진행하였으며, 아래는 분석에 관한 내용이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;분석 환경의 경우 Mac + Python 3.13.7 버전을 사용하였으며 B의 휴대전화를 사용하여 분석을 진행한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqplfL/btsQ2QlVf7d/frHrYzAe6GBw2nDQYeQkVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqplfL/btsQ2QlVf7d/frHrYzAe6GBw2nDQYeQkVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqplfL/btsQ2QlVf7d/frHrYzAe6GBw2nDQYeQkVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqplfL%2FbtsQ2QlVf7d%2FfrHrYzAe6GBw2nDQYeQkVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;407&quot; height=&quot;232&quot; data-origin-width=&quot;407&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;B의 카카오톡 버전은 25.8.4를 사용하고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 아이폰 논리백업을 통해서 카카오톡 채팅 데이터베이스를 추출하였다. 기존 포스팅에서 언급한것 처럼 아래 논문을 사용하여, 복호화 작업을 진행하였다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://pental.tistory.com/538&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://pental.tistory.com/538&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1759766394207&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[포렌식] 아이폰 카카오톡 복호화 분석 및 구현&quot; data-og-description=&quot;본 글은 언제든지 비공개 되거나, 삭제될수 있음을 미리 알려드립니다. (뭐,, 카카오톡 본사에서 글 내려라 하지 않는 이상 없어지진 않지 않을까...?)모바일 메신저는 디지털 포렌식에서 핵심적&quot; data-og-host=&quot;blog.system32.kr&quot; data-og-source-url=&quot;https://pental.tistory.com/538&quot; data-og-url=&quot;https://blog.system32.kr/538&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dntdoC/hyZKyQHpIV/C4CP3AdUCAMTX3SjCjuHq1/img.png?width=800&amp;amp;height=437&amp;amp;face=0_0_800_437,https://scrap.kakaocdn.net/dn/batCyF/hyZKSfHs5z/RMvy7ZPaZZDzeeWkTtkt1K/img.png?width=800&amp;amp;height=437&amp;amp;face=0_0_800_437,https://scrap.kakaocdn.net/dn/bYSKXJ/hyZKdSQm2N/9Aw0C4gC7JXcjdcOU0uBw1/img.png?width=1792&amp;amp;height=1080&amp;amp;face=0_0_1792_1080&quot;&gt;&lt;a href=&quot;https://pental.tistory.com/538&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://pental.tistory.com/538&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dntdoC/hyZKyQHpIV/C4CP3AdUCAMTX3SjCjuHq1/img.png?width=800&amp;amp;height=437&amp;amp;face=0_0_800_437,https://scrap.kakaocdn.net/dn/batCyF/hyZKSfHs5z/RMvy7ZPaZZDzeeWkTtkt1K/img.png?width=800&amp;amp;height=437&amp;amp;face=0_0_800_437,https://scrap.kakaocdn.net/dn/bYSKXJ/hyZKdSQm2N/9Aw0C4gC7JXcjdcOU0uBw1/img.png?width=1792&amp;amp;height=1080&amp;amp;face=0_0_1792_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[포렌식] 아이폰 카카오톡 복호화 분석 및 구현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;본 글은 언제든지 비공개 되거나, 삭제될수 있음을 미리 알려드립니다. (뭐,, 카카오톡 본사에서 글 내려라 하지 않는 이상 없어지진 않지 않을까...?)모바일 메신저는 디지털 포렌식에서 핵심적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.system32.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;논리&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;br /&gt;&lt;br /&gt;이번&amp;nbsp;분석에서는&amp;nbsp;Message.sqlite&amp;nbsp;파일의&amp;nbsp;message&amp;nbsp;테이블을&amp;nbsp;활용하여,&amp;nbsp;userid와&amp;nbsp;message&amp;nbsp;컬럼을&amp;nbsp;기준으로&amp;nbsp;단순&amp;nbsp;메시지&amp;nbsp;복호화를&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;606&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8xMEx/btsQ48yBRet/BDaRmFPJkKuQQ2KqnGmceK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8xMEx/btsQ48yBRet/BDaRmFPJkKuQQ2KqnGmceK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8xMEx/btsQ48yBRet/BDaRmFPJkKuQQ2KqnGmceK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8xMEx%2FbtsQ48yBRet%2FBDaRmFPJkKuQQ2KqnGmceK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;88&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 가장 크게 눈에 띄는 부분은 &lt;b&gt;&quot;나 10만원만 한국은행 1234-5678-90으로 보내주라&quot;&lt;/b&gt;라고 A가 B에게 보냈지만, 실질적으로 B의 휴대전화에서 남는 기록은 &lt;b&gt;&quot;나 1만원만 한국은행 1234-5678-90으로 보내주라&quot;&lt;/b&gt; 라고 수정된 메시지만 남게된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 수정 이후에는 &lt;span&gt;&lt;b&gt;변경된 메시지 내용만&lt;/b&gt;&lt;/span&gt; 보이게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이때 데이터베이스에는 다음과 같은 로그가 남는다.&lt;/p&gt;
&lt;pre id=&quot;code_1759767433799&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{&quot;logId&quot;:3681151639662792706,&quot;targetRevision&quot;:1,&quot;hidden&quot;:true,&quot;feedType&quot;:25}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 &lt;span&gt;targetRevision: 1&lt;/span&gt; 은 메시지가 수정되었음을 의미한다. 그리고 &lt;span&gt;logId&lt;/span&gt;는 &lt;span&gt;&lt;b&gt;직전 메시지를 가리키는 지표&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;1432&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvQ7FG/btsQ4VTLkx8/ToK4n8MPHiFxdVASybkmtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvQ7FG/btsQ4VTLkx8/ToK4n8MPHiFxdVASybkmtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvQ7FG/btsQ4VTLkx8/ToK4n8MPHiFxdVASybkmtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvQ7FG%2FbtsQ4VTLkx8%2FToK4n8MPHiFxdVASybkmtk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1432&quot; height=&quot;551&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;직전의 메시지를 나타내는 지표이다. 사용한 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1759767068048&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conn = sqlite3.connect(&quot;after&quot;)
cursor = conn.cursor()
cursor.execute(&quot;SELECT prevId, userid, message FROM message WHERE prevId = 3681151639662792706&quot;)
row = cursor.fetchall()
print(decrypt(row[0][1], row[0][2]))&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;896&quot; data-origin-height=&quot;34&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/11WXD/btsQ3BIu74k/wl9ZT66rLWgx8Ww0tBPyqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/11WXD/btsQ3BIu74k/wl9ZT66rLWgx8Ww0tBPyqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/11WXD/btsQ3BIu74k/wl9ZT66rLWgx8Ww0tBPyqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F11WXD%2FbtsQ3BIu74k%2Fwl9ZT66rLWgx8Ww0tBPyqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;896&quot; height=&quot;34&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;34&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 수정된 메시지는 원래 내용을 확인할수 없는것인가? 답은 원본 메시지도 확인 할 수 있다는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;카카오톡에서는 위에서 언급한 가상의 시나리오 처럼 &lt;b&gt;&quot;수정&quot;&lt;/b&gt; 기능을 악용하는 소지를 방지하기 위해 &lt;b&gt;extrainfo&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;935&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqaaPl/btsQ1YxZGS5/Za0G3YmfZ9c7Aj5ORWOuX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqaaPl/btsQ1YxZGS5/Za0G3YmfZ9c7Aj5ORWOuX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqaaPl/btsQ1YxZGS5/Za0G3YmfZ9c7Aj5ORWOuX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqaaPl%2FbtsQ1YxZGS5%2FZa0G3YmfZ9c7Aj5ORWOuX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;935&quot; height=&quot;206&quot; data-origin-width=&quot;935&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1759767157168&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;scrapURL&quot;: &quot;N/A&quot;,
  &quot;cv&quot;: &quot;1.0&quot;,
  &quot;modifyHistory&quot;: [
    {
      &quot;revision&quot;: 0,
      &quot;message&quot;: &quot;PsdqQvX+keRqNW0vIIklOi6/CUsKnpXQRmri78qnRBHiWM9pViqc/PJAWOKxDfZ2\r\n/PSZ5aM/bTTY/AX+Lb/h/A==&quot;,
      &quot;encrypted&quot;: true
    }
  ],
  &quot;revision&quot;: 1
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위 내용에서 먼저 눈에 띄는것은 다른 메시지와는 다르게 revision값이 1로 변경되어 있다는 점이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다른 평범한 메시지의 경우 다음과 같은 extraInfo를 가지고 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1759767252601&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{&quot;cv&quot;:&quot;1.0&quot;,&quot;revision&quot;:0,&quot;scrapURL&quot;:&quot;N\/A&quot;}
{&quot;scrapURL&quot;:&quot;N\/A&quot;,&quot;cv&quot;:&quot;1.0&quot;}
{&quot;scrapURL&quot;:&quot;N\/A&quot;,&quot;revision&quot;:0,&quot;cv&quot;:&quot;1.0&quot;,&quot;byHost&quot;:false}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위 modifyHistory 부분에서는 revision 키를 인덱스로 사용하여, 수정이 여러번 되어도 그 내용을 기록하는 형태를 가지고 있다. message 키에서는&amp;nbsp; \, \r, \r 등의 개행 문자 등은 처리하고 userid를 사용하여 복호화 하면 기존의 메시지를 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1759767331797&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;print(decrypt(123456789, &quot;PsdqQvX+keRqNW0vIIklOi6/CUsKnpXQRmri78qnRBHiWM9pViqc/PJAWOKxDfZ2/PSZ5aM/bTTY/AX+Lb/h/A==&quot;))&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위에서 사용한 123456789는 가상의 userId이며, 실제 복호화에는 실제 userId를 사용해야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;37&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmvl9C/btsQ3fZ3Ytg/zMKllQnaG2lYkQRXDUhPWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmvl9C/btsQ3fZ3Ytg/zMKllQnaG2lYkQRXDUhPWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmvl9C/btsQ3fZ3Ytg/zMKllQnaG2lYkQRXDUhPWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdmvl9C%2FbtsQ3fZ3Ytg%2FzMKllQnaG2lYkQRXDUhPWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;902&quot; height=&quot;37&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;37&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그 결과 원본 메시지에서는 &quot;나 10만원만 한국은행 1234-5678-90 으로 보내주라&quot; 라는 메시지를 확인 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 카카오톡은 단순히 메시지를 덮어쓰는 방식이 아니라, &lt;span&gt;extraInfo&lt;/span&gt;에 &lt;span&gt;&lt;b&gt;수정 이력(History)을 함께 저장&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;409&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rMwZy/btsQ2U9zJ2V/Bo8MXHgMRxIfdAsM2jihO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rMwZy/btsQ2U9zJ2V/Bo8MXHgMRxIfdAsM2jihO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rMwZy/btsQ2U9zJ2V/Bo8MXHgMRxIfdAsM2jihO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrMwZy%2FbtsQ2U9zJ2V%2FBo8MXHgMRxIfdAsM2jihO0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;409&quot; height=&quot;415&quot; data-origin-width=&quot;409&quot; data-origin-height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;결론적으로,&amp;nbsp;위의&amp;nbsp;예시와&amp;nbsp;같이&amp;nbsp;메시지가&amp;nbsp;&amp;ldquo;수정&amp;rdquo;된&amp;nbsp;경우에도&amp;nbsp;B가&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;가능하다는&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;br /&gt;&lt;br /&gt;다만&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;증거&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&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;400&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sTtBA/btsQ38F1RCG/ktQHm4mBZGNOQwGpf4bj3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sTtBA/btsQ38F1RCG/ktQHm4mBZGNOQwGpf4bj3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sTtBA/btsQ38F1RCG/ktQHm4mBZGNOQwGpf4bj3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsTtBA%2FbtsQ38F1RCG%2FktQHm4mBZGNOQwGpf4bj3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;209&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진은 삭제하기 전 사진이다. (정상적으로 메시지가 존재하며, 일반 메시지처럼 복호화 가능하다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SIVV0/btsQ3dBa1WL/1sCnzUlyftWjPwfhK19y31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SIVV0/btsQ3dBa1WL/1sCnzUlyftWjPwfhK19y31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SIVV0/btsQ3dBa1WL/1sCnzUlyftWjPwfhK19y31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSIVV0%2FbtsQ3dBa1WL%2F1sCnzUlyftWjPwfhK19y31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;360&quot; height=&quot;237&quot; data-origin-width=&quot;360&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;ldquo;메시지가 삭제되었습니다.&amp;rdquo;라는 문구로 표시된다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이 메시지들은 데이터베이스에서 어떻게 처리되는지 확인해보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wEWGK/btsQ3Gpt6yY/9YYh5UhrzLnvA0rUOdbQv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wEWGK/btsQ3Gpt6yY/9YYh5UhrzLnvA0rUOdbQv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wEWGK/btsQ3Gpt6yY/9YYh5UhrzLnvA0rUOdbQv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwEWGK%2FbtsQ3Gpt6yY%2F9YYh5UhrzLnvA0rUOdbQv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1144&quot; height=&quot;159&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 언급한 포스팅 내에 있는 논문에서도 언급 됐듯, &lt;b&gt;type 칼럼이 16385&lt;/b&gt;로 변경되며, message원본값은 변경되지 않은 상태이다. 즉, type 16835인 경우 프론트단에서 &lt;b&gt;&quot;메시지가 삭제되었습니다.&quot;&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;728&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RnJiI/btsQ2QzqB9C/24LN60wQ0QG2lqZ59sIke0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RnJiI/btsQ2QzqB9C/24LN60wQ0QG2lqZ59sIke0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RnJiI/btsQ2QzqB9C/24LN60wQ0QG2lqZ59sIke0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRnJiI%2FbtsQ2QzqB9C%2F24LN60wQ0QG2lqZ59sIke0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;728&quot; height=&quot;594&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진과 같이 삭제된 메시지는 모두 보이게 되며, 단 로그로 &lt;b&gt;&quot;hidden&quot;:true&lt;/b&gt;가 추가된다. (삭제한 시점을 기반으로) 이 경우 type은 0이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1105&quot; data-origin-height=&quot;165&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc8EXc/btsQ3Dl0Tx8/MMKQkO9pooLKAkw1i4oLP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc8EXc/btsQ3Dl0Tx8/MMKQkO9pooLKAkw1i4oLP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc8EXc/btsQ3Dl0Tx8/MMKQkO9pooLKAkw1i4oLP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc8EXc%2FbtsQ3Dl0Tx8%2FMMKQkO9pooLKAkw1i4oLP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1105&quot; height=&quot;165&quot; data-origin-width=&quot;1105&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;위에서 따로 언급은 하지 않았지만, type 26의 경우 &lt;b&gt;&quot;답장&quot;&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;1088&quot; data-origin-height=&quot;83&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkTJ2a/btsQ2dPf5nY/NvVnZ0AXxn5KtHm0IDPpE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkTJ2a/btsQ2dPf5nY/NvVnZ0AXxn5KtHm0IDPpE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkTJ2a/btsQ2dPf5nY/NvVnZ0AXxn5KtHm0IDPpE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkTJ2a%2FbtsQ2dPf5nY%2FNvVnZ0AXxn5KtHm0IDPpE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1088&quot; height=&quot;83&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;83&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1759768215850&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conn = sqlite3.connect(&quot;after&quot;)
cursor = conn.cursor()
cursor.execute(&quot;SELECT * FROM message WHERE message = 'jXYeIo8wBkxZ7eGCRG3LmoAhjWDBg2qETWRHkyFJ4Pk='&quot;)
rows = cursor.fetchall()
print(rows)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1759768232048&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pental@pentalui-MacBookAir kakaotalk-decryption % /opt/homebrew/bin/python3 /Users/pental/Desktop/kakaotalk-decryption/test.py
[(16, 0, None, 1, None, '', 3681152882208575489, None, None, None, 781457625, None, '{&quot;revision&quot;:0,&quot;cv&quot;:&quot;1.0&quot;}', 1759764825.827979, 3681152932582166529, 26, 1759762522, 781457625.824429, 'jXYeIo8wBkxZ7eGCRG3LmoAhjWDBg2qETWRHkyFJ4Pk=', None, 0, 384935297767633, None, None, None, None, None, 'L/+N0joqNZxbQulWgmdTGexNYOwlzWfQPTVUr6dtj8q9WmWHBGlMu8+H6MvVZeea\r\nISS/cr6EsPq481909nqa8NvEmuukEGVmPjnhQ28uN+JiRwn+JuurTvWRhEoj7FVi\r\n5FqlQZI8CTSJ27BwcMjPm1+x+fTxiD8ewK0ZYzHHpE08P7g1an2RCJ5bqo2VMbvE\r\nxvHiLYYoUqpcacPcFX9K5g==', 0, 123456789, 1, None)]&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;405&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uAJjS/btsQ3IU66sx/XFDGEthrYwh3A8t4SlNCkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uAJjS/btsQ3IU66sx/XFDGEthrYwh3A8t4SlNCkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uAJjS/btsQ3IU66sx/XFDGEthrYwh3A8t4SlNCkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuAJjS%2FbtsQ3IU66sx%2FXFDGEthrYwh3A8t4SlNCkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;405&quot; height=&quot;195&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 &lt;span&gt;message&lt;/span&gt; 테이블에서 확인한 주요 변화는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. type 값 변경&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삭제된 메시지는 type 값이 16385로 바뀌며,&lt;/li&gt;
&lt;li&gt;메시지 원본 값은 그대로 남아 있다.&lt;/li&gt;
&lt;li&gt;즉, type = 16835인 경우 프론트단(클라이언트)에서만&lt;/li&gt;
&lt;li&gt;&amp;ldquo;메시지가 삭제되었습니다.&amp;rdquo; 라는 문구를 표시한다고 추측할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. hidden 플래그&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삭제된 메시지는 log에 &quot;hidden&quot;: true 값이 추가된다.&lt;/li&gt;
&lt;li&gt;이 플래그는 삭제 시점을 기준으로 표시 여부를 제어하는 역할을 하는 것으로 보인다.&lt;/li&gt;
&lt;li&gt;이 경우 type 값은 0으로 기록된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 기타 type 값&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;type = 26 은 &amp;ldquo;답장(reply)&amp;rdquo; 기능을 나타낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이번 분석을 통해 확인할 수 있었던 사실은 크게 두 가지다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 메시지 수정 기능&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;겉으로는 &amp;ldquo;수정됨&amp;rdquo;이라는 표시와 함께 변경된 내용만 보이지만,&lt;/li&gt;
&lt;li&gt;내부적으로는 &lt;span&gt;extraInfo&lt;/span&gt; 컬럼과 &lt;span&gt;modifyHistory&lt;/span&gt;를 통해 원본 메시지가 그대로 저장되고 있어 &lt;span&gt;&lt;b&gt;복구가 가능&lt;/b&gt;&lt;/span&gt;하다.&lt;/li&gt;
&lt;li&gt;다만, 일반 사용자가 직접 확인할 수는 없고 &lt;span&gt;&lt;b&gt;디지털 포렌식 분석 과정&lt;/b&gt;&lt;/span&gt;을 거쳐야만 원문을 확인할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 메시지 삭제 기능&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;화면에서는 &amp;ldquo;메시지가 삭제되었습니다.&amp;rdquo;라는 문구가 표시되지만,&lt;/li&gt;
&lt;li&gt;데이터베이스에서는 &lt;span&gt;type&lt;/span&gt; 값과 &lt;span&gt;hidden&lt;/span&gt; 플래그로만 상태가 바뀌고, &lt;span&gt;&lt;b&gt;원본 메시지는 여전히 존재&lt;/b&gt;&lt;/span&gt;한다.&lt;/li&gt;
&lt;li&gt;따라서 삭제된 메시지 역시 복호화를 통해 확인할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로, 카카오톡은 사용자 편의를 위해 메시지 수정&amp;middot;삭제 기능을 제공하지만, 데이터베이스 차원에서는 &lt;span&gt;&lt;b&gt;안전장치(원본 보존 기록)&lt;/b&gt;&lt;/span&gt; 를 두어 원본 메시지 추적이 가능하도록 설계되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 &amp;ldquo;말 바꾸기&amp;rdquo;나 &amp;ldquo;증거 인멸&amp;rdquo;과 같은 악용 가능성을 일정 부분 방지하는 장치가 되지만, 실제 법적 증거로 활용하려면 &lt;span&gt;&lt;b&gt;전문가의 분석, 시간, 비용&lt;/b&gt;&lt;/span&gt;이 필요하다는 점에서 여전히 한계가 존재한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 카카오톡 대화는 &lt;span&gt;&lt;b&gt;편리한 소통 도구이자 동시에 법적&amp;middot;사회적 증거로서 중요한 가치&lt;/b&gt;&lt;/span&gt;를 가진다. 그렇기에 사용자는 수정&amp;middot;삭제 기능을 가볍게 생각하기보다, &lt;span&gt;&lt;b&gt;책임성과 신뢰성을 전제로 한 커뮤니케이션&lt;/b&gt;&lt;/span&gt;이 필요하다고 생각된다.&lt;/p&gt;</description>
      <category>Forensics</category>
      <category>디지털포렌식</category>
      <category>카카오톡</category>
      <category>카카오톡 디지털포렌식</category>
      <category>카카오톡 삭제</category>
      <category>카카오톡 삭제 포렌식</category>
      <category>카카오톡 수정</category>
      <category>카카오톡 수정 되돌리기</category>
      <category>카카오톡 수정 원본</category>
      <category>카카오톡 수정 포렌식</category>
      <category>카카오톡 업데이트</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/587</guid>
      <comments>https://pental.tistory.com/587#entry587comment</comments>
      <pubDate>Tue, 7 Oct 2025 01:35:25 +0900</pubDate>
    </item>
    <item>
      <title>[58회] SQLD 합격 후기</title>
      <link>https://pental.tistory.com/586</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;269&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbzEEl/btsQGTDgMT1/BJFR4IZxs0B59a38KYrZLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbzEEl/btsQGTDgMT1/BJFR4IZxs0B59a38KYrZLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbzEEl/btsQGTDgMT1/BJFR4IZxs0B59a38KYrZLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbzEEl%2FbtsQGTDgMT1%2FBJFR4IZxs0B59a38KYrZLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;999&quot; height=&quot;269&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;269&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이번 58회차 SQLD 자격증을 합격했습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이번 58회차는 역대급으로 어려웠다는 소문이 돌기도 하고,&lt;br /&gt;전공자이긴 하지만 SQL 부분은 다뤄본적이 많이 있지 않아서 조금 어려웠습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;짧게나마 제 공부 방법과 느낀점, 그리고 소소한 팁들을 기록용으로 남겨봅니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;앞으로 준비하시는 분들꼐 조금이나마 도움이 되길 바랍니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1320&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biTuqG/btsQHpuUspU/REMf6Q5QRhTzKHj1iTN5OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biTuqG/btsQHpuUspU/REMf6Q5QRhTzKHj1iTN5OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biTuqG/btsQHpuUspU/REMf6Q5QRhTzKHj1iTN5OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiTuqG%2FbtsQHpuUspU%2FREMf6Q5QRhTzKHj1iTN5OK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1320&quot; height=&quot;700&quot; data-origin-width=&quot;1320&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;SQLD(SQL Developer)는 한국데이터산업진흥원(Kdata)에서 주관하는 국가공인 자격증입니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;데이터베이스의 구조와 원리를 이해하고, &lt;span&gt;&lt;b&gt;SQL을 실제로 다루는 능력&lt;/b&gt;&lt;/span&gt;을 검증하는 시험이라서 IT 개발자뿐만 아니라 데이터 분석가, 기획자에게도 필수 스펙으로 꼽힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;공부 과정  &lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;저는 2025년 여름, 약 두 달 동안 SQLD를 준비했어요. 아이패드로 기본서를 1회독하고,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;노랭이 요약집과 모의고사까지 꾸준히 풀어 나갔습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;769&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beGOeS/btsQGUvoYNL/v8DQx0cTmO0J90eHA21NkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beGOeS/btsQGUvoYNL/v8DQx0cTmO0J90eHA21NkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beGOeS/btsQGUvoYNL/v8DQx0cTmO0J90eHA21NkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeGOeS%2FbtsQGUvoYNL%2Fv8DQx0cTmO0J90eHA21NkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;769&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;769&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D7Pzf/btsQIBasiNt/4hayFwSR3AN6PQB0OYm16k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D7Pzf/btsQIBasiNt/4hayFwSR3AN6PQB0OYm16k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D7Pzf/btsQIBasiNt/4hayFwSR3AN6PQB0OYm16k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD7Pzf%2FbtsQIBasiNt%2F4hayFwSR3AN6PQB0OYm16k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;959&quot; height=&quot;608&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;b&gt;공부 일지&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;6월 21일: 아이패드 기본서 1회독 시작&lt;/li&gt;
&lt;li&gt;6월 26일~&lt;span&gt;30일: 실전 모의고사 1~&lt;/span&gt;5회 풀기 완료&lt;/li&gt;
&lt;li&gt;7월 1일~&lt;span&gt;8일: 노랭이&lt;/span&gt;, 홍쌤 인강 1~5강 모두 수강&lt;/li&gt;
&lt;li&gt;7월 9일~17일: 기본서 P1, P2 전체 복습 완료&lt;/li&gt;
&lt;li&gt;7월 18일~&lt;span&gt;25일: 실전 모의고사 TEST 1~&lt;/span&gt;5회차 풀이&lt;/li&gt;
&lt;li&gt;7월 28일~8월 21일: 노랭이 + SQLD.KR 모의고사 반복 풀이 (점수 50점대 &amp;rarr; 90점대 상승!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;  이렇게 꾸준히 기록하면서 점수가 점차 오르는 게 눈에 보였고, 마지막에는 &lt;span&gt;&lt;b&gt;90점 이상&lt;/b&gt;&lt;/span&gt;까지 도달했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;공부 방법  &lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;기본서 1회독으로 개념 정리&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;처음에는 시대에듀 유선배 SQL개발자 교재로 큰 틀을 잡았습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;노랭이 반복 학습&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;자주 나오는 포인트와 키워드 위주로 빠르게 회독, 틀린 문제는 다시 표시해서 복습했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인강(홍쌤 강의)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;혼자 이해하기 어려운 부분은 인강으로 보충. &amp;ldquo;정규식, 서브쿼리, NULL 처리&amp;rdquo; 같은 파트가 특히 도움 됐어요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모의고사 실전 훈련&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초반 점수: 50~60점대&lt;/li&gt;
&lt;li&gt;후반 점수: 80~90점대&lt;/li&gt;
&lt;li&gt;반복하다 보니 시험장에서 시간 관리와 문제 접근법이 훨씬 편해졌습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;추천 자료  &lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 시대에듀 유선배 SQL 개발자 (개념잡기)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 노랭이 1회독 (문제 유형 확인)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. SQLD.kr 에서 최소 기출 돌렸을때 70점 나올때까지 계속 문제 풀이&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 노랭이 2회독 (점수 제대로 나오는지 확인)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 유튜브 홍쌤 &amp;amp; 아답터 인강 듣기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;합격 소감  &lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;처음에는 막막했지만, &lt;span&gt;&lt;b&gt;기본서 &amp;rarr; 노랭이 &amp;rarr; 인강 &amp;rarr; 모의고사&lt;/b&gt;&lt;/span&gt; 순으로 루틴을 돌리면서 자신감이 붙었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;특히 점수가 오르는 게 눈에 보일 때 정말 뿌듯했고, 시험장에서는 무난하게 풀고 나올 수 있었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SQLD 합격은 끝이 아니라 시작!!!&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 자격증을 기반으로 데이터 분석과 개발을 공부할 때 큰 도움이 될 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;SQLD 준비하는 분들께 ✏️&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;처음엔 무조건 &lt;span&gt;&lt;b&gt;이해 위주&lt;/b&gt;&lt;/span&gt; &amp;rarr; 암기하려 하지 말고 흐름 잡기&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;기출 반복&lt;/b&gt;&lt;/span&gt; &amp;rarr; 최소 3번은 풀어야 안정적인 합격권&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;SQL 직접 쳐보기&lt;/b&gt;&lt;/span&gt; &amp;rarr; 손으로 안 치면 절대 안 외워집니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;꾸준히 하면 누구든 합격할 수 있는 시험이니, 저처럼 일정 잡고 꾸준히 따라가 보시길 추천드립니다  &lt;/p&gt;</description>
      <category>이것저것</category>
      <category>58회 SQLD 후기</category>
      <category>SQLD</category>
      <category>SQLD 58회</category>
      <category>SQLD 공부 방법</category>
      <category>SQL개발자</category>
      <category>데이터자격시험</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/586</guid>
      <comments>https://pental.tistory.com/586#entry586comment</comments>
      <pubDate>Sat, 20 Sep 2025 12:55:30 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1673 - 치킨 쿠폰 (파이썬)</title>
      <link>https://pental.tistory.com/585</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdYdI3/btsQtgMIHap/YNLQP1fVm7ulpdRkBHJGXK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdYdI3/btsQtgMIHap/YNLQP1fVm7ulpdRkBHJGXK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdYdI3/btsQtgMIHap/YNLQP1fVm7ulpdRkBHJGXK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdYdI3%2FbtsQtgMIHap%2FYNLQP1fVm7ulpdRkBHJGXK%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;225&quot; height=&quot;225&quot; data-origin-width=&quot;225&quot; data-origin-height=&quot;225&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0cqHN/btsQtjbDw0D/wquksQ5kGEc6HLcpginLM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0cqHN/btsQtjbDw0D/wquksQ5kGEc6HLcpginLM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0cqHN/btsQtjbDw0D/wquksQ5kGEc6HLcpginLM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0cqHN%2FbtsQtjbDw0D%2FwquksQ5kGEc6HLcpginLM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1168&quot; height=&quot;423&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1673&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1673&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;치킨 한마리를 먹으면 쿠폰을 1장 준다. 요즘도 쿠폰을 주는 치킨집이 있던가,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠폰 K장을 모으면 치킨 1마리로 교환할 수 있다. 처음에 가진 치킨 수 N이 주어졌을 때, 총 몇마리의 치킨을 먹을 수 있는지 구하는 문제이다.&lt;/p&gt;
&lt;pre id=&quot;code_1757641330139&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;3 2
4 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시로 다음과 같은 입력이 주어졌다면 분석하면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 3마리를 주문 했고, 쿠폰 3장을 지급 받았다. 1마리를 교환 했고, 쿠폰이 1장 남아있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 1마리를 주문하면서 쿠폰 1장을 더 받았기에, 남은 쿠폰은 2개가 되어 한마리를 더 주문할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 5마리를 먹을 수 있는 셈이다. 완전 부럽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4 3 의 경우 처음에 4마리를 먹었고, 쿠폰 4장을 지급 받았다. 이 치킨 집은 3장당 한마리로 바꿔주기에, 4장 중에 3장을 써서 1마리를 더 먹을 수 있다. 즉 5마리를 먹을수 있는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1757641634410&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# [브론즈 2] 백준 1673 - 치킨 쿠폰

while True :
    try :
        N, K = map(int, input().split())
        result = 0
        result += N
        while N // K :
            result += N // K
            N = N // K + N % K
        print(result)
    except :
        break&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1673</category>
      <category>백준 1673 치킨 쿠폰</category>
      <category>백준 1673 치킨 쿠폰 파이썬</category>
      <category>백준 1673 파이썬</category>
      <category>백준 치킨 쿠폰</category>
      <category>백준 치킨 쿠폰 파이썬</category>
      <category>브론즈</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/585</guid>
      <comments>https://pental.tistory.com/585#entry585comment</comments>
      <pubDate>Fri, 12 Sep 2025 10:48:36 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1718 - 암호 (파이썬)</title>
      <link>https://pental.tistory.com/584</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQSg4F/btsQvRrh9S7/3XgX7vAo0qgH1cQY5gU1iK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQSg4F/btsQvRrh9S7/3XgX7vAo0qgH1cQY5gU1iK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQSg4F/btsQvRrh9S7/3XgX7vAo0qgH1cQY5gU1iK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQSg4F%2FbtsQvRrh9S7%2F3XgX7vAo0qgH1cQY5gU1iK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;352&quot; height=&quot;130&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1718&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1718&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 평문을 주어진 KEY로 암호화한 문장을 해독하는 것인데, 여기서 중요한 포인트는 &lt;b&gt;키 값에서 +1 처리를 반드시 해줘야 한다&lt;/b&gt;는 점이다.&lt;/p&gt;
&lt;pre id=&quot;code_1757638680591&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;S = input().rstrip()
KEY = input().rstrip()

LONG_KEY = &quot;&quot;
while len(LONG_KEY) &amp;lt; len(S):
    LONG_KEY += KEY&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;308&quot; data-start=&quot;276&quot;&gt;암호화할 평문 S와 키 KEY를 입력받는다.&lt;/li&gt;
&lt;li data-end=&quot;356&quot; data-start=&quot;309&quot;&gt;키는 평문보다 짧을 수 있기 때문에 평문의 길이에 맞게 반복해서 이어 붙인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1757638695750&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;result = []
for i in range(len(S)):
    if S[i] == &quot; &quot;:
        result.append(&quot; &quot;)
    else:
        c = ord(S[i]) - ord('a')
        k = ord(LONG_KEY[i]) - ord('a')
        dec = (c - (k+1)) % 26
        result.append(chr(dec + ord('a')))&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;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;715&quot; data-start=&quot;684&quot;&gt;평문이 공백 &quot; &quot;이면 그대로 결과에 넣는다.&lt;/li&gt;
&lt;li data-end=&quot;889&quot; data-start=&quot;716&quot;&gt;알파벳일 경우:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;889&quot; data-start=&quot;729&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;763&quot; data-start=&quot;729&quot;&gt;평문의 문자를 숫자로 변환(a=0, b=1, &amp;hellip;).&lt;/li&gt;
&lt;li data-end=&quot;784&quot; data-start=&quot;766&quot;&gt;키의 문자를 숫자로 변환.&lt;/li&gt;
&lt;li data-end=&quot;889&quot; data-start=&quot;787&quot;&gt;암호문을 만들 때는 (평문 + 키+1) % 26으로 암호화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1757638714087&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# [브론즈 2] 백준 1718 - 암호

S = input().rstrip()
KEY = input().rstrip()

LONG_KEY = &quot;&quot;
while len(LONG_KEY) &amp;lt; len(S):
    LONG_KEY += KEY

result = []
for i in range(len(S)):
    if S[i] == &quot; &quot;:
        result.append(&quot; &quot;)
    else:
        c = ord(S[i]) - ord('a')
        k = ord(LONG_KEY[i]) - ord('a')
        dec = (c - (k+1)) % 26
        result.append(chr(dec + ord('a')))

print(&quot;&quot;.join(result))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1718</category>
      <category>백준 1718 암호</category>
      <category>백준 1718 암호 파이썬</category>
      <category>백준 1718 파이썬</category>
      <category>백준 암호</category>
      <category>백준 암호 파이썬</category>
      <category>브론즈</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/584</guid>
      <comments>https://pental.tistory.com/584#entry584comment</comments>
      <pubDate>Fri, 12 Sep 2025 09:59:40 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈  2] 백준 1592 - 영식이와 친구들 (파이썬)</title>
      <link>https://pental.tistory.com/583</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bobsVc/btsQtmd9yhU/ZR6eTVoCRW3khiZZLmjoD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bobsVc/btsQtmd9yhU/ZR6eTVoCRW3khiZZLmjoD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bobsVc/btsQtmd9yhU/ZR6eTVoCRW3khiZZLmjoD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbobsVc%2FbtsQtmd9yhU%2FZR6eTVoCRW3khiZZLmjoD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1178&quot; height=&quot;478&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1592&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1592&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 N명의 친구들이 원형으로 앉아 있다. 공을 가진 사람이 공을 던질 때, 현재 그 사람이 받은 횟수가 홀수라면 오른쪽 L번째 있는 사람에게, 짝수라면 왼쪽으로 L번째 있는 사람에게 공을 던진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 친구가 공을 M번 받으면 게임이 끝나고, 공을 총 몇 번 던졌는지 출력하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 배열로 각 친구의 공 받은 횟수를 기록한다.&lt;/p&gt;
&lt;pre id=&quot;code_1757551830672&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;N, M, L = map(int, input().split())
A = [0] * N&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초의 배열은 [0]으로 초기화 하였으며, N, M, L 은 map을 통해서 입력 받는다.&lt;/p&gt;
&lt;pre id=&quot;code_1757551865112&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while max_ball != M :
    A[index] += 1
    max_ball = max(max_ball, A[index])
    if max_ball == M :
        break
    if A[index] &amp;lt; M and A[index] % 2 == 1 :
        index += L
        if index &amp;gt;= N :
            index -= N
    elif A[index] &amp;lt; M and A[index] % 2 == 0 :
        index -= L
        if index &amp;lt; 0 :
            index += N
    result += 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 로직은 위 부분이다. 먼저 공을 줬기 때문에 A의 현재 인덱스에 1을 증가시키고, 현재의 공의 갯수와, 가장 많은 공을 잡은 사람의 횟수를 비교하여 M과 동일하다면 종료한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽과 오른쪽으로 나누기 위해서 만약 N명의 범위가 초과 하거나 미만인경우 적절하게 +-를 통해서 N으로 증감해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 인덱스 갱신 부분을 더 깔끔하게 쓰려면 mod 연산을 바로 사용하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1757551982023&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if A[index] % 2 == 1:   # 홀수
    index = (index + L) % N
else:                   # 짝수
    index = (index - L) % N&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드&lt;/p&gt;
&lt;pre id=&quot;code_1757551992448&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# [브론즈 2] 백준 1592 - 영식이와 친구들

N, M, L = map(int, input().split())
A = [0] * N
# A[0] = 1
max_ball = 0
index = 0
result = 0
while max_ball != M :
    A[index] += 1
    max_ball = max(max_ball, A[index])
    if max_ball == M :
        break
    if A[index] &amp;lt; M and A[index] % 2 == 1 :
        index += L
        if index &amp;gt;= N :
            index -= N
    elif A[index] &amp;lt; M and A[index] % 2 == 0 :
        index -= L
        if index &amp;lt; 0 :
            index += N
    result += 1
print(result)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1592</category>
      <category>백준 1592 영식이와 친구들</category>
      <category>백준 1592 영식이와 친구들 파이썬</category>
      <category>백준 1592 파이썬</category>
      <category>백준 영식이와 친구들</category>
      <category>백준 영식이와 친구들 파이썬</category>
      <category>브론즈</category>
      <category>브론즈 2</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/583</guid>
      <comments>https://pental.tistory.com/583#entry583comment</comments>
      <pubDate>Thu, 11 Sep 2025 09:53:50 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 1] 백준 1524 - 세준세비 (파이썬)</title>
      <link>https://pental.tistory.com/582</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dXEJoK/btsQsGQtqsK/8FeOh5Nr3aNkrqnq4dnAiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dXEJoK/btsQsGQtqsK/8FeOh5Nr3aNkrqnq4dnAiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dXEJoK/btsQsGQtqsK/8FeOh5Nr3aNkrqnq4dnAiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdXEJoK%2FbtsQsGQtqsK%2F8FeOh5Nr3aNkrqnq4dnAiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;762&quot; height=&quot;588&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1524&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1524&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;세준(S)과 세비(B)가 각각 병사를 가지고 있다. 병사들끼리 전투를 하는데, &lt;b&gt;가장 약한 병사&lt;/b&gt;들끼리 싸운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전투 규칙은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 세준의 최약체 &amp;ge; 세비의 최약체 &amp;rarr; 세비의 병사가 죽는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 세준의 최약체 &amp;lt; 세비의 최약체 &amp;rarr; 세준의 병사가 죽는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘 중 한 쪽의 병사가 전멸할 때까지 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에서 조건에 따라서 양쪽 진영의 최약체만 비교하면 된다. 파이썬 리스트 기본 함수인 pop을 사용했으며 O(1)의 시간복잡도를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 정렬을 미리 해주었기 떄문에 -1 번 인덱스의 값이 항상 최약체의 값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 내가 작성하였지만 사실 이 문제는 시뮬레이션을 다 돌릴 필요가 없는 문제이다. 규칙상 세준이의 최약제 &amp;gt;= 세비의 최약체 라면 세비만 계속 죽기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 양 진영의 최강 병사 중 더 강한 쪽이 반드시 승리한다고 생각 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1757466234153&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;T = int(input())
for _ in range(T) :
    input()  # 공백 줄 처리
    N, M = map(int, input().split())  # 세준, 세비 병사 수
    sejuns = list(map(int, input().split()))  # 세준 병사 힘
    sebis = list(map(int, input().split()))   # 세비 병사 힘

    # 강한 순서로 정렬
    sejuns.sort(reverse = True)
    sebis.sort(reverse = True)
    
    # 전투 시뮬레이션
    while sejuns and sebis :
        if sejuns[-1] &amp;gt;= sebis[-1] :  # 세준의 최약체가 세비의 최약체보다 강하거나 같음
            sebis.pop()  # 세비 병사 제거
        else :
            sejuns.pop()  # 세준 병사 제거
    
    # 결과 판별
    if sejuns : 
        print(&quot;S&quot;)
    elif sebis :
        print(&quot;B&quot;)
    else :
        print(&quot;C&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1757466338704&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;T = int(input())
for _ in range(T):
    input()
    N, M = map(int, input().split())
    sejuns = max(map(int, input().split()))
    sebis = max(map(int, input().split()))

    if sejuns &amp;gt;= sebis:
        print(&quot;S&quot;)
    else:
        print(&quot;B&quot;)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1524</category>
      <category>백준 1524 세준세비</category>
      <category>백준 1524 세준세비 파이썬</category>
      <category>백준 1524 파이썬</category>
      <category>백준 세준세비</category>
      <category>백준 세준세비 파이썬</category>
      <category>백준 알고리즘</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/582</guid>
      <comments>https://pental.tistory.com/582#entry582comment</comments>
      <pubDate>Wed, 10 Sep 2025 10:06:29 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1452 - 피시방 알바 (파이썬)</title>
      <link>https://pental.tistory.com/581</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSwHum/btsQssLFjBI/QZDyft7FNhKGuMOmtSAGiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSwHum/btsQssLFjBI/QZDyft7FNhKGuMOmtSAGiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSwHum/btsQssLFjBI/QZDyft7FNhKGuMOmtSAGiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSwHum%2FbtsQssLFjBI%2FQZDyft7FNhKGuMOmtSAGiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;763&quot; height=&quot;481&quot; data-origin-width=&quot;763&quot; data-origin-height=&quot;481&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1453&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1453&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp처럼 생겼지만 걍 단순한 구현문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;check 배열에 False로 하여 100개를 미리 만들어 두고, 각 손님을 돌면서 해당 자리에 넣고 True로 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 동일한 자리가 들어오게 되면 result 변수에 +1 을 하여 거절당하는 자리를 계산할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1757465886576&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1453 - 피시방 알바

check = [False] * 100
N = int(input())
A = list(map(int, input().split()))

result = 0
for i in A :
    if check[i - 1] == False :
        check[i - 1] = True
    else :
        result += 1

print(result)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1453</category>
      <category>백준 1453 파이썬</category>
      <category>백준 1453 피시방 알바</category>
      <category>백준 1453 피시방 알바 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 피시방 알바</category>
      <category>백준 피시방 알바 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/581</guid>
      <comments>https://pental.tistory.com/581#entry581comment</comments>
      <pubDate>Wed, 10 Sep 2025 09:58:38 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1440 - 타임머신 (파이썬)</title>
      <link>https://pental.tistory.com/580</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m6xVs/btsQqV18Hdw/6CHAVh5S7ZGtT8SfAME44K/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m6xVs/btsQqV18Hdw/6CHAVh5S7ZGtT8SfAME44K/img.webp&quot; data-alt=&quot;본 문제와 무관합니다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m6xVs/btsQqV18Hdw/6CHAVh5S7ZGtT8SfAME44K/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm6xVs%2FbtsQqV18Hdw%2F6CHAVh5S7ZGtT8SfAME44K%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;1000&quot; height=&quot;840&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;840&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;799&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daiHxH/btsQs5h76qV/EXw5nGPxaRppHY791hX2n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daiHxH/btsQs5h76qV/EXw5nGPxaRppHY791hX2n1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daiHxH/btsQs5h76qV/EXw5nGPxaRppHY791hX2n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaiHxH%2FbtsQs5h76qV%2FEXw5nGPxaRppHY791hX2n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;799&quot; height=&quot;696&quot; data-origin-width=&quot;799&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1440&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1440&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉬운 구현문제중 하나이다. HH:MM:SS의 시간을 DD:DD:DD로 입력받았을때 유효한 시간의 갯수만 계싼하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단 여기서 확인해야하는 점은 시간은 1 ~ 12시까지, 분은 00 ~ 59분까지 초는 00 ~ 59초 까지만 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 유효성 검증을 하는 함수를 하나 만들어줬다.&lt;/p&gt;
&lt;pre id=&quot;code_1757465551648&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def check_hour(HH) :
    if HH &amp;gt; 12 or HH &amp;lt; 1:
        return False
    return True

def check_minute(MM) :
    if MM &amp;gt;= 60 :
        return False
    return True

def check_second(SS) :
    if SS &amp;gt;= 60 :
        return False
    return True&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 함수와 같이 시간과 분, 초를 각각 검증하는 함수를 작성하였고, 각 순열을 만들어야 하기에, permutations 함수를 이용하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1757465588976&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1440 - 타임머신
from itertools import permutations

HH, MM, SS = map(int, input().split(&quot;:&quot;))

def check_hour(HH) :
    if HH &amp;gt; 12 or HH &amp;lt; 1:
        return False
    return True

def check_minute(MM) :
    if MM &amp;gt;= 60 :
        return False
    return True

def check_second(SS) :
    if SS &amp;gt;= 60 :
        return False
    return True

result = 0
for permutation in permutations([HH, MM, SS], 3) :
    HH, MM, SS = permutation
    if check_hour(HH) and check_minute(MM) and check_second(SS) :
        result += 1

print(result)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1440</category>
      <category>백준 1440 타임머신</category>
      <category>백준 1440 타임머신 파이썬</category>
      <category>백준 1440 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 타임머신</category>
      <category>백준 타임머신 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/580</guid>
      <comments>https://pental.tistory.com/580#entry580comment</comments>
      <pubDate>Wed, 10 Sep 2025 09:54:48 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1263 - 펫 (파이썬)</title>
      <link>https://pental.tistory.com/579</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3Nyog/btsQojCFTz0/tkiP0KKh1kyq7odnBLqA80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3Nyog/btsQojCFTz0/tkiP0KKh1kyq7odnBLqA80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3Nyog/btsQojCFTz0/tkiP0KKh1kyq7odnBLqA80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3Nyog%2FbtsQojCFTz0%2FtkiP0KKh1kyq7odnBLqA80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1189&quot; height=&quot;820&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1362&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1362&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 테케가 주어지며 각 케이스는 O W로 시작한다. 0 0 이면 전체 입력이 종료된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테케마다 # 0 이 주어지면 그 케이스는 끝이 난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E x 는 체중을 빼고, F x는 체중을 더한다. 하지만 처리 도중 W &amp;lt;= 0 이 되는 순간 죽는것이다. 그 뒤 명령은 반영하지 않고, # 0 까지 입력만 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최종적으로 사망하면 RIP, 생존이고 적정 체중의 1.5배 및 2배 미만이면 :-), 그 외는 :-(을 출력하는 문제이다.&lt;/p&gt;
&lt;pre id=&quot;code_1757390461006&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1362 - 펫
import sys
input = sys.stdin.readline

def opt(O, W) :
    if W &amp;gt; O * 0.5 and W &amp;lt; 2 * O :
        return &quot;:-)&quot;
    elif W &amp;lt;= 0 :
        return &quot;RIP&quot;
    else :
        return &quot;:-(&quot;
index = 1
while True :
    O, W = map(int, input().split())
    if O == 0 and W == 0 :
        break
    alive = (W &amp;gt; 0)
    while True :
        DATA = input().split()
        op = DATA[0]
        weight = int(DATA[1])
        if op == &quot;#&quot; and weight == 0 :
            if not alive:
                print(index, &quot;RIP&quot;)
            else:
                print(index, opt(O, W))
            index += 1
            break
        if alive :
            if op == &quot;E&quot; :
                W -= weight
            elif op == &quot;F&quot; :
                W += weight
            
            if W &amp;lt;= 0 :
                alive = False&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1362</category>
      <category>백준 1362 파이썬</category>
      <category>백준 1362 펫</category>
      <category>백준 1362 펫 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 펫</category>
      <category>백준 펫 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/579</guid>
      <comments>https://pental.tistory.com/579#entry579comment</comments>
      <pubDate>Tue, 9 Sep 2025 13:01:08 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 1] 백준 1356 -  유진수 (파이썬)</title>
      <link>https://pental.tistory.com/578</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cw2Gaf/btsQopiihQJ/74MPrtk6T3MnsEDCaVrwqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cw2Gaf/btsQopiihQJ/74MPrtk6T3MnsEDCaVrwqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cw2Gaf/btsQopiihQJ/74MPrtk6T3MnsEDCaVrwqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcw2Gaf%2FbtsQopiihQJ%2F74MPrtk6T3MnsEDCaVrwqk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;740&quot; height=&quot;544&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1356&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1356&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정수 N이 주어졌을 때, 이 수가 유진수인지 판별해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유진수는 어떤 수 N을 앞부분과 뒷부분으로 나누었을 때, 앞부분 각 자리수의 곱과 뒷부분 각 자리수의 곱이 같은 경우를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1221 -&amp;gt; (12 | 21) =&amp;gt; 1 * 2 = 2, 2 * 1 = 2 -&amp;gt; 즉, 유진수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1236 -&amp;gt; (123 | 6) =&amp;gt; 1 * 2 * 3 = 6, 6 = 6 -&amp;gt; 즉, 유진수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1234 -&amp;gt; 어떤 방법으로도 곱이 같아지지 않음 -&amp;gt; 즉, 유진수 아님&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 다음과 같이 작성하였다.&lt;/p&gt;
&lt;pre id=&quot;code_1757379489091&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1356 - 유진수

N = list(input())

start = len(N)
result = False
for i in range(1, start) :
    A = N[:i]
    B = N[i:]

    temp_A, temp_B = 1, 1

    for x in A :
        temp_A *= int(x)
    for y in B :
        temp_B *= int(y)

    if temp_A == temp_B :
        result = True
        break

if result : 
    print(&quot;YES&quot;)
else :
    print(&quot;NO&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start는 전체 길이를 나타내며, result의 경우 유진수 여부를 판별하는 변수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자르는 위치를 1부터 시작해서 start 까지 돌면서 A와 B를 나눈다. 즉 앞부분과 뒷부분을 나누고, 각각 앞부분과 뒷부분의 각 요소를 곱해서 두 곱이 같으면 유진수, 다르면 유진수가 아니도록 코드를 작성하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 1221를 입력한 경우는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;979&quot; data-start=&quot;970&quot;&gt;길이: 4&lt;/li&gt;
&lt;li data-end=&quot;1022&quot; data-start=&quot;980&quot;&gt;i=1 &amp;rarr; A=&quot;1&quot;, B=&quot;221&quot; &amp;rarr; 곱: 1 vs 4 &amp;rarr; 불일치&lt;/li&gt;
&lt;li data-end=&quot;1077&quot; data-start=&quot;1023&quot;&gt;i=2 &amp;rarr; A=&quot;12&quot;, B=&quot;21&quot; &amp;rarr; 곱: 2 vs 2 &amp;rarr; 일치 &amp;rarr; &lt;b&gt;YES 출력&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작복잡도는 O(N^2)이라 조금 비효율 적이지만 그래도 자리수가 최대 10이라 충분히 빠르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1356</category>
      <category>백준 1356 유진수</category>
      <category>백준 1356 유진수 파이썬</category>
      <category>백준 1356 파이썬</category>
      <category>백준 유진수</category>
      <category>백준 유진수 파이선</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/578</guid>
      <comments>https://pental.tistory.com/578#entry578comment</comments>
      <pubDate>Tue, 9 Sep 2025 10:00:01 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈 2] 백준 1297 - TV 크기 (파이썬)</title>
      <link>https://pental.tistory.com/577</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BsVIk/btsQrsRYMCc/LqSBAq5xZZOH9J4uRXVoEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BsVIk/btsQrsRYMCc/LqSBAq5xZZOH9J4uRXVoEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BsVIk/btsQrsRYMCc/LqSBAq5xZZOH9J4uRXVoEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBsVIk%2FbtsQrsRYMCc%2FLqSBAq5xZZOH9J4uRXVoEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;788&quot; height=&quot;530&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1297&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1297&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 TV 대각선 길이 D와 높이, 너비의 비율 H:W 가 주어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 TV의 높이와 너비 (h, w)는 피타고라스 정리로 표현할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;36&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uBeCv/btsQpxNxJiB/WLKQ9l1Tkbz1qEkxwaZr90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uBeCv/btsQpxNxJiB/WLKQ9l1Tkbz1qEkxwaZr90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uBeCv/btsQpxNxJiB/WLKQ9l1Tkbz1qEkxwaZr90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuBeCv%2FbtsQpxNxJiB%2FWLKQ9l1Tkbz1qEkxwaZr90%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;140&quot; height=&quot;36&quot; data-origin-width=&quot;140&quot; data-origin-height=&quot;36&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 비율 관계가 성립한다. 아래 수식을 참고하자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;94&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEYsHL/btsQnYed1WF/jNUAdvo91SPcmanmqhUq71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEYsHL/btsQnYed1WF/jNUAdvo91SPcmanmqhUq71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEYsHL/btsQnYed1WF/jNUAdvo91SPcmanmqhUq71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEYsHL%2FbtsQnYed1WF%2FjNUAdvo91SPcmanmqhUq71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;94&quot; height=&quot;57&quot; data-origin-width=&quot;94&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 실제 높이와 너비는 H와 W를 일정 비율로 확대한 값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사칙연산으로 접근하면 높이와 너비를 K배 만큼 확대한 값이라고 한다면, 다음과 같이 수식을 새울수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;39&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xm5nu/btsQqW6RBNo/AwKkFXgLpvamk6kkdoRc4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xm5nu/btsQqW6RBNo/AwKkFXgLpvamk6kkdoRc4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xm5nu/btsQqW6RBNo/AwKkFXgLpvamk6kkdoRc4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxm5nu%2FbtsQqW6RBNo%2FAwKkFXgLpvamk6kkdoRc4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;241&quot; height=&quot;39&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;39&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 아는 대각선 공식에 대입하면 필요한 수식은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mgmzz/btsQoHcaaip/5S5GPek9DinNevTYPIV211/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mgmzz/btsQoHcaaip/5S5GPek9DinNevTYPIV211/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mgmzz/btsQoHcaaip/5S5GPek9DinNevTYPIV211/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmgmzz%2FbtsQoHcaaip%2F5S5GPek9DinNevTYPIV211%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;214&quot; height=&quot;147&quot; data-origin-width=&quot;214&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작성한 코드는 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1757378316822&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1297 - TV 크기

import math

D, H, W = map(int, input().split())

R = D / (H ** 2 + W ** 2) ** 0.5
print(int(H * R), int(W * R))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1297</category>
      <category>백준 1297 TV 크기</category>
      <category>백준 1297 TV 크기 파이썬</category>
      <category>백준 1297 파이썬</category>
      <category>백준 TV 크기</category>
      <category>백준 TV 크기 파이썬</category>
      <category>백준 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/577</guid>
      <comments>https://pental.tistory.com/577#entry577comment</comments>
      <pubDate>Tue, 9 Sep 2025 09:39:24 +0900</pubDate>
    </item>
    <item>
      <title>[브론즈  2] 백준 1350 - 진짜 공간 (파이썬)</title>
      <link>https://pental.tistory.com/576</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1350&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1350&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;758&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/31PQF/btsQnZjVyeZ/Vera0n3HfAd3IEbfTylkMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/31PQF/btsQnZjVyeZ/Vera0n3HfAd3IEbfTylkMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/31PQF/btsQnZjVyeZ/Vera0n3HfAd3IEbfTylkMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F31PQF%2FbtsQnZjVyeZ%2FVera0n3HfAd3IEbfTylkMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;630&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 시스템을 공부하는 나에겐 재밌는 문제이다. 먼저 이 문제는 파일 시스템에서는 디스크 공간이 파일 사이즈와 항상 같지 않고, 디스크가 일정한 크기의 클러스터로 나뉘어져있고, &lt;b&gt;한 클러스터는 오직 한 파일만 이용&lt;/b&gt;할 수 있다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한것은 한 클러스터는 오직 한 파일만 이용할수 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제에서 클러스트가 512bytes이고, 600bytes의 파일을 저장하려고 한다면 두개의 클러스터에 저장하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEvAVI/btsQpA4tqag/RFiPKTSvkQrOmAPtczi4X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEvAVI/btsQpA4tqag/RFiPKTSvkQrOmAPtczi4X0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEvAVI/btsQpA4tqag/RFiPKTSvkQrOmAPtczi4X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEvAVI%2FbtsQpA4tqag%2FRFiPKTSvkQrOmAPtczi4X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;431&quot; height=&quot;270&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 600 bytes의 파일을 저장하게되면 2개의 클러스터를 사용하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나 중요한것은 한 클러스터에는 하나의 파일만 이용할 수 있다는 점이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t4I5l/btsQrxZ39O4/7uGH7fzUYzbgo8aGZhk0X1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t4I5l/btsQrxZ39O4/7uGH7fzUYzbgo8aGZhk0X1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t4I5l/btsQrxZ39O4/7uGH7fzUYzbgo8aGZhk0X1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft4I5l%2FbtsQrxZ39O4%2F7uGH7fzUYzbgo8aGZhk0X1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;761&quot; height=&quot;362&quot; data-origin-width=&quot;761&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 500, 12, 100이 들어왔다면 512Bytes에 2개의 파일을 저장할수 있는것이 아닌 아래 그림과 같이 하나의 클러스터에는 한개의 파일만 저장 할 수 있는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BBSV3/btsQpbKQubH/dXppAXDxksrC6oOGOGOkJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BBSV3/btsQpbKQubH/dXppAXDxksrC6oOGOGOkJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BBSV3/btsQpbKQubH/dXppAXDxksrC6oOGOGOkJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBBSV3%2FbtsQpbKQubH%2FdXppAXDxksrC6oOGOGOkJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;275&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 코딩으로 나타내면 다음과 같이 작성 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1757377753278&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 1350 - 진짜 공간

N = int(input())
SIZE = list(map(int, input().split()))
CLUSTER = int(input())

result = 0
for i in SIZE :
    if i == 0 :
        continue

    if i &amp;gt; CLUSTER :
        if i % CLUSTER &amp;gt; 0 :
            result += i // CLUSTER + 1
        else :
            result += i // CLUSTER
    else :
        result += 1
print(result * CLUSTER)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N과 파일 크기들, 클러스터 크기를 입력받고, 파일 크기가 0인 파일은 클러스터에 저장되지 않아도 되므로, 다음 파일로 넘어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 파일 크리가 클러스터보다 크다면 클러스터를 연속해서 사용해야하는데, 여기서 클러스터가 1024 크기이고, 들어오는 파일이 2049 라면 1024 + 1024 + 1 을 사용해야하기에, 총 3개가 들어온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 파일 크기는 클러스터 크기로 나머지 연산을 했을때 0보다 크다면 + 1을 적용하고, 파일 크기를 클러스터 사이즈로 나누었을때 몫을 더해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지가 없는 경우에는 파일 크기를 클러스터 사이즈로 나누었을때의 몫을 더해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그외에는 그냥 + 1을 통해서 클러스터 갯수를 증가시키고, 마지막에는 클러스터 갯수 * 클러스터 사이즈로 결과를 도출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1350</category>
      <category>백준 1350 진짜 공간</category>
      <category>백준 1350 진짜 공간 파이썬</category>
      <category>백준 1350 파이썬</category>
      <category>백준 진짜 공간</category>
      <category>백준 진짜 공간 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/576</guid>
      <comments>https://pental.tistory.com/576#entry576comment</comments>
      <pubDate>Tue, 9 Sep 2025 09:32:45 +0900</pubDate>
    </item>
    <item>
      <title>나스 서버 교체 후기 (8베이 나스, 녹투아 쿨러)</title>
      <link>https://pental.tistory.com/575</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 사용하던 서버는 미니 피씨 형태로 작기도 하고, NVME도 1개, 하드도 최대 2개밖에 장착할 수 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 예전에 8베이 케이스를 사둔게 아깝기도 하고 용량 확장을 위해서 다시 8베이 케이스 + D-1581 보드로 이전하는 작업을 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;F1099C5D-29DA-4069-BF7A-15B9DBCB5256_4_5005_c.jpeg&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EgkhE/btsQdYqYb4q/dNBfKUKHc1sY4MedW5Kc50/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EgkhE/btsQdYqYb4q/dNBfKUKHc1sY4MedW5Kc50/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EgkhE/btsQdYqYb4q/dNBfKUKHc1sY4MedW5Kc50/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEgkhE%2FbtsQdYqYb4q%2FdNBfKUKHc1sY4MedW5Kc50%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;360&quot; data-filename=&quot;F1099C5D-29DA-4069-BF7A-15B9DBCB5256_4_5005_c.jpeg&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3년전 사놨던 8베이 나스 케이스,, 사실 한 1년 돌리고 소음이랑 발열 때문에 묵혀놨다. 근데 기존에 사용하던 서버는 SATA가 2개 뿐이라서 ㅜㅜ 어쩔수 없이 다시 서버 이전을 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bccZsV/btsQdyNhEaU/kKLIbKS0A9RPciIXISCnw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bccZsV/btsQdyNhEaU/kKLIbKS0A9RPciIXISCnw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bccZsV/btsQdyNhEaU/kKLIbKS0A9RPciIXISCnw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbccZsV%2FbtsQdyNhEaU%2FkKLIbKS0A9RPciIXISCnw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;794&quot; height=&quot;525&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 장착되어 있는 쿨러는 80mm 쿨러 4개가 달려 있고, 4핀으로 PWM 제어가 되지 않는 모델이다. 심지어 2800RPM 으로 쉬지 않고 돌아서 잠자는 방에서 돌리기엔 문제가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿨러 4개를 모두 녹투아로 교체하자니 쿨러만 10만원이 훌쩍 넘어가는 비용,, 그래서 그냥 8베이중에 4베이를 과감하게 버리고 쿨러 2개로 진행하기로 했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;69&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUVOWq/btsQfxFYdks/AKrqgb3M1nK0civKddA4nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUVOWq/btsQfxFYdks/AKrqgb3M1nK0civKddA4nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUVOWq/btsQfxFYdks/AKrqgb3M1nK0civKddA4nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUVOWq%2FbtsQfxFYdks%2FAKrqgb3M1nK0civKddA4nk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;826&quot; height=&quot;69&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;69&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VkjjR/btsQfwG4svJ/0BCSDDwcyuIUT3I3aHqBtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VkjjR/btsQfwG4svJ/0BCSDDwcyuIUT3I3aHqBtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VkjjR/btsQfwG4svJ/0BCSDDwcyuIUT3I3aHqBtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVkjjR%2FbtsQfwG4svJ%2F0BCSDDwcyuIUT3I3aHqBtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1106&quot; height=&quot;620&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개당 2.8 주고 2개를 구입했고, 서버 쿨러를 변경하기 위해서 케이스를 뜯었는데,,,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqFO4V/btsQdpI3y3N/A1SjOfzoakh5vE2hRSPwz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqFO4V/btsQdpI3y3N/A1SjOfzoakh5vE2hRSPwz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqFO4V/btsQdpI3y3N/A1SjOfzoakh5vE2hRSPwz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqFO4V%2FbtsQdpI3y3N%2FA1SjOfzoakh5vE2hRSPwz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;778&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;케이스를 완전 분해해야지만 HDD&amp;nbsp; 백플레인에 있는 쿨러를 뗄수 있다.. 이거땜에 케이스 완전 분해를 진행했다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실은 이 과정에서 조금 고민이 많이 됐다. 현재는 해당 모델의 케이스를 사용하고 있으며, 케이스 내 쿨러는 다음과 같이 배치되어 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oHuLQ/btsQdzrNNEm/uhkOxeei3FAPihZ3ReZYuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oHuLQ/btsQdzrNNEm/uhkOxeei3FAPihZ3ReZYuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oHuLQ/btsQdzrNNEm/uhkOxeei3FAPihZ3ReZYuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoHuLQ%2FbtsQdzrNNEm%2FuhkOxeei3FAPihZ3ReZYuk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;427&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해당 상품에서는 HDD 백플레인쪽에 쿨러가 없는데, HDD 백플레인쪽 2개, 위 사진에서 보이는 케이스에 딱 붙어있는 쿨러 2개&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;총 4개가 달려 있다... 팬 소음이 심해서 녹투아 NF-A8로 전체 교체를 진행하고 있는데,,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbIGB/btsQdzeg58w/k4ywt7RMvuWsxzMtTAZMb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbIGB/btsQdzeg58w/k4ywt7RMvuWsxzMtTAZMb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbIGB/btsQdzeg58w/k4ywt7RMvuWsxzMtTAZMb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbIGB%2FbtsQdzeg58w%2Fk4ywt7RMvuWsxzMtTAZMb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;427&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;흡기 배기는, 아래 보드 쪽에는 CPU 쪽으로 흡기가 되고 CPU를 식혀주는게 당연하고, 위쪽에서는 위 그림처럼 HDD 쪽으로 바람을 2방향 보내고, 반대로 뒤편에 있는 쿨러는 케이스 밖으로 바람을 보내는게 맞을까?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cteYLz/btsQdcp7DQf/odSiTBGD1NJZB9fkIEn870/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cteYLz/btsQdcp7DQf/odSiTBGD1NJZB9fkIEn870/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cteYLz/btsQdcp7DQf/odSiTBGD1NJZB9fkIEn870/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcteYLz%2FbtsQdcp7DQf%2FodSiTBGD1NJZB9fkIEn870%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;427&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아니면 2번 사진처럼 HDD 쪽에서 바람이 들어와서 뒤쪽 케이스 밖으로 빼는게 맞을까?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;근데 답을 모르겠어서 그냥 국룰인 2번으로 진행했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/du8Ox7/btsQdZDrUBh/fDN8EMBXFteGG1unbhdEG0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/du8Ox7/btsQdZDrUBh/fDN8EMBXFteGG1unbhdEG0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/du8Ox7/btsQdZDrUBh/fDN8EMBXFteGG1unbhdEG0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdu8Ox7%2FbtsQdZDrUBh%2FfDN8EMBXFteGG1unbhdEG0%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;1536&quot; height=&quot;2048&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;녹투아 쿨러로 장착한 모습.. 이 두개 쿨러가 무슨 5만원이 넘냐고,,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckCtew/btsQcbdOSni/kLAyIrMlh3OX5u4pkzoEx0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckCtew/btsQcbdOSni/kLAyIrMlh3OX5u4pkzoEx0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckCtew/btsQcbdOSni/kLAyIrMlh3OX5u4pkzoEx0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckCtew%2FbtsQcbdOSni%2FkLAyIrMlh3OX5u4pkzoEx0%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;1536&quot; height=&quot;2048&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10기가 멜라녹스도 야무지게 연결해주고 선정리는 대충 해주면 끝. 이러고 벤치마킹 돌리니까&amp;nbsp; 39~42도가 평균적으로 케이스 안에서 진행되고 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;45BC3FB9-2472-4A7E-8044-20160AF926CE_1_102_o.jpeg&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX2cjF/btsQfdHMHjo/oxlcKwHNPkMK8d4DzXERY0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX2cjF/btsQfdHMHjo/oxlcKwHNPkMK8d4DzXERY0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX2cjF/btsQfdHMHjo/oxlcKwHNPkMK8d4DzXERY0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX2cjF%2FbtsQfdHMHjo%2FoxlcKwHNPkMK8d4DzXERY0%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;1536&quot; height=&quot;2048&quot; data-filename=&quot;45BC3FB9-2472-4A7E-8044-20160AF926CE_1_102_o.jpeg&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;2048&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZGnYC/btsQcaFXQ4m/AFpFqU1CqoCsyUCmZw1GBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZGnYC/btsQcaFXQ4m/AFpFqU1CqoCsyUCmZw1GBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZGnYC/btsQcaFXQ4m/AFpFqU1CqoCsyUCmZw1GBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZGnYC%2FbtsQcaFXQ4m%2FAFpFqU1CqoCsyUCmZw1GBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;748&quot; height=&quot;73&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;73&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어 1개 팬으로 버티다 보니까 당연히 온도가 높아져서 뒤질수밖에,,, 그래서 변경하게 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkOilX/btsQc6C7Yql/6ZPTFJK6XcxqWJ8QQmOb70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkOilX/btsQc6C7Yql/6ZPTFJK6XcxqWJ8QQmOb70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkOilX/btsQc6C7Yql/6ZPTFJK6XcxqWJ8QQmOb70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkOilX%2FbtsQc6C7Yql%2F6ZPTFJK6XcxqWJ8QQmOb70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1378&quot; height=&quot;595&quot; data-origin-width=&quot;1378&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드 평균 IDLE에서는 HGST 4TB 모델이 51도, WD 4TB모델이 45도를 유지하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱히 나쁘지 않은듯~ 예쩐엔 파일 조금만 옮겨도 60도 이랬는데 역시 쿨링은 잘해줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>그냥 개발 및 잡담</category>
      <category>8베이 나스</category>
      <category>8베이 서버</category>
      <category>HDD 온도</category>
      <category>녹투아 쿨러</category>
      <category>서버</category>
      <category>자작 나스</category>
      <category>자작 서버</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/575</guid>
      <comments>https://pental.tistory.com/575#entry575comment</comments>
      <pubDate>Sat, 30 Aug 2025 16:08:25 +0900</pubDate>
    </item>
    <item>
      <title>[실버 5] 백준 11723 - 집합 (파이썬)</title>
      <link>https://pental.tistory.com/574</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;962&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AxPAv/btsPRGj3zG9/LWvypudAIKKxVcNZodUlIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AxPAv/btsPRGj3zG9/LWvypudAIKKxVcNZodUlIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AxPAv/btsPRGj3zG9/LWvypudAIKKxVcNZodUlIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAxPAv%2FbtsPRGj3zG9%2FLWvypudAIKKxVcNZodUlIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1416&quot; height=&quot;962&quot; data-origin-width=&quot;1416&quot; data-origin-height=&quot;962&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1755072170560&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 백준 11723 - 집합

import sys
input = lambda: sys.stdin.readline().rstrip()

S = []
M = int(input())
for _ in range(M) :
    line = input().split()
    if len(line) &amp;gt; 1 :
        op = line[0]
        num = int(line[1])

        if op == &quot;add&quot; :
            if num not in S :
                S.append(num)
        elif op == &quot;remove&quot; :
            if num in S :
                S.remove(num)
        elif op == &quot;check&quot; :
            if num in S :
                print(&quot;1&quot;)
            else :
                print(&quot;0&quot;)
        elif op == &quot;toggle&quot; :
            if num in S :
                S.remove(num)
            else :
                S.append(num)
    else :
        op = line[0]
        if op == &quot;all&quot; :
            S = [n for n in range(1, 21)]
        elif op == &quot;empty&quot; :
            S = []&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 11723</category>
      <category>백준 11723 집합</category>
      <category>백준 11723 집합 파이썬</category>
      <category>백준 11723 파이썬</category>
      <category>백준 집합</category>
      <category>백준 집합 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/574</guid>
      <comments>https://pental.tistory.com/574#entry574comment</comments>
      <pubDate>Wed, 13 Aug 2025 17:03:15 +0900</pubDate>
    </item>
    <item>
      <title>백준 5522, 10178, 9295, 10569, 2921 (파이썬)</title>
      <link>https://pental.tistory.com/573</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTMolT/btsPEC25oDq/n7DkReN8ISs7o5LIp42fNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTMolT/btsPEC25oDq/n7DkReN8ISs7o5LIp42fNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTMolT/btsPEC25oDq/n7DkReN8ISs7o5LIp42fNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTMolT%2FbtsPEC25oDq%2Fn7DkReN8ISs7o5LIp42fNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1364&quot; height=&quot;354&quot; data-origin-width=&quot;1364&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;# 백준 5522 - 카드 게임

A = [int(input()) for _ in range(5)]
print(sum(A))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 10178 - 할로윈의 사탕

T = int(input())
for _ in range(T) :
    c, v = map(int, input().split())
    print(f&quot;You get {c // v} piece(s) and your dad gets {c % v} piece(s).&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 9295 - 주사위

T = int(input())
for i in range(T) :
    a, b = map(int, input().split())
    print(f&quot;Case {i + 1}: {a + b}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 10569 - 다면체

T = int(input())
for _ in range(T) :
    V, E = map(int, input().split())
    print(2 - V + E)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;# 백준 2921 - 도미노

N = int(input())
total = 0

for i in range(N + 1):
    for j in range(i, N + 1):
        total += i + j

print(total)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준 10178</category>
      <category>백준 10178 파이썬</category>
      <category>백준 10569</category>
      <category>백준 10569 파이썬</category>
      <category>백준 2921</category>
      <category>백준 2921 파이썬</category>
      <category>백준 5522</category>
      <category>백준 5522 파이썬</category>
      <category>백준 9295</category>
      <category>백준 9295 파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/573</guid>
      <comments>https://pental.tistory.com/573#entry573comment</comments>
      <pubDate>Fri, 1 Aug 2025 16:10:39 +0900</pubDate>
    </item>
    <item>
      <title>[실버 3] 백준 6666 - Help Me with the Game (파이썬)</title>
      <link>https://pental.tistory.com/572</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EUdNf/btsPEO2Efu7/XOUtScg18qKCwo6XOTrmv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EUdNf/btsPEO2Efu7/XOUtScg18qKCwo6XOTrmv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EUdNf/btsPEO2Efu7/XOUtScg18qKCwo6XOTrmv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEUdNf%2FbtsPEO2Efu7%2FXOUtScg18qKCwo6XOTrmv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;684&quot; height=&quot;792&quot; data-origin-width=&quot;684&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/6666&quot;&gt;https://www.acmicpc.net/problem/6666&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제집에서 이거 안풀면 꿈에서 나온다는 말이 있어서 찾아보게된 문제이며, 문제 번호부터가 6666으로 예사롭지가 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 진짜 문제도 예사롭지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력을 한번 봐보자&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;+---+---+---+---+---+---+---+---+
|.r.|:::|.b.|:q:|.k.|:::|.n.|:r:|
+---+---+---+---+---+---+---+---+
|:p:|.p.|:p:|.p.|:p:|.p.|:::|.p.|
+---+---+---+---+---+---+---+---+
|...|:::|.n.|:::|...|:::|...|:p:|
+---+---+---+---+---+---+---+---+
|:::|...|:::|...|:::|...|:::|...|
+---+---+---+---+---+---+---+---+
|...|:::|...|:::|.P.|:::|...|:::|
+---+---+---+---+---+---+---+---+
|:P:|...|:::|...|:::|...|:::|...|
+---+---+---+---+---+---+---+---+
|.P.|:::|.P.|:P:|...|:P:|.P.|:P:|
+---+---+---+---+---+---+---+---+
|:R:|.N.|:B:|.Q.|:K:|.B.|:::|.R.|
+---+---+---+---+---+---+---+---+
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력자체가 조금 빡치게 생겨서 나같은 경우는 &quot;+---+---+---+---+---+---+---+---+&quot; 이친구를 모두 없애고, 1번 위치 부터 -1위치까지 &amp;ldquo;|&amp;rdquo;를 기준으로 나누고, Board에 넣는다. 체스판은 총 17줄이기 때문에 17만큼만 반복문을 구했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 입력 결과&lt;/p&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;|:r:|...|...| &amp;rarr; [':r:', '...', ..., '...']
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬 기준을 설정했다. 정렬 기준은 다음과 같이 설정하였다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;columns = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
priority = {'K' : 0, 'Q' : 1, 'R' : 2, 'B' : 3, 'N' : 4, &quot;P&quot; : 5}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;columns는 열에 대응되는 알파벳 a ~ h를 나타내고, priority는 말의 중요도 순서를 나타내었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위의 경우 출력 시 정렬 기준으로 사용 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;for row in range(8) :
    for col in range(8) :
        cell = board[row][col]
        piece = cell[1]
        if piece == '.' or piece == ':':
            continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백색과 흑색 말의 위치 정보를 따로 저장한다. cell[1]은 :r: 또는 .P. 처럼 가운데 문자를 의미하고, 비어있는 칸은 스킵한다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;        col_letter = columns[col]
        row_number = 8 - row
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행과 열을 체스 기보 표기법 좌표로 변환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예 : e4, Nc6등&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;if piece.isupper() :
    kind = piece
    if kind == 'P' :
        name = f&quot;{col_letter}{row_number}&quot;
    else :
        name = f&quot;{kind}{col_letter}{row_number}&quot;
    white.append((priority[kind], row_number, col_letter, name))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백색 말은 대문자로 이루어져있어서 isupper함수를 통해서 대문자인지 확인하였고, P는 열 + 행, 나머지는 말이름 + 열 + 행으로 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정렬을 하기 위해서 (우선순위, 행번호, 열문자, 기보)를 형식으로 한 튜플로 저장한다.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;else :
    kind = piece.upper()
    if kind == 'P' :
        name = f&quot;{col_letter}{row_number}&quot;
    else :
        name = f&quot;{kind}{col_letter}{row_number}&quot;
    balack.append((priority[kind], -row_number, col_letter, name))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흑색말은 소문자로 이루저여있지에, 소문자에서 대문자로 바꾸어 동일한 포맷을 유지하도록 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행번호는 위에서부터 내려오기 때문에 -row_number로 정렬 방향을 반대로 만들어주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서는 정렬을 해서 출력하라 하였기에 다음과 같이 정렬한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;white.sort()
balack.sort()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# 백준 6666 - Help me With the Game

board = []
for i in range(17) :
    s = input()
    if s != &quot;+---+---+---+---+---+---+---+---+&quot; :
        s = s[1:-1].split(&quot;|&quot;)
        board.append(s)

columns = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
priority = {'K' : 0, 'Q' : 1, 'R' : 2, 'B' : 3, 'N' : 4, &quot;P&quot; : 5}

white = []
balack = []
for row in range(8) :
    for col in range(8) :
        cell = board[row][col]
        piece = cell[1]
        if piece == '.' or piece == ':':
            continue
        col_letter = columns[col]
        row_number = 8 - row

        if piece.isupper() :
            kind = piece
            if kind == 'P' :
                name = f&quot;{col_letter}{row_number}&quot;
            else :
                name = f&quot;{kind}{col_letter}{row_number}&quot;
            white.append((priority[kind], row_number, col_letter, name))
        else :
            kind = piece.upper()
            if kind == 'P' :
                name = f&quot;{col_letter}{row_number}&quot;
            else :
                name = f&quot;{kind}{col_letter}{row_number}&quot;
            balack.append((priority[kind], -row_number, col_letter, name))

white.sort()
balack.sort()

print(&quot;White: &quot; + &quot;,&quot;.join(piece[3] for piece in white))
print(&quot;Black: &quot; + &quot;,&quot;.join(piece[3] for piece in balack))
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 6666</category>
      <category>백준 6666 Help Me with the Game</category>
      <category>백준 6666 Help Me with the Game 파이썬</category>
      <category>백준 6666 파이썬</category>
      <category>백준 Help Me with the Game</category>
      <category>백준 Help Me with the Game 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/572</guid>
      <comments>https://pental.tistory.com/572#entry572comment</comments>
      <pubDate>Thu, 31 Jul 2025 11:19:13 +0900</pubDate>
    </item>
    <item>
      <title>[골드 4] 백준 2661 - 좋은수열 (파이썬)</title>
      <link>https://pental.tistory.com/571</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QESJK/btsPB4zxdh1/myM3KKgUMrHKmlaPDBDvCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QESJK/btsPB4zxdh1/myM3KKgUMrHKmlaPDBDvCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QESJK/btsPB4zxdh1/myM3KKgUMrHKmlaPDBDvCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQESJK%2FbtsPB4zxdh1%2FmyM3KKgUMrHKmlaPDBDvCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1085&quot; height=&quot;477&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;477&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 백트래킹&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/2661&quot;&gt;https://www.acmicpc.net/problem/2661&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 숫자 1, 2, 3 으로만 이루어지는 수열이 있으며, 임의의 길이의 인접한 두 개의 부분 수열이 동일한 것이 있으면, 그 수열은 나쁜 수열이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 수열은 인접한 두 개의 부분 수열이 동일하면 안된다. 즉 1212는 마지막 두자리 12가 반복되므로 나쁜 수열이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길이 N의 좋은 수열 중 사전순으로 가장 앞서는 수열을 찾아야한다.&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;def is_good(seq) :
    length = len(seq)
    for i in range(1, length // 2 + 1) :
        if seq[-i:] == seq[-2 * i : -i] :
            return False
    return True
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 함수는 현재 수열이 좋은 수열인지 판단한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i는 검사할 패턴의 길이, 최대 length // 2 까지만 확인하면 충분하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 123123에서는 뒤에서부터 길이 3까지의 패턴 123을 비교한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;seq[-i:]는 마지막 i개의 문자, seq[-2*i:-i]는 그 앞 i개의 문자를 나타내며, 두부분이 같다면 반복되는 패턴이므로 나쁜수열이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복이 없다면 좋은 수열을 나타낸다.&lt;/p&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;def dfs(seq) :
    global found
    if found : return
    if len(seq) == N :
        print(seq)
        found = True
        return 
    for digit in '123' :
        new_seq = seq + digit
        if is_good(new_seq) :
            dfs(new_seq)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 수열 seq를 기반으로 깊이우선탐색을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수열의 길이가 N이 되면 출력하고 종료하고, 숫자 1, 2, 3을 하나씩 붙여가면서 수열을 확장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;붙였을때 좋은 수열인지 검사 후 통과하면 재귀를 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 어려운 문제인데 이게 어떻게 정답률이 50%..&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;# 백준 2661 - 좋은수열
# 분류 : 백트래킹

N = int(input())

found = False

def is_good(seq) :
    length = len(seq)
    for i in range(1, length // 2 + 1) :
        if seq[-i:] == seq[-2 * i : -i] :
            return False
    return True

def dfs(seq) :
    global found
    if found : return
    if len(seq) == N :
        print(seq)
        found = True
        return 
    for digit in '123' :
        new_seq = seq + digit
        if is_good(new_seq) :
            dfs(new_seq)

dfs(&quot;&quot;)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 2661</category>
      <category>백준 2661 좋은수열</category>
      <category>백준 2661 좋은수열 파이썬</category>
      <category>백준 2661 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 좋은수열</category>
      <category>백준 좋은수열 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/571</guid>
      <comments>https://pental.tistory.com/571#entry571comment</comments>
      <pubDate>Wed, 30 Jul 2025 23:12:25 +0900</pubDate>
    </item>
    <item>
      <title>[yolo11]   YOLO를 활용한 차량 분류 시스템 개발기 (2) - Yolo를 통해 객체 인식하기</title>
      <link>https://pental.tistory.com/570</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.system32.kr/567&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://blog.system32.kr/567&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1753772568329&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[yolo11]   YOLO를 활용한 차량 분류 시스템 개발기 (1) - YOLO란 무엇인가? + labelme 사용법&quot; data-og-description=&quot;블랙박스 영상에는 단순히 사고 장면을 담는 것 이상의 수많은 정보가 들어 있다. 차량의 움직임, 주변 상호, 도로 표시, 다른 차량 정보까지 &amp;mdash; 이것들은 모두 범죄 수사, 보험 분쟁, 운전 패턴 &quot; data-og-host=&quot;blog.system32.kr&quot; data-og-source-url=&quot;https://blog.system32.kr/567&quot; data-og-url=&quot;https://blog.system32.kr/567&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmNBUs/hyZnpNNrp4/OwLiMZKUVzO5iZzwQqOEIK/img.png?width=800&amp;amp;height=482&amp;amp;face=0_0_800_482,https://scrap.kakaocdn.net/dn/bEfPeX/hyZqS16UBi/NKuQKASGJUeVil1rROv5e0/img.png?width=800&amp;amp;height=482&amp;amp;face=0_0_800_482,https://scrap.kakaocdn.net/dn/hvt4R/hyZqPxx0gY/3DJgBkeoSR7vjXvLsSJaA1/img.png?width=1792&amp;amp;height=1081&amp;amp;face=0_0_1792_1081&quot;&gt;&lt;a href=&quot;https://blog.system32.kr/567&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.system32.kr/567&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmNBUs/hyZnpNNrp4/OwLiMZKUVzO5iZzwQqOEIK/img.png?width=800&amp;amp;height=482&amp;amp;face=0_0_800_482,https://scrap.kakaocdn.net/dn/bEfPeX/hyZqS16UBi/NKuQKASGJUeVil1rROv5e0/img.png?width=800&amp;amp;height=482&amp;amp;face=0_0_800_482,https://scrap.kakaocdn.net/dn/hvt4R/hyZqPxx0gY/3DJgBkeoSR7vjXvLsSJaA1/img.png?width=1792&amp;amp;height=1081&amp;amp;face=0_0_1792_1081');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[yolo11]   YOLO를 활용한 차량 분류 시스템 개발기 (1) - YOLO란 무엇인가? + labelme 사용법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;블랙박스 영상에는 단순히 사고 장면을 담는 것 이상의 수많은 정보가 들어 있다. 차량의 움직임, 주변 상호, 도로 표시, 다른 차량 정보까지 &amp;mdash; 이것들은 모두 범죄 수사, 보험 분쟁, 운전 패턴&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.system32.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존글에서는 YOLO를 활용한 차량 분류 시스템 개발 - YOLO가 무엇인지, 그리고 Labelme를 사용해서 Yolo에 적합한 타임의 Dataset으로 변환하는 과정에 관해서 작성했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 게시물에서는 &lt;a href=&quot;https://blog.system32.kr/567&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[yolo11]   YOLO를 활용한 차량 분류 시스템 개발기 (1) - YOLO란 무엇인가? + labelme 사용법&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;1094&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B06IZ/btsPBIW7qr3/spKSNqqCqJMATXLiY9jnp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B06IZ/btsPBIW7qr3/spKSNqqCqJMATXLiY9jnp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B06IZ/btsPBIW7qr3/spKSNqqCqJMATXLiY9jnp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB06IZ%2FbtsPBIW7qr3%2FspKSNqqCqJMATXLiY9jnp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1094&quot; height=&quot;292&quot; data-origin-width=&quot;1094&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만들어 두었던 YOLODataset 폴더를 그대로 사용할 것이며, 필자의 환경은 Apple M2, MPS를 사용해서 진행하며, Python 3.9.6 버전을 사용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 진행전 가상 환경을 구축하고 진행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1753773046333&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pental@pentalui-MacBookAir ultralytics % python3 -m venv yolovenv
pental@pentalui-MacBookAir ultralytics % source yolovenv/bin/activate&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1753772709273&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install ultralytics&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 python pip를 통해서 ultralytics를 설치한다. 설치에는 꽤나 많은 시간이 소요된다.&lt;/p&gt;
&lt;pre id=&quot;code_1753772771843&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import ultralytics
ultralytics.checks()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제대로 설치되었는지 확인하기 위해서 위와 같은 코드를 사용하면 아래와 같이 어떤 버전을 사용하고 있으며 CPU 상태 등을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1SIxf/btsPDZJBOeA/eGZvSKPhK8ZnP8VT1DXGD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1SIxf/btsPDZJBOeA/eGZvSKPhK8ZnP8VT1DXGD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1SIxf/btsPDZJBOeA/eGZvSKPhK8ZnP8VT1DXGD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1SIxf%2FbtsPDZJBOeA%2FeGZvSKPhK8ZnP8VT1DXGD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;968&quot; height=&quot;262&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습은 간단하다. 미리 알아둔 Dataset 경로만 있으면 자동으로 필요한 파일은 다운받고, 학습까지 진행해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1753773261811&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yolo train model=yolo11n.pt data=/Users/pental/Desktop/YOLODataset/dataset.yaml epochs=100 imgsz=640&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습 중간중간에, runs 폴더 내 train 폴더에서 어떻게 학습이 되고 있는지 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2064&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7PDnS/btsPDbxee1y/aCNo0wEYGMfGt9d5Vh7lsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7PDnS/btsPDbxee1y/aCNo0wEYGMfGt9d5Vh7lsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7PDnS/btsPDbxee1y/aCNo0wEYGMfGt9d5Vh7lsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7PDnS%2FbtsPDbxee1y%2FaCNo0wEYGMfGt9d5Vh7lsK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2064&quot; height=&quot;1096&quot; data-origin-width=&quot;2064&quot; data-origin-height=&quot;1096&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;train_batch0.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmYJJo/btsPDXZn9Kk/kCb0eqBB6Aefn9Hn3kkMpk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmYJJo/btsPDXZn9Kk/kCb0eqBB6Aefn9Hn3kkMpk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmYJJo/btsPDXZn9Kk/kCb0eqBB6Aefn9Hn3kkMpk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmYJJo%2FbtsPDXZn9Kk%2FkCb0eqBB6Aefn9Hn3kkMpk%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;1920&quot; height=&quot;1920&quot; data-filename=&quot;train_batch0.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;labels.jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;1600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWCmp4/btsPB2HObRM/dbrKzH3pyy41ZjoRg7Z2y1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWCmp4/btsPB2HObRM/dbrKzH3pyy41ZjoRg7Z2y1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWCmp4/btsPB2HObRM/dbrKzH3pyy41ZjoRg7Z2y1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWCmp4%2FbtsPB2HObRM%2FdbrKzH3pyy41ZjoRg7Z2y1%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;1600&quot; height=&quot;1600&quot; data-filename=&quot;labels.jpg&quot; data-origin-width=&quot;1600&quot; data-origin-height=&quot;1600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학습이 완료되면, runs 폴더 아래 train의 마지막 폴더에 weights 폴더가 존재한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsJRUW/btsPC4LFcY9/0RFdB8Y61cDRI7udrdnfLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsJRUW/btsPC4LFcY9/0RFdB8Y61cDRI7udrdnfLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsJRUW/btsPC4LFcY9/0RFdB8Y61cDRI7udrdnfLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsJRUW%2FbtsPC4LFcY9%2F0RFdB8Y61cDRI7udrdnfLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;766&quot; height=&quot;290&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 폴더안에는 best.pt와 last.pt가 존재하며, 여기서 우리가 사용할 것은 best.pt이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8bzCH/btsPDMcFuD9/XMtUfuFhrLW1YUco0m1KI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8bzCH/btsPDMcFuD9/XMtUfuFhrLW1YUco0m1KI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8bzCH/btsPDMcFuD9/XMtUfuFhrLW1YUco0m1KI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8bzCH%2FbtsPDMcFuD9%2FXMtUfuFhrLW1YUco0m1KI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;760&quot; height=&quot;114&quot; data-origin-width=&quot;760&quot; data-origin-height=&quot;114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 예측을 진행해야 한다. 예측은 다음과 같은 커맨드 라인으로 진행 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1753773458692&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yolo predict model=best.pt source=input.mp4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 작업이 완료되면, runs 폴더 아래 predict 폴더가 생성된다. 해당 파일은 아까 학습시킨 모델로 예측이 진행된 결과물이 들어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3164&quot; data-origin-height=&quot;1880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AeDqc/btsPDF5JUtO/Oipk6DphtEoJMvD1NMosZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AeDqc/btsPDF5JUtO/Oipk6DphtEoJMvD1NMosZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AeDqc/btsPDF5JUtO/Oipk6DphtEoJMvD1NMosZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAeDqc%2FbtsPDF5JUtO%2FOipk6DphtEoJMvD1NMosZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3164&quot; height=&quot;1880&quot; data-origin-width=&quot;3164&quot; data-origin-height=&quot;1880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3164&quot; data-origin-height=&quot;1880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vZIrO/btsPCUoYarH/PKzEcKGhZNGaYSPEiXAmIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vZIrO/btsPCUoYarH/PKzEcKGhZNGaYSPEiXAmIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vZIrO/btsPCUoYarH/PKzEcKGhZNGaYSPEiXAmIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvZIrO%2FbtsPCUoYarH%2FPKzEcKGhZNGaYSPEiXAmIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3164&quot; height=&quot;1880&quot; data-origin-width=&quot;3164&quot; data-origin-height=&quot;1880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예측 결과가 나오긴 했지만, &lt;/span&gt;&lt;b&gt;아직은 아쉬운 점이 많았다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 테스트해본 결과, 오탐(false positive)도 많고, 미탐(false negative)도 상당히 많아 개선이 필요해 보였다. 특히 비슷한 차량 외형 간 구분이 제대로 되지 않거나, 일부 프레임에서는 객체를 전혀 인식하지 못하는 경우도 발생했다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해선 다음과 같은 부분에 대한 추가 고민이 필요할 것 같다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;끝날 때까지 끝난 게 아니다.&lt;br /&gt;YOLO 프로젝트는 계속됩니다...&lt;/blockquote&gt;</description>
      <category>이것저것</category>
      <category>yolo</category>
      <category>yolo 사용법</category>
      <category>yolo 인식</category>
      <category>객체인식</category>
      <category>번호판인식</category>
      <category>차량인식</category>
      <category>파이썬</category>
      <category>파이썬 객체인식</category>
      <category>파이썬 머신러닝</category>
      <category>파이썬 영상분석</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/570</guid>
      <comments>https://pental.tistory.com/570#entry570comment</comments>
      <pubDate>Tue, 29 Jul 2025 16:23:42 +0900</pubDate>
    </item>
    <item>
      <title>[실버 2] 백준 11279 - 최대 힙 (파이썬)</title>
      <link>https://pental.tistory.com/569</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lH0lB/btsPDXkLTSK/o6G14UB15IKzW1fKsThMkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lH0lB/btsPDXkLTSK/o6G14UB15IKzW1fKsThMkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lH0lB/btsPDXkLTSK/o6G14UB15IKzW1fKsThMkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlH0lB%2FbtsPDXkLTSK%2Fo6G14UB15IKzW1fKsThMkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;468&quot; height=&quot;250&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 자료구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/11279&quot;&gt;https://www.acmicpc.net/problem/11279&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준 1927과 비슷한 문제이다. 1927 최소 힙 문제에서는 정석대로 heap에 값을 양수로 넣었지만, 이번 문제는 최대 힙을 구하는 문제이기에, -를 붙여서 음수로 넣어주면 힙에서는 최대 힙으로 정렬되게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 문제점은 pop 할때도 음수로 나오기에, 다시한번 -를 붙여주면, 최대 힙으로 출력 할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;# 백준 11729 - 최대 힙

import heapq
import sys

input = sys.stdin.readline
N = int(input())
heap = []

for i in range(N) :
    x = int(input())
    if x == 0 :
        if len(heap) &amp;gt; 0 :
            print(-heapq.heappop(heap))
        else :
            print(0)
    else :
        heapq.heappush(heap, -x)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 11279</category>
      <category>백준 11279 파이썬</category>
      <category>백준 11729 최대 힙 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 최대 힙</category>
      <category>백준 최대 힙 파이썬</category>
      <category>백준 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/569</guid>
      <comments>https://pental.tistory.com/569#entry569comment</comments>
      <pubDate>Tue, 29 Jul 2025 15:52:07 +0900</pubDate>
    </item>
    <item>
      <title>[실버 2] 백준 1927 - 최소 힙 (파이썬)</title>
      <link>https://pental.tistory.com/568</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SXebL/btsPBl8WtUN/jOz9D3cy2WVcNyX0VwB8KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SXebL/btsPBl8WtUN/jOz9D3cy2WVcNyX0VwB8KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SXebL/btsPBl8WtUN/jOz9D3cy2WVcNyX0VwB8KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSXebL%2FbtsPBl8WtUN%2FjOz9D3cy2WVcNyX0VwB8KK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1398&quot; height=&quot;436&quot; data-origin-width=&quot;1398&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 자료구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/1927&quot;&gt;https://www.acmicpc.net/problem/1927&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙의 기초적인 문제이다. 사실 시간초과가 나긴했는데, sys.stdin.readline을 고려하지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서는 N이 최대 10만개이기 때문에 단순히 input()으로만으로는 당연히 시간 초과가 날 수 밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에서 N을 입력받고, 다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 X가 주어진다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;X가 0이 아닌 경우에는 배열에 자연수 X를 넣고, 0이라면 배열에서 가장 작은 값을 출력하고, 그 값을 배열에서 제거하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 적합한 자료구조는 heap이기에 아래와 같은 코드로 작성하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;# 백준 1927 - 최소 힙

import heapq
import sys

input = sys.stdin.readline
N = int(input())
heap = []

for i in range(N) :
    x = int(input())
    if x == 0 :
        if len(heap) &amp;gt; 0 :
            print(heapq.heappop(heap))
        else :
            print(0)
    else :
        heapq.heappush(heap, x)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1927</category>
      <category>백준 1927 최소 힙 파이썬</category>
      <category>백준 1927 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 최소 힙</category>
      <category>백준 최소 힙 파이썬</category>
      <category>백준 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/568</guid>
      <comments>https://pental.tistory.com/568#entry568comment</comments>
      <pubDate>Tue, 29 Jul 2025 15:47:26 +0900</pubDate>
    </item>
    <item>
      <title>[yolo11]   YOLO를 활용한 차량 분류 시스템 개발기 (1) - YOLO란 무엇인가? + labelme 사용법</title>
      <link>https://pental.tistory.com/567</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;블랙박스 영상에는 단순히 사고 장면을 담는 것 이상의 &lt;span&gt;&lt;b&gt;수많은 정보&lt;/b&gt;&lt;/span&gt;가 들어 있다. 차량의 움직임, 주변 상호, 도로 표시, 다른 차량 정보까지 &amp;mdash; 이것들은 모두 &lt;span&gt;&lt;b&gt;범죄 수사&lt;/b&gt;&lt;/span&gt;, &lt;span&gt;&lt;b&gt;보험 분쟁&lt;/b&gt;&lt;/span&gt;, &lt;span&gt;&lt;b&gt;운전 패턴 분석&lt;/b&gt;&lt;/span&gt; 등 다양한 분야에서 활용될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서는 이러한 영상 정보들을 좀 더 &lt;span&gt;&lt;b&gt;정형화된 데이터로 추출&lt;/b&gt;&lt;/span&gt;하여 분석하기 위해 여러 기능들을 구현하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그중 첫 번째는 가장 기본적이면서도 강력한 기능, 바로 &lt;span&gt;&lt;b&gt;차량 분류 시스템&lt;/b&gt;이&lt;/span&gt;다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  차량 분류 시스템이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 내가 주차 중 누군가의 차량에 의해 긁히는 뺑소니를 당했는데, 블랙박스 영상에는 차량의 &lt;span&gt;&lt;b&gt;외형&lt;/b&gt;&lt;/span&gt;만 찍혔다고 가정해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 경우, &lt;span&gt;&lt;b&gt;차량 종류(승용차, SUV, 트럭 등)&lt;/b&gt;&lt;/span&gt; 만 알아도 용의 차량을 좁히는 데 큰 도움이 될거로 추정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 기능을 구현하기 위해 선택한 기술이 바로 YOLO (You Only Look Once)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;  YOLO란 무엇인가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YOLO(You Only Look Once)는 객체 탐지(Object Detection) 분야에서 가장 널리 쓰이는 딥러닝 모델 중 하나이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기존의 이미지 분류 모델과 달리, &lt;/span&gt;&lt;b&gt;YOLO는 이미지 안에 있는 객체들의 위치와 종류를 한 번에 예측&lt;/b&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;YOLO를 사용해보기 전에 블랙박스 영상의 샘플을 구해, 5분짜리 영상에서 1초 간격으로 총 300개의 이미지를 만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;영상을 이미지로 만드는 것은 ffmpeg를 사용해 영상 -&amp;gt; 이미지로 변환하였다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1753528217235&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ffmpeg -i input.mp4 -vf fps=1 output_%04d.jpg&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W9bBZ/btsPAgfuVZl/f5LYuHYP5UzyYOmh09zSY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W9bBZ/btsPAgfuVZl/f5LYuHYP5UzyYOmh09zSY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W9bBZ/btsPAgfuVZl/f5LYuHYP5UzyYOmh09zSY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW9bBZ%2FbtsPAgfuVZl%2Ff5LYuHYP5UzyYOmh09zSY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;548&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 만들어진 이미지에 객체를 학습하기 위해서 labelme 도구를 사용한다. 설치 방법과 실행은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Labelme는 이미지에 객체의 경계 박스를 그리거나 폴리곤 형태로 라벨링할 수 있는 &lt;span&gt;&lt;b&gt;Python 기반의 시각적 어노테이션 툴&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 방법과 실행은 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1753528297142&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install labelme&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 가상환경을 사용하는 경우&lt;/p&gt;
&lt;pre id=&quot;code_1753528307964&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;conda create --name labelme_env python=3.8
conda activate labelme_env
pip install labelme&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;설치가 완료되면 단순히 터미널에서 다음과 같이 실행하면, labelme가 실행된다.&lt;/p&gt;
&lt;pre id=&quot;code_1753528329923&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;labelme&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;labelme가 실행되면 좌측 상단에서 이미지 샘플들을 불러올 수 있다. 단일 파일의 경우 Open File, 디렉터리에 있는 모든 이미지를 가져오려면 Open Dir을 클릭하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRJqYX/btsPAUCJHwr/BB6aizWpDEgLHKFQTALVc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRJqYX/btsPAUCJHwr/BB6aizWpDEgLHKFQTALVc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRJqYX/btsPAUCJHwr/BB6aizWpDEgLHKFQTALVc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRJqYX%2FbtsPAUCJHwr%2FBB6aizWpDEgLHKFQTALVc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1792&quot; height=&quot;1081&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자 같은 경우는 sample 폴더를 선택해, 300장의 이미지를 모두 탑재했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MItW7/btsPBKe36Fw/YkhIEmTVoDHCBcyz3SpUW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MItW7/btsPBKe36Fw/YkhIEmTVoDHCBcyz3SpUW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MItW7/btsPBKe36Fw/YkhIEmTVoDHCBcyz3SpUW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMItW7%2FbtsPBKe36Fw%2FYkhIEmTVoDHCBcyz3SpUW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1792&quot; height=&quot;1081&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진은 이미 Polygon을 생성한 상태이고, Create Polygon 기능을 통해서 원하는 위치에 객체를 인식시킨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOjW6N/btsPBlNnVRl/7So9k2iO5lKitcTgf8hbeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOjW6N/btsPBlNnVRl/7So9k2iO5lKitcTgf8hbeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOjW6N/btsPBlNnVRl/7So9k2iO5lKitcTgf8hbeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOjW6N%2FbtsPBlNnVRl%2F7So9k2iO5lKitcTgf8hbeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1792&quot; height=&quot;1081&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1081&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 원하는 영역에 Polygon을 생성하고, 최초 점 위치를 클릭하면 다음과 같이 라벨링을 지정할 수 있는 창이 확인된다.&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;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xr9Uv/btsPzFUdgok/LIEpPTerK4EdnepIlcxLoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xr9Uv/btsPzFUdgok/LIEpPTerK4EdnepIlcxLoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xr9Uv/btsPzFUdgok/LIEpPTerK4EdnepIlcxLoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxr9Uv%2FbtsPzFUdgok%2FLIEpPTerK4EdnepIlcxLoK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;453&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 도로 내 점선을 인식시켰기 때문에, road_dotted_line으로 이름을 붙여주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 사진으로 넘어가기 위해서는 키보드에서 A 나 D를 통해서 이전, 다음 이미지로 넘어 갈 수 있다. 또는 아래 버튼을 클릭 하면 이전, 다음 이미지로 넘어갈 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;188&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XyoEU/btsPB63hDEw/QKm2aV1qBV9P8cZRWJSmCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XyoEU/btsPB63hDEw/QKm2aV1qBV9P8cZRWJSmCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XyoEU/btsPB63hDEw/QKm2aV1qBV9P8cZRWJSmCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXyoEU%2FbtsPB63hDEw%2FQKm2aV1qBV9P8cZRWJSmCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;188&quot; height=&quot;88&quot; data-origin-width=&quot;188&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;300장의 이미지에서 일부 필요한 정보를 추출하여 &lt;s&gt;노가다&lt;/s&gt;를 진행한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1082&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PzYK2/btsPBI9nfdQ/4SnvIO6ApS0DHbAYjskJfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PzYK2/btsPBI9nfdQ/4SnvIO6ApS0DHbAYjskJfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PzYK2/btsPBI9nfdQ/4SnvIO6ApS0DHbAYjskJfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPzYK2%2FbtsPBI9nfdQ%2F4SnvIO6ApS0DHbAYjskJfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1792&quot; height=&quot;1082&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1082&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1082&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQScTN/btsPzEudftj/dx9vu63THnkaEK44JyYSe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQScTN/btsPzEudftj/dx9vu63THnkaEK44JyYSe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQScTN/btsPzEudftj/dx9vu63THnkaEK44JyYSe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQScTN%2FbtsPzEudftj%2Fdx9vu63THnkaEK44JyYSe0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1792&quot; height=&quot;1082&quot; data-origin-width=&quot;1792&quot; data-origin-height=&quot;1082&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노가다가 완료 되면, 샘플 이미지 파일 및 아까 마스킹 한 json 파일이 잘 저장되었는지 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nG7ie/btsPAKmzf4S/H86mQ1vBVY28fZaqdLibxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nG7ie/btsPAKmzf4S/H86mQ1vBVY28fZaqdLibxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nG7ie/btsPAKmzf4S/H86mQ1vBVY28fZaqdLibxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnG7ie%2FbtsPAKmzf4S%2FH86mQ1vBVY28fZaqdLibxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;548&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;labelme 같은 경우는 json으로 반환해주는데, yolo에서 필요한 정보는 txt파일 형태로 되어 있어야 하기에, labelme2yolo를 통해서 yolo가 인식 할 수 있도록 변환해 주어야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1753528681710&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pip install labelme2yolo&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1753528694592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pental@pentalui-MacBookAir BLACKBOX % labelme2yolo --json_dir sample --val_size 0.15 --test_size 0.15&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 사용한 명령줄은 위와 같으며, 실행 시키면 다음과 같이 진행되는것을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rpilt/btsPBlzP6Jd/kNYxsgLKZW66tWCkhXPPyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rpilt/btsPBlzP6Jd/kNYxsgLKZW66tWCkhXPPyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rpilt/btsPBlzP6Jd/kNYxsgLKZW66tWCkhXPPyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRpilt%2FbtsPBlzP6Jd%2FkNYxsgLKZW66tWCkhXPPyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;719&quot; height=&quot;102&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;102&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lASqR/btsPAxVmzIJ/kw5jOy1n5zdtP1TsoUJEUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lASqR/btsPAxVmzIJ/kw5jOy1n5zdtP1TsoUJEUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lASqR/btsPAxVmzIJ/kw5jOy1n5zdtP1TsoUJEUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlASqR%2FbtsPAxVmzIJ%2Fkw5jOy1n5zdtP1TsoUJEUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;47&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지정한 경로에서 YOLODataset 폴더가 생성된 것을 확인 할 수 있고, 해당 폴더는 아래 사진과 같은 구조를 가지고 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NhO6X/btsPBGRgI2X/KYfFYLgKXUrsPKDNnoYjdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NhO6X/btsPBGRgI2X/KYfFYLgKXUrsPKDNnoYjdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NhO6X/btsPBGRgI2X/KYfFYLgKXUrsPKDNnoYjdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNhO6X%2FbtsPBGRgI2X%2FKYfFYLgKXUrsPKDNnoYjdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;752&quot; height=&quot;158&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV5vuU/btsPAYkF10k/GzzxFtmqetpiK3pMBxtnP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV5vuU/btsPAYkF10k/GzzxFtmqetpiK3pMBxtnP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV5vuU/btsPAYkF10k/GzzxFtmqetpiK3pMBxtnP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV5vuU%2FbtsPAYkF10k%2FGzzxFtmqetpiK3pMBxtnP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;548&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;548&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 json에서 txt로 변환 된 것을 확인 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음편에서는 생성한 마스킹 정보를 바탕으로 yolo 학습 및 예측을 포스팅 할 예정이다.&lt;/p&gt;</description>
      <category>이것저것</category>
      <category>Labelme</category>
      <category>labelme 사용방법</category>
      <category>labelme 사용법</category>
      <category>labelme2yolo</category>
      <category>python 객체인식</category>
      <category>yolo</category>
      <category>yolo json에서 txt로 변환</category>
      <category>yolo 사용방법</category>
      <category>yolo 사용법</category>
      <category>객체인식</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/567</guid>
      <comments>https://pental.tistory.com/567#entry567comment</comments>
      <pubDate>Sat, 26 Jul 2025 20:21:46 +0900</pubDate>
    </item>
    <item>
      <title>[골드 3] 백준 16957 - 체스판 위의 공 (파이썬)</title>
      <link>https://pental.tistory.com/566</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FM1c5/btsPqnyKG2F/nRm5444NkKlZ4v0WusIb40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FM1c5/btsPqnyKG2F/nRm5444NkKlZ4v0WusIb40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FM1c5/btsPqnyKG2F/nRm5444NkKlZ4v0WusIb40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFM1c5%2FbtsPqnyKG2F%2FnRm5444NkKlZ4v0WusIb40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2366&quot; height=&quot;1176&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1176&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : DFS&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/16957&quot;&gt;https://www.acmicpc.net/problem/16957&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 공이 어디로 떨어지는가가 아니라 각 골짜기로 얼마나 많은 공이 모이는가를 역방향으로 계산한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 칸에서 인접한 8방향 중 가장 낮은 칸으로 공이 흘러간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 흐름을 역방향 그래프로 만들어 두고, 실제로 공이 도달할 수 있는 최종 지점부터 시작해서, 역으로 DFS를 돌며 얼마나 많은 공이 이 칸으로 오는지 세는 방식이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;입력 처리&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;R, C = map(int, input().split())
B = [list(map(int, input().split())) for _ in range(R)]

dr = [0, 0, 1, 1, 1, -1, -1, -1]
dc = [1, -1, -1, 0, 1, -1, 0, 1]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B[r][c]는 r행 c열의 높이값을 나타내며, dr, dc는 8방향 이동을 위한 델타값이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;흐름을 반대로 저장할 adj를 선언한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;adj = {(r, c) : [] for r in range(R) for c in range(C)}
valley = []
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adj[(r, c)]는 이 칸으로 공이 도달하는 출발 위치 리스트를 나타내며, valley의 경우 더 낮은 인접같이 없어 공이 머무르게 되는 칸을 나타낸다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;흐름 경로 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;for r in range(R):
    for c in range(C):
        min_val = B[r][c]
        who = (-1, -1)
        for i in range(8):
            nr, nc = r + dr[i], c + dc[i]
            if 0 &amp;lt;= nr &amp;lt; R and 0 &amp;lt;= nc &amp;lt; C and B[nr][nc] &amp;lt; min_val:
                min_val = B[nr][nc]
                who = (nr, nc)
        
        if who != (-1, -1):
            adj[who].append((r, c))
        else:
            valley.append((r, c))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 칸 (r, c)에서 가장 낮은 인접 칸 (nr, nc)를 찾고, 더 낮은 칸이 있으면 (nr, nc)로 공이 흐르므로 adj[(nr, nc)]에 (r, c)를 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 없는 경우 골짜기로 간주한다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;def dfs(r, c):
    global count
    count += 1
    for (nr, nc) in adj[(r, c)]:
        dfs(nr, nc)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역방향 DFS로써, 현재 valley에서 이 칸으로 유입되는 모든 칸들을 방문하며, count에 누적한다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;for vr, vc in valley:
    count = 0
    dfs(vr, vc)
    answer[vr][vc] = count
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 골짜기마다 DFS를 실행해 얼마나 많은 공이 이 골짜기로 모이는지 카운트 하고, 그 수를 answer[vr][vc]에 기록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이 풀이의 문제점은 중복 방문이 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 (2, 2)가 여러 valley에 도달하는 경로 중 중복으로 포함되면, DFS에서 여러번 방문하게 되고, 결과적으로 전체 공 개수가 맞지 않게 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 백준 16957 - 체스판 위의 공
# 분류 : DFS

from collections import deque

R, C = map(int, input().split())
B = [list(map(int, input().split())) for _ in range(R)]

adj = {(r, c) : [] for r in range(R) for c in range(C)}

dr = [0, 0, 1, 1, 1, -1, -1, -1]
dc = [1, -1, -1, 0, 1, -1, 0, 1]

valley = []

for r in range(R) :
    for c in range(C) :
        min_val = B[r][c]
        who = (-1, -1)
        for i in range(8) :
            nr, nc = r + dr[i], c + dc[i]
            if nr &amp;lt; 0 or R &amp;lt;= nr or nc &amp;lt; 0 or C &amp;lt;= nc :
                continue

            if min_val &amp;gt; B[nr][nc] :
                min_val = B[nr][nc]
                who = (nr, nc)
        
        if who != (-1, -1) :
            adj[who].append((r, c))
        else :
            valley.append((r, c))

count = 0

def dfs(r, c) :
    global count
    count += 1

    for (nr, nc) in adj[(r, c)] :
        dfs(nr, nc)
    
answer = [[0] * C for _ in range(R)]

for vr, vc in valley :
    count = 0
    dfs(vr, vc)
    answer[vr][vc] = count
    
for i in range(R) :
    print(*answer[i])
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 16957</category>
      <category>백준 16957 체스판 위의 공</category>
      <category>백준 16957 체스판 위의 공 파이썬</category>
      <category>백준 16957 파이썬</category>
      <category>백준 체스판 위의 공</category>
      <category>백준 체스판 위의 공 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/566</guid>
      <comments>https://pental.tistory.com/566#entry566comment</comments>
      <pubDate>Mon, 21 Jul 2025 09:46:05 +0900</pubDate>
    </item>
    <item>
      <title>[실버 4] 백준 25214 - 크림 파스타 (파이썬)</title>
      <link>https://pental.tistory.com/565</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;459&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btvc3n/btsPpQnpfzI/EGSYWcKlNfIr9eTlOdALv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btvc3n/btsPpQnpfzI/EGSYWcKlNfIr9eTlOdALv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btvc3n/btsPpQnpfzI/EGSYWcKlNfIr9eTlOdALv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtvc3n%2FbtsPpQnpfzI%2FEGSYWcKlNfIr9eTlOdALv1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1180&quot; height=&quot;459&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;459&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 다이나믹 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/25214&quot;&gt;https://www.acmicpc.net/problem/25214&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 인덱스 i에 대해, D[i]는 A[0]부터 A[i]까지의 &lt;b&gt;최솟값,&lt;/b&gt; E[i]는 E[i-1]과 (A[i] - D[i]) 중 &lt;b&gt;더 큰 값이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, E[i]는 &lt;b&gt;앞에서부터 지금까지의 최댓값을 유지하면서&lt;/b&gt;, A[i]에서 이전까지의 최솟값을 뺀 값 중 최대를 갱신한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;D = [0] * N
E = [0] * N
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D[i]는 A[0] ~ A[i] 중 최솟값을 나타내고, E[i]는 지금까지의 A[i] - D[i] 중 최대를 나타낸다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;D[0] = A[0]
for i in range(1, N) :
    D[i] = min(D[i - 1], A[i])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최솟값 갱신은 위와 같이 작성하며, D[i]는 A[0] ~ A[i]에서의 최솟값을 저장한다.&lt;/p&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;E[0] = 0
for i in range(1, N) :
    E[i] = max(E[i - 1], A[i] - D[i])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E[i]는 이전 최댓값과 현재 A[i] - D[i] 값 중 큰 것을 유지한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 백준 25214 - 크림 파스타
# 분류 : 다이나믹 프로그래밍

N = int(input())
A = list(map(int, input().split()))

D = [0] * N
E = [0] * N

D[0] = A[0]
for i in range(1, N) :
    D[i] = min(D[i - 1], A[i])

E[0] = 0
for i in range(1, N) :
    E[i] = max(E[i - 1], A[i] - D[i])

print(*E)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 25214</category>
      <category>백준 25214 크림 파스타</category>
      <category>백준 25214 크림 파스타 파이썬</category>
      <category>백준 25214 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 크림 파스타</category>
      <category>백준 크림 파스타 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/565</guid>
      <comments>https://pental.tistory.com/565#entry565comment</comments>
      <pubDate>Sun, 20 Jul 2025 13:19:15 +0900</pubDate>
    </item>
    <item>
      <title>[골드 1] 백준 1311 - 할 일 정하기 1 (파이썬)</title>
      <link>https://pental.tistory.com/564</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W638V/btsPqK7wyCM/8lvO4LAUx1FNCNqfqDorn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W638V/btsPqK7wyCM/8lvO4LAUx1FNCNqfqDorn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W638V/btsPqK7wyCM/8lvO4LAUx1FNCNqfqDorn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW638V%2FbtsPqK7wyCM%2F8lvO4LAUx1FNCNqfqDorn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1171&quot; height=&quot;428&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;428&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 다이나믹 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/1311&quot;&gt;https://www.acmicpc.net/problem/1311&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 N * N 크기의 비용 행렬 D가 주어지고, 사람 N명에게 각각 하나의 일을 배정하는데, 각 사람마다 각 일에 대한 비용이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 사람에게 정확히 하나의 일만, 각 일도 정확히 한 사람에게만 배정되도록 하면서 총 비용의 합을 최소화 해야한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;초기 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;cache = [[-1] * (2 ** N) for _ in range(N)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cache[x][mask]는 x번째 사람까지 할당했을 때, mask 상태에서의 최소 비용을 저장한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;기저 조건&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;if x == 0:
    for i in range(N):
        if mask == (2 ** i):
            cache[x][mask] = D[x][i]
            return D[x][i]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 사람에게 일을 한 개만 할당한 경우 해당 비용을 바로 반환한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;재귀적으로 최소 비용을 계산&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;llvm&quot;&gt;&lt;code&gt;for i in range(N):
    if mask &amp;amp; (2 ** i) != 0:
        ret = min(ret, D[x][i] + dp(x - 1, mask - (2 ** i)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 x번째 사람에게 i번째 일을 배정할 수 있는 경우에 대해, 그 비용과 이전 상태의 최소 비용을 더해서 ret를 갱신한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;결과 반환&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;return dp(N - 1, (2 ** N) - 1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람 N명을 모두 배정한 경우, 모든 일이 사용되었을 때의 최소 비용을 출력한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 1311 - 할 일 정하기 1
# 분류 : 다이나믹 프로그래밍
import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline
N = int(input())
D = [list(map(int, input().split())) for _ in range(N)]

cache = [[-1] * (2 ** N) for _ in range(N)]
# N * (2 ^ N)
def dp(x, mask) :
    if cache[x][mask] != -1 :
        return cache[x][mask]

    if x == 0 :
        for i in range(N) :
            if mask == (2 ** i) :
                cache[x][mask] = D[x][i]
                return D[x][i]
    
    ret = 1e9
    for i in range(N) :
        if mask &amp;amp; (2 ** i) != 0 :
            ret = min(ret, D[x][i] + dp(x - 1, mask - (2 ** i)))
        
    cache[x][mask] = ret
    return ret
    
print(dp(N - 1, (2 ** N) - 1))
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1311</category>
      <category>백준 1311 파이썬</category>
      <category>백준 1311 할 일 정하기 1</category>
      <category>백준 1311 할 일 정하기 1 파이썬</category>
      <category>백준 할 일 정하기 1</category>
      <category>백준 할 일 정하기 1 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/564</guid>
      <comments>https://pental.tistory.com/564#entry564comment</comments>
      <pubDate>Sat, 19 Jul 2025 13:41:13 +0900</pubDate>
    </item>
    <item>
      <title>[골드 3] 백준 7579 - 앱 (파이썬)</title>
      <link>https://pental.tistory.com/563</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ywDEr/btsPpo5ylM0/YxDk4jJAkxFIPt5lRbEqs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ywDEr/btsPpo5ylM0/YxDk4jJAkxFIPt5lRbEqs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ywDEr/btsPpo5ylM0/YxDk4jJAkxFIPt5lRbEqs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FywDEr%2FbtsPpo5ylM0%2FYxDk4jJAkxFIPt5lRbEqs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1205&quot; height=&quot;675&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 다이나믹 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/7579&quot;&gt;https://www.acmicpc.net/problem/7579&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 확보를 위해서 필요한 최소 비용을 구하는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 N개가 있고, 각각 메모리 m[i], 비용 c[i]를 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 확보해야 할 메모리는 M보다 크거나 같으며, 비용의 합이 최소가 되도록 하는 앱을 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DP 테이블은 다음과 같이 정의한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;D = [[0] * 10001 for _ in range(N)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D[i][j]는 i번 앱까지 고려했을 때, 비용 j 이하로 확보 가능한 최대 메모리를 나타내며, 비용 최대치가 10000이므로 열 크기를 10001로 설정한다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;# D[0][i] : 첫 번째 앱만 사용할 때의 최대 메모리
for i in range(c[0], 10001) :
    D[0][i] = m[0]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기화는 첫 앱의 비용보다 크거나 같은 비용 i에 대해서 m[0]만큼 확보가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점화식은 다음과 같이 구성한다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;for i in range(1, N) :
    for j in range(10001) :
        D[i][j] = D[i - 1][j]  # i번째 앱을 쓰지 않았을 때

        if j &amp;gt;= c[i] :
            # i번째 앱을 사용하는 경우와 비교하여 더 큰 메모리 확보
            D[i][j] = max(D[i][j], m[i] + D[i - 1][j - c[i]])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i번째 앱을 사용하지 않는 경우는 이전 상태를 그대로 유지하고, i번째 앱을 사용하는 경우 이전상태에서 비용 c[i]를 줄이고, 메모리 m[i]를 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 최소 비용을 탐색한다.&lt;/p&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;for i in range(10001) :
    if D[N - 1][i] &amp;gt;= M :
        print(i)
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 행에서 메모리 &amp;ge; M을 만족하는 가장 작은 비용 i를 출력한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;# 백준 7579 - 앱
# 분류 : 다이나믹 프로그래밍

N, M = map(int, input().split())
m = list(map(int, input().split()))
c = list(map(int, input().split()))

D = [[0] * 10001 for _ in range(N)]

# D[0][i], i &amp;lt; c[0] -&amp;gt; 0, i &amp;gt;= c[0] -&amp;gt; m[0]
for i in range(c[0], 10001) :
    D[0][i] = m[0]

for i in range(1, N) :
    for j in range(10001) :
        D[i][j] = D[i - 1][j]

        if j &amp;gt;= c[i] :
            D[i][j] = max(D[i][j], m[i] + D[i - 1][j - c[i]])

for i in range(10001) :
    if D[N - 1][i] &amp;gt;= M :
        print(i)
        break
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 7579</category>
      <category>백준 7579 앱</category>
      <category>백준 7579 앱 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 앱</category>
      <category>백준 앱 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/563</guid>
      <comments>https://pental.tistory.com/563#entry563comment</comments>
      <pubDate>Fri, 18 Jul 2025 18:28:36 +0900</pubDate>
    </item>
    <item>
      <title>[골드 5] 백준 11578 - 팀원 모집 (파이썬)</title>
      <link>https://pental.tistory.com/562</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2394&quot; data-origin-height=&quot;1404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gvhyu/btsPn5J9ajg/YAiVkjoDlmdSJpOz7MigW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gvhyu/btsPn5J9ajg/YAiVkjoDlmdSJpOz7MigW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gvhyu/btsPn5J9ajg/YAiVkjoDlmdSJpOz7MigW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGvhyu%2FbtsPn5J9ajg%2FYAiVkjoDlmdSJpOz7MigW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2394&quot; height=&quot;1404&quot; data-origin-width=&quot;2394&quot; data-origin-height=&quot;1404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 브루트포스 + 자료구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/11578&quot;&gt;https://www.acmicpc.net/problem/11578&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번부터 N번까지의 문제를 모두 풀 수 있는 최소한의 팀원수를 구하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 팀원은 자신이 풀 수 있는 문제 번호 리스트를 가지고 있다. 팀원은 M명이며, 문제를 모두 풀 수 있는 팀원의 최소 수를 구해야한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;A = [list(map(int, input().split()))[1:] for _ in range(M)]
A = [set(a) for a in A]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 팀원이 자신이 풀 수 있는 문제 번호들을 입력받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;list(map(int, input().split()))[1:] 에서 [1:] 부터 시작하는 이유는 첫 번째 숫자는 개수이므로 무시한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;set(a)로 변환해서 나중에 합집한 연산을 쉽게 수행하도록 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;4 3
2 1 2
2 3 4
1 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A = [{1, 2}, {3, 4}, {2}]&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;answer = -1
for n in range(1, M + 1) :
    found = False
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1명부터 M명까지 조합을 시도하며, n명이 모이면 모든 문제 (1 ~ N)를 커버할 수 있는지 확인한다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;    for combination in combinations(A, n) :
        U = set()
        for a in combination :
            U |= a
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;combination은 팀원 조합(set들의 리스트)를 나타내며 U |= a는 U = U.union(a)와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 팀원들이 커버 가능한 문제들을 모두 합친다.&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;        if len(list(U)) == N :
            found = True
            break
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;U의 길이가 N이면 모든 문제를 커버했다는 뜻이므로, 더이상 탐색할 필요가 없어 break를 걸어준다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 11578 - 팀원 모집
# 분류 : 브루트포스 + set 자료구조

from itertools import combinations

N, M = map(int, input().split())
A = [list(map(int, input().split()))[1:] for _ in range(M)]
A = [set(a) for a in A]

answer = -1
for n in range(1, M + 1) :
    found = False
    for combination in combinations(A, n) :
        U = set()
        for a in combination :
            U |= a
        if len(list(U)) == N :
            found = True
            break

    if found : 
        answer = n
        break

print(answer)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 11578</category>
      <category>백준 11578 팀원 모집</category>
      <category>백준 11578 팀원 모집 파이썬</category>
      <category>백준 11578 파이썬</category>
      <category>백준 팀원 모집</category>
      <category>백준 팀원 모집 파이썬</category>
      <category>백준 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/562</guid>
      <comments>https://pental.tistory.com/562#entry562comment</comments>
      <pubDate>Thu, 17 Jul 2025 15:28:43 +0900</pubDate>
    </item>
    <item>
      <title>[골드 2] 백준 2450 - 모양 정돈 (파이썬)</title>
      <link>https://pental.tistory.com/561</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2398&quot; data-origin-height=&quot;1366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ntwMw/btsPl8m6G12/Kf3DDdlxddv6TozmOLz9l1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ntwMw/btsPl8m6G12/Kf3DDdlxddv6TozmOLz9l1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ntwMw/btsPl8m6G12/Kf3DDdlxddv6TozmOLz9l1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FntwMw%2FbtsPl8m6G12%2FKf3DDdlxddv6TozmOLz9l1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2398&quot; height=&quot;1366&quot; data-origin-width=&quot;2398&quot; data-origin-height=&quot;1366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 브루트포스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/2450&quot;&gt;https://www.acmicpc.net/problem/2450&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열 A에는 1, 2, 3이 섞여있으면서, 각각 모양을 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 배열을 구간 3개로 나누어서, 각 구간에는 한 가지 모양이 있도록 정렬해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 [2, 2, 1, 1, 3, 3] 과 같은 형태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 숫자들을 바꾸는 횟수를 최소화 해아한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 처리는 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;N = int(input())
A = list(map(int, input().split()))
A = [x - 1 for x in A]  # 0, 1, 2 로 바꿈
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 배열을 x - 1을 통해서 0, 1, 2로 정규화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그후 각 숫자의 개수를 센다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;count = [0] * 3
for x in A :
    count[x] += 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 A = [0, 0, 1, 2, 1] &amp;rarr; count = [2, 2, 1] 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 순열을 통해 모든 배치를 시도한다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;for permutation in permutations(range(3), 3):
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 (0, 1, 2), (0, 2, 1) &amp;hellip; 총 6가지 순서로 세 구간을 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구간을 미리 만들어 뒀으면 정렬된 상태의 목표 배열을 생성한다.&lt;/p&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;B = []
for x in permutation:
    B += [x] * count[x]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 count = [2, 2, 1] 이고, permutation = (1, 0, 2) 라면 B = [1, 1, 0, 0, 2]가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘못 위치한 원소를 파악 하기 위해서 다음과 같디 정의 한다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;wrong = [[0]*3 for _ in range(3)]
for i in range(N):
    if A[i] != B[i]:
        wrong[A[i]][B[i]] += 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wrong[i][j]는 i를 j로 바꿔야 함을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교화 가능한 부분 계산을 위해서 다음과 같이 정의한다.&lt;/p&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;for i in range(3):
    for j in range(i + 1, 3):
        tmp = min(wrong[i][j], wrong[j][i])
        num_changes += tmp
        wrong[i][j] -= tmp
        wrong[j][i] -= tmp
        remain = max(wrong[i][j], wrong[j][i])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i &amp;harr; j 끼리 바꿔서 해결 가능한 개수는 min(wrong[i][j], wrong[j][i])이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸로 교환하고 남은 애들은 사이클로 해결해야 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말한 사이클은 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;num_changes += 2 * remain
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어서 1&amp;rarr; 2, 2&amp;rarr; 3, 3 &amp;rarr; 1과 같이 순환하는 경우는 2번 바꿔야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다 끝났다면 최소 교환 횟수를 저장한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;answer = min(answer, num_changes)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 백준 2450 - 모양 정돈
# 분류 : 브루트포스

from itertools import permutations

N = int(input())
A = list(map(int, input().split()))
A = [x - 1 for x in A]

answer = 1e9
count = [0] * 3
for x in A :
    count[x] += 1

for permutation in permutations(range(3), 3) :
    B = []
    for x in permutation :
        B += [x] * count[x]
    
    wrong = [[0] * 3 for _ in range(3)]
    for i in range(N) :
        if A[i] != B[i] :
            wrong[A[i]][B[i]] += 1

    num_changes = 0
    remain = 0

    for i in range(3) :
        for j in range(i + 1, 3) :
            # i -&amp;gt; j, j -&amp;gt; i, a, b min(a, b)
            tmp = min(wrong[i][j], wrong[j][i])
            num_changes += tmp

            wrong[i][j] -= tmp
            wrong[j][i] -= tmp
            remain = max(wrong[i][j], wrong[j][i])

    # i -&amp;gt; j, j -&amp;gt; k, k -&amp;gt; i : 2번, 같은 수,
    num_changes += 2 * remain
    answer = min(answer, num_changes)

print(answer)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>골드 2</category>
      <category>백준</category>
      <category>백준 2450</category>
      <category>백준 2450 모양 정돈</category>
      <category>백준 2450 모양 정돈 파이썬</category>
      <category>백준 2450 파이썬</category>
      <category>백준 모양 정돈</category>
      <category>백준 모양 정돈 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/561</guid>
      <comments>https://pental.tistory.com/561#entry561comment</comments>
      <pubDate>Wed, 16 Jul 2025 17:17:12 +0900</pubDate>
    </item>
    <item>
      <title>[플래티넘 5] 백준 1981 - 배열에서 이동 (파이썬)</title>
      <link>https://pental.tistory.com/560</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cy1l4/btsPjQUCFU5/WOJWt6PzjHz6dNw7kCKVC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cy1l4/btsPjQUCFU5/WOJWt6PzjHz6dNw7kCKVC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cy1l4/btsPjQUCFU5/WOJWt6PzjHz6dNw7kCKVC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCy1l4%2FbtsPjQUCFU5%2FWOJWt6PzjHz6dNw7kCKVC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2378&quot; height=&quot;924&quot; data-origin-width=&quot;2378&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 이분 탐색 + BFS&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/1981&quot;&gt;https://www.acmicpc.net/problem/1981&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N x N 크기의 정수 배열 A가 주어짐&lt;/li&gt;
&lt;li&gt;(0, 0) &amp;rarr; (N-1, N-1)까지 &lt;b&gt;상하좌우&lt;/b&gt;로 이동 가능&lt;/li&gt;
&lt;li&gt;단, 이동하는 칸의 숫자는 어떤 [min, max] 구간에 속해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이때 max - min 의 최소값을 구하는 것이 목적&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 풀이 아이디어는 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열의 값은 최대 200이므로 min ~ max 범위가 0~200 사이임&lt;/li&gt;
&lt;li&gt;max - min &amp;lt;= mid라고 가정하고 이동이 가능한지 BFS로 검사함&lt;/li&gt;
&lt;li&gt;mid 값을 이분 탐색으로 줄여나가며 최소값을 찾는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 설정은 다음과 같이 진행한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;low, high = 0, 200
answer = -1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mid = max_val - min_val 을 이분 탐색으로 줄여 나갈 범위이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이분 탐색을 시작한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;while low &amp;lt;= high:
    mid = (low + high) // 2
    found = False
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 mid를 고정하고, 어떤 min_val ~ max_val = min_val + mid 범위 내에서 시작점과 끝점을 동시에 포함하면서 도달 가능한지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 가능한 min_val을 탐색한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;for min_val in range(200 - mid + 1):
    max_val = min_val + mid
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;max_val이 200을 넘지 않도록 탐색 범위를 제한한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작점과 끝점이 범위에 포함되는지 확인한다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;if A[0][0] &amp;lt; min_val or max_val &amp;lt; A[0][0]:
    continue
if A[N-1][N-1] &amp;lt; min_val or max_val &amp;lt; A[N-1][N-1]:
    continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작점과 도착점이 범위 안에 들어있지 않으면 해당 구간은 유효하지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 탐색을 시작한다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;visit = [[False]*N for _ in range(N)]
queue = deque()
queue.append((0, 0))
visit[0][0] = True
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS로 이동 가능한지 확인하는 부분이다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;while queue:
    r, c = queue.popleft()
    for i in range(4):
        nr, nc = r + dr[i], c + dc[i]
        if nr &amp;lt; 0 or nr &amp;gt;= N or nc &amp;lt; 0 or nc &amp;gt;= N:
            continue
        if A[nr][nc] &amp;lt; min_val or A[nr][nc] &amp;gt; max_val:
            continue
        if not visit[nr][nc]:
            visit[nr][nc] = True
            queue.append((nr, nc))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;min_val ~ max_val 범위 내 값만 탐색하면서 방문을 체크한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS 결과에 따른 이분 탐색을 갱신한다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;if visit[N - 1][N - 1]:
    found = True
    break
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도착지까지 도달했으면 더 작은 mid도 가능할 수 있으므로 high 줄인다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;if found:
    answer = mid
    high = mid - 1
else:
    low = mid + 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 백준 1981 - 배열에서 이동
# 분류 : 이분 탐색 + BFS

from collections import deque

N = int(input())
A = [list(map(int, input().split())) for _ in range(N)]

low, high = 0, 200
answer = -1
dr = [1, -1 ,0, 0]
dc = [0, 0, 1, -1]

while low &amp;lt;= high :
    mid = (low + high) // 2

    found = False

    for min_val in range(200 - mid + 1) :
        max_val = min_val + mid

        if A[0][0] &amp;lt; min_val or max_val &amp;lt; A[0][0] :
            continue
        if A[N - 1][N - 1] &amp;lt; min_val or max_val &amp;lt; A[N - 1][N - 1] :
            continue

        visit = [[False] * N for _ in range(N)]
        queue = deque()

        queue.append((0, 0))
        visit[0][0] = True

        while len(queue) != 0 :
            r, c= queue.popleft()

            for i in range(4) :
                nr, nc = r + dr[i], c + dc[i]

                if nr &amp;lt; 0 or N &amp;lt;= nr or nc &amp;lt; 0 or N &amp;lt;= nc :
                    continue
                if A[nr][nc] &amp;lt; min_val or max_val &amp;lt; A[nr][nc] :
                    continue
                if not visit[nr][nc] :
                    queue.append((nr, nc))
                    visit[nr][nc] = True
        
        if visit[N - 1][N - 1] :
            found = True
            break
    
    if found :
        answer = mid
        high = mid - 1
    else :
        low = mid + 1

print(answer)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1981</category>
      <category>백준 1981 배열에서 이동</category>
      <category>백준 1981 배열에서 이동 파이썬</category>
      <category>백준 1981 파이썬</category>
      <category>백준 배열에서 이동</category>
      <category>백준 배열에서 이동 파이썬</category>
      <category>백준 알고리즘</category>
      <category>파이썬</category>
      <category>플래티넘</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/560</guid>
      <comments>https://pental.tistory.com/560#entry560comment</comments>
      <pubDate>Tue, 15 Jul 2025 15:49:40 +0900</pubDate>
    </item>
    <item>
      <title>[골드 5] 백준 14567 - 선수과목 (Prerequisite) (파이썬)</title>
      <link>https://pental.tistory.com/559</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;1026&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSMvDB/btsPh6Q1Kn3/SJFrdSrKzcQGk3qGfWUeN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSMvDB/btsPh6Q1Kn3/SJFrdSrKzcQGk3qGfWUeN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSMvDB/btsPh6Q1Kn3/SJFrdSrKzcQGk3qGfWUeN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSMvDB%2FbtsPh6Q1Kn3%2FSJFrdSrKzcQGk3qGfWUeN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2344&quot; height=&quot;1026&quot; data-origin-width=&quot;2344&quot; data-origin-height=&quot;1026&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 다이나믹 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/14567&quot;&gt;https://www.acmicpc.net/problem/14567&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 N개의 과목이 주어지며, M개의 선수 조건이 주어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 과목에 대해 가장 빠른 이수 학기를 출력해야한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, M = map(int, input().split())
adj = [[] for _ in range(N)]

for _ in range(M) :
    a, b = map(int, input().split())
    a, b = a - 1, b - 1
    adj[b].append(a)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;adj[b].append(a)는 b를 듣기 위해 a를 먼저 들어야 한다는 조건이므로, b에서 a로 역방향 간선을 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, b의 선수 과목들을 adj[b]에 저장한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;cache = [-1] * N
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cache[i]는 i번 과목을 이수할 수 있는 가장 빠른 학기를 저장한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;def dp(u) :
    if cache[u] != -1 :
        return cache[u]

    if len(adj[u]) == 0 :
        ret = 1
    else :
        ret = max([dp(v) + 1 for v in adj[u]])
    cache[u] = ret
    return ret
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dp(u)는 과목 u를 듣기 위한 최소 학기 수를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선수 과목이 없으면 바로 1학기에 들을 수 있으며, 선수 과목이 있다면 그 중 가장 늦게 들을 수 있는 과목 + 1학기가 돼야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모이제이션으로 중복 계산을 방지한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 14567 - 선수과목 (Prerequisite)
# 분류 : 다이나믹 프로그래밍

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)

N, M = map(int, input().split())
adj = [[] for _ in range(N)]

for _ in range(M) :
    a, b = map(int, input().split())
    a, b = a - 1, b - 1

    adj[b].append(a)

cache = [-1] * N
def dp(u) :
    if cache[u] != -1 :
        return cache[u]

    if len(adj[u]) == 0 :
        ret = 1
    else :
        ret = max([dp(v) + 1 for v in adj[u]])
    cache[u] = ret
    return ret

for i in range(N) :
    print(dp(i), end = &quot; &quot;)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 14567</category>
      <category>백준 14567 선수과목 (prerequisite)</category>
      <category>백준 14567 파이썬</category>
      <category>백준 선수과목 (prerequisite)</category>
      <category>백준 선수과목 (prerequisite) 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/559</guid>
      <comments>https://pental.tistory.com/559#entry559comment</comments>
      <pubDate>Mon, 14 Jul 2025 17:02:21 +0900</pubDate>
    </item>
    <item>
      <title>[골드 3] 백준 1719 - 택배 (파이썬)</title>
      <link>https://pental.tistory.com/558</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FBCnT/btsPfuSyXxw/8Fkgb3SgEpUYnlGZhqPRFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FBCnT/btsPfuSyXxw/8Fkgb3SgEpUYnlGZhqPRFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FBCnT/btsPfuSyXxw/8Fkgb3SgEpUYnlGZhqPRFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFBCnT%2FbtsPfuSyXxw%2F8Fkgb3SgEpUYnlGZhqPRFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;275&quot; height=&quot;180&quot; data-origin-width=&quot;275&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1719&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1719&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 다익스트라&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/1719&quot;&gt;https://www.acmicpc.net/problem/1719&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 어느 경로로 가는 것이 최단 경로인지를 알아내는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 도시(정점) 간의 최단 경로를 찾아야하며, 단순히 최단 거리만 출력하는 것이 아니라, 어디로 먼저 가야 하는지를 출력해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, i &amp;rarr; j 로 갈 때 첫번째로 가야하는 도시를 출력해야하는 것ㅇ디ㅏ.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;from queue import PriorityQueue

N, M = map(int, input().split())  # 도시 수 N, 도로 수 M
adj = [[] for _ in range(N)]      # 인접 리스트

# 간선 정보 입력
for _ in range(M):
    a, b, c = map(int, input().split())
    a, b = a - 1, b - 1            # 0-indexed
    adj[a].append((b, c))
    adj[b].append((a, c))

# 모든 정점쌍 최단 거리 저장할 2차원 리스트
dist = [[1e9] * N for _ in range(N)]

# 모든 정점에 대해 다익스트라 수행
for s in range(N):
    pq = PriorityQueue()
    pq.put((0, s))
    dist[s][s] = 0

    while pq.qsize() != 0:
        d, u = pq.get()
        if d != dist[s][u]:
            continue

        for v, w in adj[u]:
            if dist[s][v] &amp;gt; dist[s][u] + w:
                dist[s][v] = dist[s][u] + w
                pq.put((dist[s][v], v))
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;matlab&quot;&gt;&lt;code&gt;for i in range(N):
    for j in range(N):
        if i == j:
            print(&quot;-&quot;, end=&quot; &quot;)
        else:
            for k, w in adj[i]:
                if dist[i][j] == w + dist[k][j]:
                    print(k + 1, end=&quot; &quot;)
                    break
    print()
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의도는 i &amp;rarr; j 로 가는 최단 경로에서 처음으로 가야 할 노드 k를 찾고 싶은 것이다. i &amp;rarr; k 간선이 있고, k &amp;rarr; j까지 최단 거리라면 그게 최단 경로 일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 단순한 거리 비교에 기반하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist[i][j] == w + dist[k][j] 조건을 만족하는 아무 노드나 찍는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 최단 경로는 여러 개일 수도 있고, 경유 순서를 추적하지 않기 때문에 반례가 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 반례를 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;1 -&amp;gt; 2-&amp;gt; 4, 1 -&amp;gt; 3 -&amp;gt; 4 둘다 거리가 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 adj[1]에 2, 3 모두 연결되ㅓ 있고, dist[1][4] == w + dist[k][4] 조건을 만족한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 걸 먼저 print 할지는 adj[1] 순서에 따라 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;다익스트라를 N번 돌려서 모든 쌍의 최단 거리를 구함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;문제점&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;최단 거리만 있고, 경로(특히 첫 번째 경유지) 추적을 하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;오답 가능성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;단순한 거리 비교로는 정확한 경로 추정이 안 됨 (정점 방문 흐름이 보장되지 않음)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 코드가 맞았지만, 개선 방법을 요약하면 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다익스트라 수행 중에 이 정점은 어디를 통해 처음 왔는가를 기록해야 한다.&lt;/li&gt;
&lt;li&gt;즉, first[s][v] = u 또는 first[s][v] = first[s][u] 방식으로 추적이 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;# 백준 1719 - 택배
# 분류 : 다익스트라

from queue import PriorityQueue

N, M = map(int, input().split())
adj = [[] for _ in range(N)]

for _ in range(M) :
    a, b, c = map(int, input().split())
    a, b = a - 1, b - 1
    adj[a].append((b, c))
    adj[b].append((a, c))

dist = [[1e9] * N for _ in range(N)]

for s in range(N) :
    pq = PriorityQueue()

    pq.put((0, s))
    dist[s][s] = 0

    while pq.qsize() != 0 :
        d, u = pq.get()
        if d != dist[s][u] :
            continue

        for v, w in adj[u] :
            if dist[s][v] &amp;gt; dist[s][u] + w :
                dist[s][v] = dist[s][u] + w
                pq.put((dist[s][v], v))

for i in range(N) :
    for j in range(N) :
        if i == j :
            print(&quot;-&quot;, end = &quot; &quot;)
        else :
            for k, w in adj[i] :
                if dist[i][j] == w + dist[k][j] :
                    print(k + 1, end = &quot; &quot;)
                    break
        
    print()
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1719</category>
      <category>백준 1719 택배</category>
      <category>백준 1719 택배 파이썬</category>
      <category>백준 1719 파이썬</category>
      <category>백준 택배</category>
      <category>백준 택배 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/558</guid>
      <comments>https://pental.tistory.com/558#entry558comment</comments>
      <pubDate>Sun, 13 Jul 2025 11:29:27 +0900</pubDate>
    </item>
    <item>
      <title>[Reversing.kr] Easy Crack</title>
      <link>https://pental.tistory.com/557</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;흠,, 포렌식만 공부하다가 이제 리버싱도 슬슬 해볼까 해서 reversing.kr 을 풀어보기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 리버싱은 공부해도 어려운것 같다.. 포렌식 보다 훨씬 더,, 해당 포스팅은 포렌식 7년차의 리버싱 입문기라고 생각하고, 틀린점이 있어도 그냥 귀엽게 넘어가 주면 좋겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Easy_CrackMe.exe의 파일은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5Vccn/btsPfIJG8kn/uREznaBzzmsKGlQX4kRW9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5Vccn/btsPfIJG8kn/uREznaBzzmsKGlQX4kRW9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5Vccn/btsPfIJG8kn/uREznaBzzmsKGlQX4kRW9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5Vccn%2FbtsPfIJG8kn%2FuREznaBzzmsKGlQX4kRW9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;470&quot; height=&quot;580&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;table id=&quot;22d95991-2839-8087-948e-dff5f5ffae62&quot; style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr id=&quot;22d95991-2839-807f-b89e-c03614789909&quot;&gt;
&lt;td id=&quot;Mzj;&quot;&gt;FileName&lt;/td&gt;
&lt;td id=&quot;Dp?|&quot;&gt;Easy_CrackMe.exe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;22d95991-2839-8076-835c-ce22626dc6ca&quot;&gt;
&lt;td id=&quot;Mzj;&quot;&gt;FileSize&lt;/td&gt;
&lt;td id=&quot;Dp?|&quot;&gt;40,960 Byte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;22d95991-2839-8066-8200-fa379a293985&quot;&gt;
&lt;td id=&quot;Mzj;&quot;&gt;CRC32&lt;/td&gt;
&lt;td id=&quot;Dp?|&quot;&gt;FE454D60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;22d95991-2839-8017-962e-e3f64c3fae77&quot;&gt;
&lt;td id=&quot;Mzj;&quot;&gt;MD5&lt;/td&gt;
&lt;td id=&quot;Dp?|&quot;&gt;A74DB218A9175E0AE2CCFFB3476DD4CF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr id=&quot;22d95991-2839-80a1-b3b0-fcd80ccf1ba1&quot;&gt;
&lt;td id=&quot;Mzj;&quot;&gt;SHA-1&lt;/td&gt;
&lt;td id=&quot;Dp?|&quot;&gt;F153F26F16B5AE03E3A7BE7FFE5395E966051F3B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Easy_CrackMe.exe 를 실행하면 다음과 같은 창이 나타난다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;107&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tA7X9/btsPf0i0M3f/Y0fZXN3p5vzmRbVsKyOz6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tA7X9/btsPf0i0M3f/Y0fZXN3p5vzmRbVsKyOz6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tA7X9/btsPf0i0M3f/Y0fZXN3p5vzmRbVsKyOz6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtA7X9%2FbtsPf0i0M3f%2FY0fZXN3p5vzmRbVsKyOz6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;301&quot; height=&quot;107&quot; data-origin-width=&quot;301&quot; data-origin-height=&quot;107&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무거나 입력 후 확인을 클릭하면 다음과 같이 Incorrect Password 와 같은 알림창이 나타난다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DsjHA/btsPfpqscC8/JKaZkl7g82xXRxbGkUYRi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DsjHA/btsPfpqscC8/JKaZkl7g82xXRxbGkUYRi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DsjHA/btsPfpqscC8/JKaZkl7g82xXRxbGkUYRi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDsjHA%2FbtsPfpqscC8%2FJKaZkl7g82xXRxbGkUYRi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;344&quot; height=&quot;282&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDA 9.1 Free를 통해서 파일을 연다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;1029&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6ivuI/btsPfym6FHp/CPYWPbYqSG6NQVpF8XDmBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6ivuI/btsPfym6FHp/CPYWPbYqSG6NQVpF8XDmBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6ivuI/btsPfym6FHp/CPYWPbYqSG6NQVpF8XDmBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6ivuI%2FbtsPfym6FHp%2FCPYWPbYqSG6NQVpF8XDmBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1918&quot; height=&quot;1029&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;1029&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDA Free를 통해서 바이너리 파일을 열어보면 자동으로 시작점을 잡아 준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcyLwS/btsPfko1vcf/XO2gndBrNpzkn9MnOHWjN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcyLwS/btsPfko1vcf/XO2gndBrNpzkn9MnOHWjN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcyLwS/btsPfko1vcf/XO2gndBrNpzkn9MnOHWjN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcyLwS%2FbtsPfko1vcf%2FXO2gndBrNpzkn9MnOHWjN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1032&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 IDA를 쓸줄은 모르지만 그래도 깔짝깔짝 써보려고 한다&amp;hellip; 리버싱 입문자,,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYNZOS/btsPgff0doe/Z3QdyD3K4F66QJVl2Eyzq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYNZOS/btsPgff0doe/Z3QdyD3K4F66QJVl2Eyzq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYNZOS/btsPgff0doe/Z3QdyD3K4F66QJVl2Eyzq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYNZOS%2FbtsPgff0doe%2FZ3QdyD3K4F66QJVl2Eyzq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;886&quot; height=&quot;315&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 초기에 정의되는 부분에서는 다음과 같은 힌트를 확인 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태에서 Tab 키를 누르면 디컴파일된 코드로 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zzWkf/btsPfpD1pZn/2spUrWTINLGwWfCWI4ie21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zzWkf/btsPfpD1pZn/2spUrWTINLGwWfCWI4ie21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zzWkf/btsPfpD1pZn/2spUrWTINLGwWfCWI4ie21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzzWkf%2FbtsPfpD1pZn%2F2spUrWTINLGwWfCWI4ie21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;798&quot; height=&quot;127&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;127&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이게 중요한건 아니고, 위에서 순서대로 살펴보면 다음과 같다.&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;mov     eax, [esp+hInstance]
push    0               ; dwInitParam
push    offset DialogFunc ; lpDialogFunc
push    0               ; hWndParent
push    65h             ; lpTemplateName
push    eax             ; hInstance
call    ds:DialogBoxParamA
xor     eax, eax
retn    10h
_WinMain@16 endp

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분에서는 mov eax, [esp+hInstance] 에서는 스택에서 첫번쨰 인자 hInstace를 가져오는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값은 WinMain(HINSTACE hInstace, &amp;hellip;) 에서의 hInstace이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 push 인자들에서는 DialogBoxParamA함수의 인자들을 푸쉬하는 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 다음과 같은 시그니처를 가진다고 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;INT_PTR DialogBoxParamA(
  HINSTANCE hInstance,
  LPCSTR lpTemplateName,
  HWND hWndParent,
  DLGPROC lpDialogFunc,
  LPARAM dwInitParam
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한건 아닌것 같으니 넘어간다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shift+F12를 통해서 사용되는 문자열을 확인 할 수 있으며, 위에서 Incorrect PAssword와 같은 문자열을 확인 했기에, IDA Strings 기능을 통해서 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;95&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csGFGg/btsPfKU448g/VjK5NqdmXRp62H0wxNqNd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csGFGg/btsPfKU448g/VjK5NqdmXRp62H0wxNqNd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csGFGg/btsPfKU448g/VjK5NqdmXRp62H0wxNqNd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsGFGg%2FbtsPfKU448g%2FVjK5NqdmXRp62H0wxNqNd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;451&quot; height=&quot;95&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;95&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Strings에서는 74개의 문자열들이 발견 되었으며, Incorrect Password 및 Congratulaion !! 등의 문자열 패턴을 확인 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 Incorrect Password 부분에서 잘못된 암호가 입력되었기 때문에, 해당 값을 더블클릭하여 어떤 구조로 되어 있는지 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zMDr2/btsPgZjdRrk/ivesAPBHqIL7ZPMfM4ixX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zMDr2/btsPgZjdRrk/ivesAPBHqIL7ZPMfM4ixX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zMDr2/btsPgZjdRrk/ivesAPBHqIL7ZPMfM4ixX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzMDr2%2FbtsPgZjdRrk%2FivesAPBHqIL7ZPMfM4ixX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;717&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sub_401080에서 조건 문 들을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DmGp5/btsPgAD7Qzv/x5OmrJFlcF3Omqh3aU9G80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DmGp5/btsPgAD7Qzv/x5OmrJFlcF3Omqh3aU9G80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DmGp5/btsPgAD7Qzv/x5OmrJFlcF3Omqh3aU9G80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDmGp5%2FbtsPgAD7Qzv%2Fx5OmrJFlcF3Omqh3aU9G80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1032&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1032&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bunnep/btsPf5YZ8Nj/KOKF3tZ7jntKUyIvQdVD51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bunnep/btsPf5YZ8Nj/KOKF3tZ7jntKUyIvQdVD51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bunnep/btsPf5YZ8Nj/KOKF3tZ7jntKUyIvQdVD51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbunnep%2FbtsPf5YZ8Nj%2FKOKF3tZ7jntKUyIvQdVD51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1457&quot; height=&quot;673&quot; data-origin-width=&quot;1457&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cmp [esp+68h+Stirngs], 45h; &amp;lsquo;E&amp;rsquo; 부분에서 cmp는 compare를 나타내며, 이 문자가 동일한지 확인하고, Congrautulation !! 이 출력되도록 하는 구조이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 부터 차근차근 확인해 본다.&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;sub_401080 proc near

String= byte ptr -64h
var_63= byte ptr -63h
Str1= byte ptr -62h
var_60= byte ptr -60h
hDlg= dword ptr  4

sub     esp, 64h
push    edi
mov     ecx, 18h
xor     eax, eax
lea     edi, [esp+68h+var_63]
mov     [esp+68h+String], 0
push    64h ; 'd'       ; cchMax
rep stosd
stosw
stosb
mov     edi, [esp+6Ch+hDlg]
lea     eax, [esp+6Ch+String]
push    eax             ; lpString
push    3E8h            ; nIDDlgItem
push    edi             ; hDlg
call    ds:GetDlgItemTextA
cmp     [esp+68h+var_63], 61h ; 'a'
jnz     short loc_401135
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 함수의 시작에서는 다이얼로그 박스에서 에디트박스의 텍스트를 읽어온 후, 그 텍스트의 첫번쨰 문자가 &amp;lsquo;a&amp;rsquo; 인지 확인하는 함수이다.&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;push    2               ; MaxCount
lea     ecx, [esp+6Ch+Str1]
push    offset Str2     ; &quot;5y&quot;
push    ecx             ; Str1
call    _strncmp
add     esp, 0Ch
test    eax, eax
jnz     short loc_401135
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 함수는 strcpm를 호출하여, Str1이라는 버퍼의 값이 문자열 &amp;ldquo;5y&amp;rdquo;와 같은지를 확인하고, 앞에서 부터 두 글자만 비교하고, 같지 않으면 loc_401135로 분기하는 함수이다.&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;push    ebx
push    esi
mov     esi, offset aR3versing ; &quot;R3versing&quot;
lea     eax, [esp+70h+var_60]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 조건이 맞다면, 문자열 &amp;ldquo;R3versing&amp;rdquo;의 주소를 esi에 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문자열은 PE 리소스의 .rdata 섹션 등에 존재하는 고정 문자열일 가능성이 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, 지역 변수 var_60의 주소를 계산해서 eax에 저장한다. 즉, eax = 문자열을 복사할 목적지 버퍼의 주소를 나타낸다.&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;cmp     [esp+68h+String], 45h ; 'E'
jnz     short loc_401135
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 간단히 말하면 스택에 있는 String이라는 버퍼의 첫 번째 바이트가 &amp;lsquo;E&amp;rsquo; 인지 검사하고, 그렇지 않으면 loc_401135로 점프하는 조건문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 지금까지 나온 값들을 종합하면 &amp;lsquo;Ea5yR3versing&amp;rsquo; 이 정답이 되게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;336&quot; data-origin-height=&quot;189&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csyIZ0/btsPfjwS2Yh/YUyXWDKSqP4Y55R6LUu81K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csyIZ0/btsPfjwS2Yh/YUyXWDKSqP4Y55R6LUu81K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csyIZ0/btsPfjwS2Yh/YUyXWDKSqP4Y55R6LUu81K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsyIZ0%2FbtsPfjwS2Yh%2FYUyXWDKSqP4Y55R6LUu81K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;336&quot; height=&quot;189&quot; data-origin-width=&quot;336&quot; data-origin-height=&quot;189&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>이것저것</category>
      <category>IDA</category>
      <category>ida 리버싱</category>
      <category>reversing.kr easy crackme</category>
      <category>리버싱</category>
      <category>리버싱 입문</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/557</guid>
      <comments>https://pental.tistory.com/557#entry557comment</comments>
      <pubDate>Sat, 12 Jul 2025 20:22:04 +0900</pubDate>
    </item>
    <item>
      <title>[골드 5] 백준 14284 - 간선 이어가기 2 (파이썬)</title>
      <link>https://pental.tistory.com/556</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjhoIy/btsPfhMrogP/KMVkb0XAhP6xXHMBySCi8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjhoIy/btsPfhMrogP/KMVkb0XAhP6xXHMBySCi8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjhoIy/btsPfhMrogP/KMVkb0XAhP6xXHMBySCi8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjhoIy%2FbtsPfhMrogP%2FKMVkb0XAhP6xXHMBySCi8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1176&quot; height=&quot;647&quot; data-origin-width=&quot;1176&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/14284&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/14284&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 조금 방향 없는 그래프, 즉 무방향 그래프가 주어지며, 정점수 N, 간선수 M이 주어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 간선은 가중치를 가지며, 출발점 S에서 도착점 T까지의 최단 거리를 구하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에세의 핵심 알고리즘은, 단연코 다익스트라 알고리즘이라고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 가중치가 있는 그래프에서 하나의 시작점에서 다른 모든 정점까지의 최단 경로를 구하는 알고리즘이며, 이 문제에서는 특정 시작점에서 특정 도착점 까지의 거리만 구하면 된다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from queue import PriorityQueue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위 큐는 최소 거리 기준으로 정점을 꺼내기 위해서 위와 같이 사용한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, M = map(int, input().split())
adj = [[] for _ in range(N)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정점수와 간선수 및 인접 리스트 방식으로 그래프를 저장하기 위해서 위와 같이 선언한다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;for _ in range(M):
    a, b, c = map(int, input().split())
    a, b = a - 1, b - 1
    adj[a].append((b, c))
    adj[b].append((a, c))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 간선 정보를 입력받으며, 양방향 간선이므로, adj[a], adj[b]에 각각 추가한다.&lt;/p&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;S, T = map(int, input().split())
S, T = S - 1, T - 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작점 S, 도착점 T 입력 및 1-Base-Index를 0-Based-Index로 수정한다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;dist = [1e9] * N
pq = PriorityQueue()

pq.put((0, S))
dist[S] = 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dist의 경우 시작점에서 각 정점까지의 최단 거리를 저장하며, 시작점 S는 거리 0으로 초기화, 나머지는 무한대로 미리 초기화 해둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 우선순위 큐에 (거리, 정점) 형태로 삽입한다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;while pq.qsize() != 0:
    d, u = pq.get()

    if d != dist[u]:
        continue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐에서 현재 가장 거리가 짧은 정점 u를 꺼내며, 꺼낸 값 d가 dist[u]와 다르면 이미 더 짧은 거리로 처리되었으므로 스킵한다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;    for v, w in adj[u]: 
        if dist[v] &amp;gt; dist[u] + w:
            dist[v] = dist[u] + w
            pq.put((dist[v], v))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인접한 정점 v에 대해서 현재까지 알려진 거리보다 더 짧은 경로가 있으면 업데이트한다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;print(dist[T])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 dist[T]를 출력하면 S에서 T까지의 최단 거리를 출력 하는 것이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시간 복잡도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;O(M Log N) &amp;rarr; 우선순위 큐 기반 다익스트라 사용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;# 백준 14284 - 간선 이어가기 2
# 분류 : 다익스트라

import sys
from queue import PriorityQueue

input = sys.stdin.readline

N, M = map(int, input().split())
adj = [[] for _ in range(N)]

for _ in range(M) :
    a, b, c = map(int, input().split())
    a, b = a - 1, b - 1

    adj[a].append((b, c))
    adj[b].append((a, c))

S, T = map(int, input().split())
S, T = S - 1, T - 1

dist = [1e9] * N
pq = PriorityQueue()

pq.put((0, S))
dist[S] = 0

while pq.qsize() != 0 :
    d, u = pq.get()

    if d != dist[u] :
        continue
    
    for v, w in adj[u]: 
        if dist[v] &amp;gt; dist[u] + w :
            dist[v] = dist[u] + w
            pq.put((dist[v], v))

print(dist[T])
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 14284</category>
      <category>백준 14284 파이썬</category>
      <category>백준 간선 이어가기 2</category>
      <category>백준 간선 이어가기 2 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/556</guid>
      <comments>https://pental.tistory.com/556#entry556comment</comments>
      <pubDate>Sat, 12 Jul 2025 12:33:39 +0900</pubDate>
    </item>
    <item>
      <title>[골드 5] 백준 17072 - 나무 위의 빗물 (파이썬)</title>
      <link>https://pental.tistory.com/555</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;505&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bwqgh/btsPfJA3Xux/h2M0GqROR64pQvPosdQeZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bwqgh/btsPfJA3Xux/h2M0GqROR64pQvPosdQeZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bwqgh/btsPfJA3Xux/h2M0GqROR64pQvPosdQeZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBwqgh%2FbtsPfJA3Xux%2Fh2M0GqROR64pQvPosdQeZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;543&quot; height=&quot;505&quot; data-origin-width=&quot;543&quot; data-origin-height=&quot;505&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/17073&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/17073&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 비의 양 W가 루트 노드에 고이며, 나무는 N개의 정점으로 이루어진 트리이고, 루트 노드는 1번이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비는 모든 리프 노드까지 동일하게 분배되며, 각 리프 노드까지 고인 빗물의 양을 구하는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 이 문제를 해결하는 방법은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;트리는 사이클이 없는 연결 그래프이므로, DFS로 리프 노드를 쉽게 찾을 수 있다.&lt;/li&gt;
&lt;li&gt;루트에서 DFS를 돌려 리프 노드의 개수를 센다.&lt;/li&gt;
&lt;li&gt;전체 물이의 양 W를 리프 노드 개수로 나눈다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;리프노드마다 동일한 양의 물이 고이기 때문이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 정점 수, 물의 양을 입력받는 인접 리스트를 생성한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, W = map(int, input().split())
adj = [[] for _ in range(N)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N은 트리의 정점 개수, W는 전체 빗물의 양, adj는 트리의 구조를 표현하는 인접 리스트를 의미한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;for _ in range(N - 1):
    u, v = map(int, input().split())
    u -= 1
    v -= 1
    adj[u].append(v)
    adj[v].append(u)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리는 N - 1개의 간선을 가지며, 입력된 정점 번호는 1부터 시작하므로 0부터 시작하도록 0-Index based 형식으로 처리한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무방향 그래프이므로 adj[u], adj[v] 양쪽에 추가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방문 처리 배열 및 리프 노드 수를 초기화 한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;visit = [False] * N
count = 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;visit의 경우 DFS 중복 방문 방지용 배열이며, count는 리프 노드의 개수를 셀 변수를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 DFS 함수를 정의한다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;def dfs(u):
    visit[u] = True
    is_leaf = True

    for v in adj[u]:
        if not visit[v]:
            dfs(v)
            is_leaf = False
    
    if is_leaf:
        global count
        count += 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;u는 현재 방문 중인 노드를 의미하며 is_leaf는 자식 노드가 있는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자식이 있으면 리프가 아니므로 is_leaf = False로 리프 노드인 경우 count를 증가시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 전체적인 흐름은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;트리 구조를 입력받고 인접 리스트를 구성한다.&lt;/li&gt;
&lt;li&gt;DFS로 루트부터 탐색하면서 리프 노드 개수를 파악한다.&lt;/li&gt;
&lt;li&gt;물의 양 W를 리프 노드 수 count로 나눠서 정답을 출력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 17073 - 나무 위의 빗물
# 분류 : DFS + 수학

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10 ** 6)

N, W = map(int, input().split())
adj = [[] for _ in range(N)]

for _ in range(N - 1) :
    u, v = map(int, input().split())
    u -= 1
    v -= 1

    adj[u].append(v)
    adj[v].append(u)

visit = [False] * N
count = 0

def dfs(u) :
    visit[u] = True
    is_leaf = True

    for v in adj[u] :
        if not visit[v] :
            dfs(v)
            is_leaf = False
    
    if is_leaf :
        global count
        count += 1

dfs(0)
print(W / count)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>dfs</category>
      <category>백준</category>
      <category>백준 17073</category>
      <category>백준 17073 파이썬</category>
      <category>백준 나무 위의 빗물</category>
      <category>백준 나무 위의 빗물 파이썬</category>
      <category>백준 알고리즘</category>
      <category>백준 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/555</guid>
      <comments>https://pental.tistory.com/555#entry555comment</comments>
      <pubDate>Fri, 11 Jul 2025 17:35:31 +0900</pubDate>
    </item>
    <item>
      <title>[골드 4] 백준 20159 - 동작 그만. 밑장 빼기냐?</title>
      <link>https://pental.tistory.com/554</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1042&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coKaSJ/btsPb0vUlX1/8jeilXkkS376lsiutSCjq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coKaSJ/btsPb0vUlX1/8jeilXkkS376lsiutSCjq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coKaSJ/btsPb0vUlX1/8jeilXkkS376lsiutSCjq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoKaSJ%2FbtsPb0vUlX1%2F8jeilXkkS376lsiutSCjq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2366&quot; height=&quot;1042&quot; data-origin-width=&quot;2366&quot; data-origin-height=&quot;1042&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/20159&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/20159&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플레이어가 번갈아 가면서 카드를 가져간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짝수 번째(0, 2, 4 &amp;hellip; )는 내차례, 홀수 번째는 상대 차례이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 카드 1장을 상다 차례에서 내가 가져도록 1번의 밑장 빼기를 허용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대 점수를 얻기 위해 밑장 빼기를 어느 위치에서 할지를 결정해야한다.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;psum0 = [0] * N  # 내 차례에서의 누적합
psum1 = [0] * N  # 상대 차례에서의 누적합

psum0[0] = A[0]
psum1[0] = 0

for i in range(1, N):
    if i % 2 == 0:  # 내 차례
        psum0[i] = psum0[i - 1] + A[i]
        psum1[i] = psum1[i - 1]
    else:           # 상대 차례
        psum0[i] = psum0[i - 1]
        psum1[i] = psum1[i - 1] + A[i]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i번째 카드가 내 차례인지 상대 차례인지를 나누어 각각의 누적합 배열을 구성한다.&lt;/p&gt;
&lt;pre class=&quot;ruby&quot;&gt;&lt;code&gt;def range_sum0(l, r): ...
def range_sum1(l, r): ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누적합을 이용한 구간 합 함수를 각각 구현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sum0의 경우 내 차례인 카드들 중 l ~ r의 합을 나타내고, sum1의 경우 상대 차례인 카드들 중 l ~ r의 합을 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;밑장 빼기 시뮬레이션은 다음과 같이 진행한다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;answer = psum0[N - 1]  # 밑장 안 뺐을 경우의 기본 점수

for i in range(N):
    score = range_sum0(0, i - 1) + range_sum1(i, N - 2)
    if i % 2 == 0:
        score += A[N - 1]  # 밑장 빼기 성공하면 마지막 카드 얻음
    
    answer = max(answer, score)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i는 밑장을 빼는 위치이고, range_sum0, range_sum1을 통해서 밑짱 빼기 시뮬레이션을 진행한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 백준 20159 - 동작 그만. 밑장 빼기냐?
# 분류 : 누적합

N = int(input())
A = list(map(int, input().split()))

psum0 = [0] * N
psum1 = [0] * N
psum0[0] = A[0]
psum1[0] = 0

for i in range(1, N) :
    if i % 2 == 0 :
        psum0[i] = psum0[i - 1] + A[i]
        psum1[i] = psum1[i - 1]
    else :
        psum0[i] = psum0[i - 1]
        psum1[i] = psum1[i - 1] + A[i]

def range_sum0(l, r) :
    if l &amp;gt; r :
        return 0
    ret = psum0[r]
    if l &amp;gt; 0 :
        ret -= psum0[l - 1]
    return ret

def range_sum1(l, r) :
    if l &amp;gt; r :
        return 0
    ret = psum1[r]
    if l &amp;gt; 0 :
        ret -= psum1[l - 1]
    return ret

answer = psum0[N - 1]
for i in range(N) :
    score = range_sum0(0, i - 1) + range_sum1(i, N - 2)
    if i % 2 == 0 :
        score += A[N - 1]
    
    answer = max(answer, score)

print(answer)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 20159</category>
      <category>백준 20159 파이썬</category>
      <category>백준 동작 그만. 밑장 빼기냐?</category>
      <category>백준 동작 그만. 밑장 뺴기냐? 파이썬</category>
      <category>알고리즘</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/554</guid>
      <comments>https://pental.tistory.com/554#entry554comment</comments>
      <pubDate>Wed, 9 Jul 2025 16:56:29 +0900</pubDate>
    </item>
    <item>
      <title>[실버 4] 백준 29767 - 점수를 최대로 (파이썬)</title>
      <link>https://pental.tistory.com/553</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2402&quot; data-origin-height=&quot;1186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DhmR9/btsPbAqPdMj/VgiCeLuPKOAOTSrLlYS1s0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DhmR9/btsPbAqPdMj/VgiCeLuPKOAOTSrLlYS1s0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DhmR9/btsPbAqPdMj/VgiCeLuPKOAOTSrLlYS1s0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDhmR9%2FbtsPbAqPdMj%2FVgiCeLuPKOAOTSrLlYS1s0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2402&quot; height=&quot;1186&quot; data-origin-width=&quot;2402&quot; data-origin-height=&quot;1186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/29767&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/29767&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;길이가 N인 정수 수열 A가 주어지며, 누적합(A[0]부터 A[i]까지의 합)을 구해 전체 N개의 누적합 중 K개를 선택해서 합을 최대로 만들어야한다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, K = map(int, input().split())
A = list(map(int, input().split()))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N은 원소 개수, K는 선택할 누적합 개수를 입력 받는다.&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;psum = [0] * N
psum[0] = A[0]

for i in range(1, N):
    psum[i] = psum[i - 1] + A[i]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;psum[i]는 A[0] + A[1] + &amp;hellip; + A[i]를 의미하며, 즉, 누적합 배열을 만든다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;psum.sort(reverse=True)
print(sum(psum[:K]))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누적합 배열을 내림차순 정렬한 뒤, 상위 K개의 값을 선택하여 더한 결과를 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 이 문제 풀이의 아이디어는 누적합은 앞에서부터의 합이므로 psum[i]는 i + 1개 원소의 부분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점수를 최대로 하려면 가장 큰 누적합들만 선택하면 되고, 따라서 누적합 배열을 정렬해 상위 K개만 골라서 더하면 해결 할 수 있는 문제이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 29767 - 점수를 최대로
# 분류 : 누적합 + 그리디

N, K = map(int, input().split())
A = list(map(int, input().split()))

psum = [0] * N
psum[0] = A[0]

for i in range(1, N) :
    psum[i] = psum[i - 1] + A[i]

psum.sort(reverse=True)
print(sum(psum[:K]))
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 29767</category>
      <category>백준 29767 점수를 최대로</category>
      <category>백준 29767 파이썬</category>
      <category>백준 점수를 최대로</category>
      <category>백준 점수를 최대로 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/553</guid>
      <comments>https://pental.tistory.com/553#entry553comment</comments>
      <pubDate>Wed, 9 Jul 2025 16:55:01 +0900</pubDate>
    </item>
    <item>
      <title>[플래티넘 5] 백준 1050 - 물약 (파이썬)</title>
      <link>https://pental.tistory.com/552</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2352&quot; data-origin-height=&quot;1340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bg255/btsO8IciN9T/VuJoXJF3FXesEN1owXbFTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bg255/btsO8IciN9T/VuJoXJF3FXesEN1owXbFTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bg255/btsO8IciN9T/VuJoXJF3FXesEN1owXbFTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBg255%2FbtsO8IciN9T%2FVuJoXJF3FXesEN1owXbFTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2352&quot; height=&quot;1340&quot; data-origin-width=&quot;2352&quot; data-origin-height=&quot;1340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1050&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/1050&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러개의 기초 물약은 가격이 주어지고, 일부 물약은 다른 물약들로 조합하여 만들 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조합은 &quot;LOVE=A+2B&quot; 같은 형태로 주어진다.&lt;/li&gt;
&lt;li&gt;목표: 물약 &amp;ldquo;LOVE&amp;rdquo;를 만드는데 필요한 최소 비용 계산하는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, M = map(int, input().split())
stuff = {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N은 가격이 주어진 물약 수를 나타내며, M은 조합식 수를 나타낸다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;for _ in range(N) :
    name, cost = input().split()
    cost = int(cost)
    stuff[name] = cost
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격이 주어진 물약은 딕셔너리 stuff에 저장한다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;formulas = [input() for _ in range(M)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LOVE = 2A + 3B 형식으로 전체 조합식을 저장한다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;for i in range(M) :
    result, formula = formulas[i].split(&quot;=&quot;)
    
    if result not in stuff :
        stuff[result] = -1  # 아직 계산 안 됨
    
    elements = formula.split(&quot;+&quot;)
    for e in elements :
        k = int(e[0])
        name = e[1:]
        if name not in stuff :
            stuff[name] = -1  # 조합에 필요한 것도 초기화
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-1은 아직 비용 계산이 안된 물약을 나타낸다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;while True :
    update = False

    for i in range(M) :
        result, formula = formulas[i].split(&quot;=&quot;)
        elements = formula.split(&quot;+&quot;)

        computable = True
        sum = 0
        for e in elements :
            k = int(e[0])
            name = e[1:]

            if stuff[name] == -1 :
                computable = False
                break
            else :
                sum += k * stuff[name]
                sum = min(sum, MAX_VAL)  # 오버플로 방지

        if computable :
            if stuff[result] == -1 or stuff[result] &amp;gt; sum :
                stuff[result] = sum
                update = True

    if not update :
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 조합식을 순회하면서, 조합 가능한 경우에만 최소 비용을 갱신한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갱신이 일어났으면 한 번 더 반복하며, 더이상 갱신이 없으면 종료한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 1050 - 물약
# 분류 : 자료구조

import re

N, M = map(int, input().split())
MAX_VAL = 10000000001

stuff = {}
for _ in range(N) :
    name, cost = input().split()
    cost = int(cost)
    stuff[name] = cost

formulas = [input() for _ in range(M)]

for i in range(M) :
    result, formula = formulas[i].split(&quot;=&quot;)
    
    if result not in stuff :
        stuff[result] = -1
    
    elements = formula.split(&quot;+&quot;)
    for e in elements :
        k = int(e[0])
        name = e[1 : ]

        if name not in stuff :
            stuff[name] = -1

while True :
    update = False

    for i in range(M) :
        result, formula = formulas[i].split(&quot;=&quot;)
        elements = formula.split(&quot;+&quot;)

        computable = True
        sum = 0
        for e in elements:
			    match = re.match(r&quot;(\\d+)([A-Z]+)&quot;, e)
			    k = int(match[1])
			    name = match[2]
			
			    if name not in stuff or stuff[name] == -1:
			        computable = False
			        break
			    else:
			        cost = k * stuff[name]
			        if cost &amp;gt; MAX_VAL:
			            cost = MAX_VAL
			        sum += cost
			        if sum &amp;gt; MAX_VAL:
			            sum = MAX_VAL

        if computable :
            if stuff[result] == -1 or stuff[result] &amp;gt; sum :
                stuff[result] = sum
                update = True

    if not update :
        break

if &quot;LOVE&quot; in stuff and stuff[&quot;LOVE&quot;] != -1 :
    print(stuff[&quot;LOVE&quot;])
else :
    print(-1)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 1050</category>
      <category>백준 1050 파이썬</category>
      <category>백준 물약</category>
      <category>백준 물약 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/552</guid>
      <comments>https://pental.tistory.com/552#entry552comment</comments>
      <pubDate>Tue, 8 Jul 2025 16:29:13 +0900</pubDate>
    </item>
    <item>
      <title>[골드 2] 백준 2461 - 대표 선수 (파이썬)</title>
      <link>https://pental.tistory.com/551</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2362&quot; data-origin-height=&quot;1028&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHJu8q/btsO7FTz8HI/oZKPnGKlBXbGnXz4NcnbZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHJu8q/btsO7FTz8HI/oZKPnGKlBXbGnXz4NcnbZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHJu8q/btsO7FTz8HI/oZKPnGKlBXbGnXz4NcnbZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHJu8q%2FbtsO7FTz8HI%2FoZKPnGKlBXbGnXz4NcnbZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2362&quot; height=&quot;1028&quot; data-origin-width=&quot;2362&quot; data-origin-height=&quot;1028&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2461&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.acmicpc.net/problem/2461&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;분류 : 정렬 + 우선순위 큐&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크 : &lt;a href=&quot;https://www.acmicpc.net/problem/2461&quot;&gt;https://www.acmicpc.net/problem/2461&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;풀이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N개의 반이 있고, 각 반에는 M명의 학생이 있음.&lt;/li&gt;
&lt;li&gt;각 학생마다 실력이 있고, 각 반에서 &lt;b&gt;한 명씩 대표로 뽑아서&lt;/b&gt; 실력 차이를 최소로 하고 싶음.&lt;/li&gt;
&lt;li&gt;즉, N명의 대표를 뽑을 때 &lt;b&gt;최소 실력차가 가장 작은 집합&lt;/b&gt;을 만들고, 그 차이를 출력해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;from queue import PriorityQueue
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; Python 표준 라이브러리의 우선순위 큐 (최소 힙 역할) 사용&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;N개의 반마다 M명의 학생 실력을 입력 받음&lt;/li&gt;
&lt;li&gt;A[i][j]는 i번째 반의 j번째 학생 실력&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;for i in range(N):
    A[i].sort()
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 반의 학생 실력을 정렬해서 &lt;b&gt;가장 작은 수부터 선택할 수 있도록&lt;/b&gt; 함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;pq = PriorityQueue()  # 최소 힙
pos = [0] * N          # 각 반의 현재 선택된 인덱스
max_val = 0
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pq: (값, 반 번호) 형태로 우선순위 큐에 저장&lt;/li&gt;
&lt;li&gt;max_val: 현재 선택된 값 중 가장 큰 값&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;for i in range(N):
    pq.put((A[i][0], i))         # 각 반에서 가장 작은 학생을 우선 삽입
    max_val = max(max_val, A[i][0])  # 초기 최대값 갱신
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 반에서 실력이 가장 낮은 학생부터 시작&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;while True:
    min_val, id = pq.get()     # 현재까지의 최솟값과 그 반의 번호
    answer = min(answer, max_val - min_val)  # 차이 최소 갱신
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 pq에는 각 반에서 하나씩 뽑힌 학생들이 들어 있음&lt;/li&gt;
&lt;li&gt;이 중 제일 실력이 낮은 학생을 꺼냄 &amp;rarr; min_val&lt;/li&gt;
&lt;li&gt;이 집합에서 최대 실력(max_val)과의 차이를 계산해서 answer 갱신&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gml&quot;&gt;&lt;code&gt;    pos[id] += 1
    if pos[id] &amp;gt;= M:
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 반의 다음 학생으로 이동&lt;/li&gt;
&lt;li&gt;만약 그 반에서 더 이상 뽑을 수 없으면 반복 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;    pq.put((A[id][pos[id]], id))
    max_val = max(max_val, A[id][pos[id]])
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 학생을 우선순위 큐에 추가&lt;/li&gt;
&lt;li&gt;최대 실력 갱신&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;# 백준 2461 - 대표 선수
# 분류 : 정렬 + 우선순위 큐

from queue import PriorityQueue

N, M = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]

for i in range(N) :
    A[i].sort()

pq = PriorityQueue()
pos = [0] * N
max_val = 0
for i in range(N) :
    pq.put((A[i][0], i))
    max_val = max(max_val, A[i][0])

answer = 1e9
while True :
    min_val, id = pq.get()
    answer = min(answer, max_val - min_val)

    pos[id] += 1

    if pos[id] &amp;gt;= M :
        break

    pq.put((A[id][pos[id]], id))
    max_val = max(max_val, A[id][pos[id]])

print(answer)
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Programming/백준</category>
      <category>백준</category>
      <category>백준 2461</category>
      <category>백준 2461 파이썬</category>
      <category>백준 대표 선수</category>
      <category>백준 대표 선수 파이썬</category>
      <category>파이썬</category>
      <author>pental</author>
      <guid isPermaLink="true">https://pental.tistory.com/551</guid>
      <comments>https://pental.tistory.com/551#entry551comment</comments>
      <pubDate>Mon, 7 Jul 2025 16:39:10 +0900</pubDate>
    </item>
  </channel>
</rss>