Neko


'~ 2015/컴퓨터공부'에 해당되는 글 6건

  1. 2015.09.22 Bufferoverflow 기법 정리
  2. 2015.09.05 핸드레이
  3. 2014.07.22 strace, 제가 한번 사용해 보겠습니다.
  4. 2014.05.18 Buffer Overflow (3)
  5. 2014.04.06 Frame Pointer Overwrite/One Byte Overflow (5)
  6. 2014.03.11 MISCCCCCCCCCC!

https://docs.google.com/document/d/15d3f0ZEKxYXsrUNybTQlONGyxY9MVhb8NgDJAPNRCkU/edit?usp=drive_web


나름 공들여서 썼었던 기억이 난다. 기말고사 기간동안...

'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼


작년에 한동안 학교다니면서 짬짬히 했었던거. 쏟은 시간에 비해 결과물은 비루하다. 오랜만에 파일정리하고있었는데 나오드라. 나중에 시간되면 갖고있는 나머지도 다 해봐야될듯. 근데 이거 두 개 하고서는 꽤나 어셈에 대한 두려움이 없어져갖고 신기했었다. 뭐든지 다 읽을 수 있는기분ㅋ 

요즘은.. 어셈보면.. 심란하다...


그리고 누누히 말하지만 나는 포인터들이 싫다. (정색)


re(完).docx

re3(完).docx






'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼

http://www.linuxintro.org/wiki/Strace 를 참고하겠습니다!


저는 지금 이 글을 쓰는 지금 strace를 전혀 쓸줄 모름니다. strace <file>로 실행시킬 수 있다는거밖에 모름.

자 그렇다면 같이 해봅시다. 헬로월드 프로그램을 짜서 분석해보죠

[nightmare@localhost nightmare]$ cat hello.c

#include<stdio.h>

int main()

{

printf ("Hello, World!\n");

return 0;

}


컴파일하고 strace ./파일명 으로 우선 결과물을 출력해줍시다.


[nightmare@localhost nightmare]$ strace ./hello

execve("./hello", ["./hello"], [/* 22 vars */]) = 0

brk(0)                                  = 0x8049548

old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40014000

open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)

open("/etc/ld.so.cache", O_RDONLY)      = 3

fstat(3, {st_mode=S_IFREG|0644, st_size=12210, ...}) = 0

old_mmap(NULL, 12210, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40015000

close(3)                                = 0

open("/lib/libc.so.6", O_RDONLY)        = 3

fstat(3, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0

read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212"..., 4096) = 4096

old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x40018000

mprotect(0x40105000, 30812, PROT_NONE)  = 0

old_mmap(0x40105000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xec000) = 0x40105000

old_mmap(0x40109000, 14428, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40109000

close(3)                                = 0

mprotect(0x40018000, 970752, PROT_READ|PROT_WRITE) = 0

mprotect(0x40018000, 970752, PROT_READ|PROT_EXEC) = 0

munmap(0x40015000, 12210)               = 0

personality(PER_LINUX)                  = 0

getpid()                                = 1120

fstat64(0x1, 0xbffff364)                = -1 ENOSYS (Function not implemented)

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0

old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40015000

ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0

write(1, "Hello, World!\n", 14Hello, World!

)         = 14

munmap(0x40015000, 4096)                = 0

_exit(0)                                = ?


"To analyze strace's output you must know that the first keyword in a line of output from strace is always a syscall like open or read. Then, in parantheses, the arguments follow, then the result. "

우선 strace의 출력의 첫 키워드는 시스템콜이고, 괄호안에는 전달되는 인자라네여. 그리고 뒤에 결과가 따른다고 합니다. 아마 뒤에 = 한게 결과겠죠?

ㅋㅋ맞다고 써있네요.


"Every line follows the syntax

syscall(arguments) = return value

친절하게 시스템콜이 어떤 동작을 하는지 모르겠다면 man 2 <systemcall>이렇게 찾아보라고도 하네요.

어.. 근데 생각해보니 이게 다네요?

헐?

끗.


analysis

근데 old_mmap랑 mmap 랑 munmap 랑 같은거 같은데 뭘 하는지는 잘 감이 잡히지 않네요. 근데 왜 그동안 strace..이걸 안쓰려고 했나 모르겠ㅅ브니다. 역시 하고봐야 되는듯. 그동안 무서워서 못건드렸거든옄ㅋㅋㅋㅋㅋㅋㅋㅋ 이런..


++) mmap는 근데 메모리에 어떤 장치가 사용할 메모리를 할당해주는 것인 것 같은데, 그렇다면 각각 함수, 즉 open 이나 read, write같은 함수가 사용하는 공간을 만들어주는 것인가요? 위에 strace를 보면 각각 함수들 실행시키기 전에 하나씩 있는걸 보니..

'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼

조금 너무 간결한 개념설명(정리)

RedHat 6.2 기준 스택 버퍼오버플로우에 대한 글 입니다.

모든 지적 다 감사히 받습니다


정말 개념만 설명하고 싶었습니다. 가장 기본적인 것들만 적어놓았으니 이런 개념이구나 참고만 하시기 바랍니다 :)


[1] Buffer Overflow (BOF)

#include<stdio.h>

main(int argc, char *argv[])

{

char buffer[40];

strcpy(buffer, argv[1]);

printf("%s\n", buffer);

}


이런 코드가 있을 때 메모리의 상황은

(낮은 주소)[buffer(40 bytes)] [(Saved)Frame Pointer(4 bytes)] [Return Address(RET) (4bytes)](높은 주소)

이렇게 되게 된다.  (스택이 자라는 방향: 낮은주소 ← 높은주소, 스택은 LIFO(Last-In-First-Out))


*)SFP(Saved Frame Pointer)란?- 처음에 함수 프롤로그(push %ebp)에 의해 저장된 EBP의 값이다 (함수에서 지역변수들이 사용될 때 그 기준으로 EBP가 쓰이는데 타 함수로 넘어갈 경우 다시 돌아왔을 때 ebp를 복귀시켜야 하니 저장해두는 값. 함수가 시작했을때 당시 최초의 EBP 주소를 가리키고 있다)

