목록해킹 (27)
ii4gsp
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bBbVAX/btqBcMyzkil/pWDY8VePT1lOwu2zuO2BxK/img.png)
LOB는 \xff를 입력했을 때, \x00으로 처리해버려 쉘을 획득하지 못하는 문제가 발생한다. 그래서 bash2를 입력해주고 문제를 풀어야한다. gremlin.c 소스코드를 보면 256byte buffer라는 변수가 선언되있고 argc가 2 이상인지 확인하고 strcpy() 함수로 argv[1]에 buffer를 복사한다. strcpy() 함수에서 취약점이 발생한다. 파일을 복사하여 gdb로 파일을 열어주었다. 를 보면 buffer가 ebp-256에 위치한것을 알 수 있고 buffer의 크기가 256이니 dummy값 없이 buffer - sfp - ret가 된다. strcpy()함수 호출하고 난 바로 다음인 부분을 break point해주고 A로 256개의 값을 채워주었다. NOP중에서 0xbffff91..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/WvBoF/btqA6oEV9bf/bcl4yjMNCyejKwIsrEX49k/img.png)
소스코드가 아주 짧아졌다. gets()함수에서 취약점이 발생한다. gdb로 파일을 열고 disas main을해주고 를 보면 0xffffffd8은 2진수로 1101 1000인데 1의 보수를 해주면 0010 0111이되고 2의 보수를 해주면 +1이 되니 40이된다 buf에서 ebp까지의 거리는 40이다. buf에서 ret까지의 거리는 44가된다 44byte의 값을 채워주고 쉘코드를 넣으면될것 이다. #include int main() { printf("%p\n", getenv("shellcode")); return 0; } shellcode의 주소를 알아내기 위해 c언어로 코드를 작성해주었다. setreuid함수가 없어서 setreuid가 포함된 41byte 쉘코드를 환경변수에 등록하였다. 환경변수 expo..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/cqqGHZ/btqA2T7gZhl/ZNrnuJ5CJNOmqk2DZX8Zk0/img.png)
힌트를 보니 다른 문제와는 다르게 소스코드가 아주 길다. count가 100이상이면 "what are you trying to do?"라는 문장을 출력한다. check가 0xdeadbeef라면 shellout함수를 실행시킨다. 사용자로부터 입력을 받고 입력받은 값에서 1byte를 읽고 1byte의 값이 0x08이면 count 값을 -1한다. byte값이 \r, \n, 0x08 모두 아니라면 string[count]에 입력한 1byte 값을 대입하고 count 값을 +1한다. shellout함수는 쉘을 실행시킨다. 변수가 선언된 순서를보면 string변수가 먼저 선언되고 check변수가 선언되었다. ret변조는 불가능하다 그래서 check값을 0xdeadbeef로 해줘야한다. check변수가 string보..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/dW0UbD/btqA2ORe1cl/xSpyUtSKmHaKP2lTbq5CD1/img.png)
level16과 비슷하다 shell을 실행시키는 함수 부분이 없다. 쉘 코드를 환경변수에 등록하여 문제를 풀면 될 것 같다. - 0xffffffc8은 [ebp-56]이다. buf에서 ebp까지의 거리다. - 0xfffffff0은 [ebp-16]이다. call에서 ebp까지의 거리다. buf에서 call까지의 거리 = 56 - 16 = 40 export shellcode=$(python -c 'print "\x90" * 20 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"') 쉘 코드를 환경변수에 등록해주고 #include int main() { printf("%p\n..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/duzLVt/btqA050sCDd/4nnjckbrK8WCEt1JgcNblK/img.png)
fgets()함수때문에 ret조작은 불가능하고 *call의 주소 값을 shell함수 주소로 조작해주면 될 것 같다. - 0xffffffc8은 [ebp-56] 즉, buf에서 ebp까지의 거리는 56이다. - 0xfffffff0은 [ebp-16] call에서 ebp까지의 거리는 16이다. buf에서 call까지의 거리는 56 - 16 = 40 shell함수의 시작 주소는 0x080484d0이다 buf ~ call까지의 거리를 쓰레기 값으로 덮어주고 + shell함수 주소를 리틀 엔디언 방식으로 덮어주면 될 것이다. payload (python -c 'print "\x90" * 40 + "\xd0\x84\x04\x08"';cat) | ./attackme
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/7niaU/btqA04NTZuo/Nwt63KONs8hgUhzNHZA4k0/img.png)
힌트를 보면 gets()함수가 아닌 fgets()함수를 써서 45byte만큼의 입력만 받아 ret변조를 불가능하게 만들어뒀다. check의 값을 0xdeadbeef로 변조를해서 쉘을 실행시켜야한다. attackme를 tmp에 복사하고 gdb로 분석을 해보자 에서 0x38만큼 할당해주었다. 0x38은 10진수로 56byte이다. crap[4byte] + check[4byte] + buf[20byte] = 28byte 컴파일러가 생성한 dummy는 28byte이다. 에서 0xffffffc8은 2진수로 1100 1000인데 1의 보수를 해주면 0011 0111에서 2의 보수를 구하면 +1이 되니 56이된다. ebp-56 위치 주소를 eax로 옮기는 걸 알 수 있다. 에서 eax를 스택에 올리고 fgets()함..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/ygKGU/btqAY6MhmJt/NsleCMBA6Rd1hKKxeEVvxk/img.png)
디버거 프로그램을 탐지하는 함수를 찾아보자 프로그램을 실행하면 "정상"이라는 문자가 출력된다. 올리디버거로 프로그램을 열어 실행하면 "디버깅 당함"이라는 문자가 출력된다. Search for -> All intermodular calls를 클릭하고 IsDebuggerPresent라는 함수가 보인다. 함수이름부터 IsDebuggerPresent이기 때문에 디버거를 탐지한다고 의심하였다. 더블클릭을 하여 IsDebuggerPresnt함수가 실행되는 영역으로 이동해주었다. IsDebuggerPresent함수를 호출하는 부분에서 break를 걸고 실행하면 아무런 문자도 출력이 안된다. EAX레지스터의 값을 확인해보니 0이다. IsDebuggerPresent함수를 호출하고 난 다음의 명령인 CMP ESI, ESP..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/cAZkPK/btqA06xV3BL/sjpzDoKLkMlAOQmLkr14MK/img.png)
문제를 보니 스트링 비교함수를 찾아내는것 같다. 프로그램을 실행하여 Regcode부분에 임의의 값을 넣어보자 에러 문자가 뜨는것을 볼수있다. 올리디버거로 파일을 열고 문자열 비교함수 찾아보자. 우클릭을 눌러 Search for -> All intermodular calls를 눌러주면 해당 프로그램에서 쓰고있는 함수들을 볼수있다. StrCmp이라는 문자열 비교함수를 찾을수있다. 더블클릭을 하면 StrCmp함수가 사용되고있는 부분으로 이동한다. "2G83G35Hs2"를 push하고 StrCmp함수를 호출하여 문자열을 비교한다. "2G83G35Hs2"를 패스워드에 입력해보자. 해석) 감사합니다, 비밀번호가 맞습니다 성공