목록hackerschool (20)
ii4gsp
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bVVFec/btqA7rh8wde/5y8poJ6ia1HIMAzT81Otsk/img.png)
첫 번째 문제와 크게 달라지진 않았다. 하지만 버퍼의 크기가작아 쉘코드를 환경변수에 등록하면 될것 같다. strcpy() 함수에서 취약점이 일어난다. 파일을 복사해주고 gdb로 열어보면 스택의 구조는 buffer - sfp - ret이다. #include int main() { printf("%p\n", getenv("shellcode")); return 0; } 쉘코드의 주소를 알아내기 위해 소스코드를 작성해주고 25byte 쉘코드를 환경변수에 등록해주고 아까 작성한 코드를 실행하여 쉘코드의 주소를 알아내었다. 페이로드 작성은 buffer[16byte] + sfp[4byte] + ret가 된다. payload ./cobolt $(python -c 'print "\x90" * 20 + "\x61\xff\..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/boFkq4/btqA9AZQZ8C/eAuDhSkmKuoNfZtHGWB4wK/img.png)
bleh의 버퍼는 80byte의 크기인데 fgets() 함수로 버퍼를 79byte만큼 입력을받아 버퍼 오버플로우는 힘들것 같다. 하지만 printf() 함수에서 포맷스트링 버그가 일어난다. 서식문자를 입력하니 메모리를 읽어서 출력한다. 문자와 서식문자를 같이 입력하니 입력한 A의 값 41414141이 보인다. gdb로 disas main을하니 main symbol을 찾을 수 없다고 한다. .dtors를 활용 하면 될 것 같다. gcc는 컴파일 할 때 .ctors와 .dtors 두 세그먼트를 생성한다. .ctors는 main() 전에 실행되고 .dtors는 main() 종료 후에 실행된다. main()이 종료되고 .dtors함수가 실행되기 전에 쉘 코드 주소 넣으면 된다. .dtors 세그먼트의 주소는 0..
![](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/vQ54b/btqA4z6RQuR/8fd0ADDK9s4ATwAFHdGxKK/img.png)
힌트파일을 보면 level14문제에서 보았던 check변수를 포인터로 바뀐것을 알 수 있다. 포인터 변수는 메모리의 주소 값을 저장하는 변수이기 때문에 check변수에 들어가는 값은 메모리 주소의 값이 저장된다. - 0xffffffc8은 ebp-56이다. - 0xfffffff0은 ebp-16이다. 따라서 buf에서 *check까지의 거리는 56 - 16 = 40 40byte라는 빈공간을 채워줘야 할 것이다. - 0xdeadbeef와 *check 포인터가 값을 비교한다. 메모리 상에서 0xdeadbeef의 주소를 알아내 *check의 주소를 0xdeadbeef의 주소로 덮어 씌우면 쉘이 실행될 것이다. 0x080484b2가 0xdeadbeef의 메모리 상의 주소이다. 이제 페이로드를 작성할 수 있을 것이다..
![](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()함..