*)RET(Return Address)란?- EIP(Extended Instruction Pointer)가 가리킬 곳을 가르쳐주는 주소값. EIP는 프로그램이 끝난 후 돌아갈 주소를 가지고 있다.


위의 소스에서 strcpy때문에 버퍼오버플로우가 생기게 되는데, 만약에 버퍼(유저입력으로) 48바이트를 넣는다면 유저의 입력이 버퍼인 40바이트 뿐만아니라 버퍼 뒤에 있는 SFP와 RET까지 덮어버려 프로그램의 실행을 바꾸기 때문이다. RET는 EIP, 즉 함수 실행이 끝난 뒤 어디로 EIP가 가야 할 지 가르쳐주는 역할을 가지고 있기 때문에 만약에 사용자가 RET를 덮어쓴다면 사용자가 입력한 주소로 프로그램의 실행이 계속 되게 된다. 이를 이용해 버퍼에 쉘코드를 넣고 RET를 버퍼의 시작 주소값 또는 NOPSLED 중 하나의 주소값으로 설정한다면 EIP는 버퍼로 가 쉘코드를 그대로 실행하게 된다.


예시:

Payload= "\x90"x20bytes, "Shellcode"x24bytes, "Buffer Address"x4bytes


*)NOPSLED란?- NOP(No OPeration)는 (Intel x86 CPU기준으로)"\x90"을 뜻하는데, 이 명령은 아무 동작도 하지 않고 다음 명령으로 넘어가라는 뜻이다. 만약에 NOP가 900개 있고 그 후에 쉘코드가 있다면 ESP(Extended Stack Pointer- 실행하는 명령을 가르키는 포인터)는 NOPSLED(미끄럼틀같이) 아무 명령도 실행하지 않고 계속 진행하다가 마지막에 있는 쉘코드를 실행하게 된다.

*)Little Endian이란?- 엔디안은 메모리에 수를 저장하는 방식인데, 차이점은 빅 엔디안과 리틀 엔디안에 12345678을 넣게 된다면, 빅 엔디안(이 방식을 쓰는 컴퓨터는 별로 없다)은 12 34 56 78로 메모리에 적재하는 반면 리틀 엔디안은 뒤에서부터 78 56 34 12 이렇게 두바이트씩 끊어 거꾸로 넣게 된다. 고로 리턴 어스레스 같은 경우에도 페이로드에 거꾸로 뒤집어 준 후 넣어야 한다. \x~~\x~~\xff\xbf <- 이런 식

설명은 <http://itguru.tistory.com/71>을 참고했습니다



[2] Return-to-Libc (RTL)

Libc란 공유 라이브러리를 뜻한다. 이 공유 라이브러리는 프로그램이 호출될 때 사용되는 함수를 포함하고 있으며 프로그램이 언제든지 함수를 호출할 때 사용된다.

아까와 같은 코드가 있다면, (위에서 다시 가져와보자)

#include<stdio.h>

main(int argc, char *argv[])

{

char buffer[40];

strcpy(buffer, argv[1]);

printf("%s\n", buffer);

}

물론 아까처럼 버퍼오버플로우를 사용하여 공격할 수도 있다. 하지만 이번에는 Libc를 사용해 공격해볼 것이다.

쉘을 따려면 system("/bin/sh");를 실행시키면 된다

프로그램을 gdb로 메인에 브레이크포인트(b main)를 건 후, 실행시킨 후 브레이크포인트에서 p system을 하면 system함수의 주소가 나온다.

RET를 이 시스템 함수의 주소로 하고, 그 후 4바이트 뒤에 &"/bin/sh" (/bin/sh의 주소) 를 넣으면 system이 ebp+8부터 인자를 참조하기 때문에 system("/bin/sh"); 를 실행하게 된다.

ebp+4에는(system함수 주소 뒤, /bin/sh주소 앞) 더미를 넣거나, 깔끔하게 끝내고 싶다면 exit의 주소를 넣으면 된다. 이곳은 system실행 후 돌아갈 ret을 저장하는 곳이기 때문이다.

예시:

Payload= "\x90"x44bytes, "system address"x4bytes, "exit address"x4bytes, "/bin/sh address"x4bytes



[3] RTL Chaining (Chaining RTL Calls)

RTL Chaining, 이건 위의 RTL과 비슷한 개념이다.

만약에 위와 같은 코드에 strcpy를 두번, system을 한번 이렇게 연속으로 실행하고 싶다고 가정해보자.(걍 머리에 떠오르는 함수,...)

그렇다면 이것들을 어떻게 실행시켜야 할까?

strcpy의 인자는 2개(char *dest, const char *source)이다. 인자가 하나라면 (function) (function) (argv) (argv) 이렇게 끼워서 두 번 실행시킬 수 있겠지만, 늘 함수 주소 뒤의 4바이트를 인자로 참조하기 때문에 인자가 2개인 strcpy는 1번 이상 사용할 수 없다.

&strcpy &strcpy(x) &dest &source <...어떻게 전달하지?>


RTL Chaining을 사용하면 된다!!(??뜬금 느낌표)

우선 개념도를 적어놓겠다.

&strcpy &poppopret &dest &source &strcpy &poppopret &dest &source &system &exit &/bin/sh

pop- Stack에서 데이터를 빼는 것 말고도 pop는 esp+4를 하게 되기 때문에 다음 인스트럭션을 가르키게 된다. 이 경우에는 가젯이 pop pop ret이기 때문에 strcpy를 실행하고 인자를 두 개 전달한 뒤, pop pop ret을 이용해 두 인자를 건너뛰고 그 뒤에 있는 두 번째 strcpy의 주소를 ret하여 다시 실행하게 되는 것이다.

*)가젯(Gadget)이란?- 프로그램 내부의(함수에) 기계어로 된 ret로 끝나는 코드의 조각으로써 필요한 가젯을 찾아 공격자의 마음대로 사용하면 된다

만약에 건너뛰어야 하는 인자가 3개라면, pop pop pop ret, 하나라면 pop ret을 찾아 사용하면 되는 것이다.


[4] SFP overwrite (One-byte Overflow)


[5] Fake EBP (FEBP)

<기말공부다하고돌아오겟슴니다>


'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼

어제 golem을 푸는데에 사용한 frame pointer overwrite에 대해 간단하게 아는만큼만 쓰려고 합니다.


#include <stdio.h>

#include <stdlib.h>


void problem_child(char *src)

{

        char buffer[40];

        strncpy(buffer, src, 41);

        printf("%s\n", buffer);

}


main(int argc, char *argv[])

{

        if(argc<2){

                printf("argv error\n");

                exit(0);

        }


        problem_child(argv[1]);

}


이 소스를 한번 뜯어봅시다.

void problem_child(char *src)

{

        char buffer[40];

        strncpy(buffer, src, 41);

        printf("%s\n", buffer);

}

-> buffer는 40바이트밖에 없는 반면, strncpy에서는 src에서 buffer으로 41바이트를 복사합니다.


(low)[buffer] [sfp] [ret](high) 가 있다 함은,(함수의 인자가 어떤 형식으로 스택에 보내지는지는 모르겠습니다) 41바이트를 복사하기 때문에 buffer를 지나 sfp 한 바이트를 변조 할 수 있는 것이죠.

problem_child의 sfp에는 후에 메인 함수로 복귀하기 위해 main 함수의 sfp전의 주소가 저장되어 있게 됩니다. 후에 실행할 명령이 더이상 없기 때문이죠.


이 함수의 leave 명령을 하게 되면,

leave:

mov ebp, esp

pop ebp


이 명령들에 의해 esp를 ebp가 있는 곳(sfp가 있는 곳)으로 이동시키고, pop ebp를 하여 ebp를 복귀시키며 동시에 esp에도 4를 더하게 됩니다.(여기서 알고있어야 하는것은 sfp에 있던 값이 변조된 값이라 sfp를 참고한 ebp는 메인으로 복귀하지 않고 이상한 곳으로 날아갔다는 점입니다. 이걸 악이용해 해커는 ebp가 원하는 곳으로 가게끔 변조할 수 있습니다.)

leave 후 ret 명령이 실행되는데요(모두 problem_child안에서 일어나고 있습니다), 이것은 eip에 ret(ebp+4)에 저장되어있는 주소를 넣어 후에 실행할 코드의 주소를 알려주게 됩니다. 여기서, ebp는 현재 변조된 sfp에 의해 이상한 주소로 날아가 있기 때문에, 그 주소에서부터 4바이트를 읽어들여 eip에 넣게 됩니다. 결과적으로 이상한 곳에 있는 이상한 데이터를 eip에 넣게 되는 것입니다.


어제 풀 때 사용한 노트를 보면,

 argv[1] = [one of the nopsled's addr] [nopsled] [shellcode] [the byte that overflows the fp]

 has to equal 41bytes

라는 내용이 있습니다. 


fp는 메인함수를 가르키고 있기 때문에 주소값의 앞 6자리는 같았습니다. 그 후, 우리가 사용할 수 있는 공간은 argv[1]이었기 때문에 fp를 변조해 ebp가 argv[1]-4의 주소를 가리키고 있게 하였습니다. argv[1]은 위에 구성한 것처럼 앞의 4바이트가 ret로 인해 읽혀야 하니 주소값을 넣어야 합니다. 고로, 앞의 4바이트는 뒤에 넣은 nopsled중 한 곳을 가리키게 하였습니다. ret가 실행된 후 nopsled를 타고 쉘코드가 실행되게 할 수 있기 위함이죠. strncpy에서 41바이트가 복사되어야 하니 마지막 바이트는 fp를 변조할 값을 넣었습니다. 이렇게 해서 leave에서 변조된 ebp가 &(argv[1])-4로 점프하고, pop esp로 esp는 problem_child 의 ret명령을 실행하고, ebp는 4바이트 늘어난 뒤 ret를 가리키는줄 알고 argv[1]의 첫 4바이트를 eip에 넣게 됩니다. 그러면 eip는 그 주소(이 경우 nopsled)로 점프하여 그 후 나오는 명령, (여기선 쉘코드)를 결과적으로 실행하게 됩니다.

 

fpo가 메인함수에서 안되는 이유는 모르겠지만, 제 생각으로는 타 함수들은 메인으로 돌아가기 위해 sfp를 주소 복구용으로 사용하는 반면, 메인 함수는 돌아가야 할 주소가 필요 없기 때문에 메인함수에서는 실행이 안되는것 같습니다. 메인 함수는 _libc_start_main으로 돌아가야하죠.. 없는 디버깅 실력을 모아 메인 함수를 따라가 봤는데, sfp가 있는 곳에는 0x00000000이 있드라구여. 그 후에 있는 ret 주소는 start함수를 가르키고 있었는데.. 워낙 디버깅 실력이 없어서 더는 못찾아봤어요.ㅋㅋ..


이거 쓰고보니 한국어 참 어렵네요.. 뭔가 설명이 오묘하다.


http://research.hackerschool.org/Datas/Research_Lecture/sfp.txt

꼭 참고하시기 바랍니다 :)

'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼


MISCCCCCCCCCC.pdf


장난으로 시작한걸 정말 쓸 줄은 몰랐슴다.

근데 이거 쓰기 시작한건 작년에 시작했는데 중간에 묵혀두다가 오늘 발견하고 후딱 끝내버렸다..

뭔가 조금 허술한 감이 없지않아 많지만, 문서를 쓰는거에 조금 익숙해져야겠다 하고 연습겸 쓴 것 같아요.

언리밋님.. 예제에 풀이를 썼는데... 양해해주세요 +_+..

쓰는건 재미있었습니다ㅋㅋ 컬러풀하니 예쁜가요?

구글드라이브에서 적어서 포맷이 어케되었는지 확인하기 두렵습니다..

'~ 2015 > 컴퓨터공부' 카테고리의 다른 글

Bufferoverflow 기법 정리  (0) 2015.09.22
핸드레이  (0) 2015.09.05
strace, 제가 한번 사용해 보겠습니다.  (0) 2014.07.22
Buffer Overflow  (3) 2014.05.18
Frame Pointer Overwrite/One Byte Overflow  (5) 2014.04.06
MISCCCCCCCCCC!  (0) 2014.03.11
Posted by 에버토끼