본문 바로가기

Storehouse/Diary

[Grotesque] aeg (2020.10.03 클리어)

추석에 맛난거 먹고 띵가띵가 놀고.. 방에서 굴러다니다가 할 게 없어서 pwnable.kr에 접속했다.

 

뭐풀지.. 이것저것 깔짝깔짝 보다가 aeg가 점수가 좀 높기도 하고 재밌어보여서 문제를 열어봤다. 

 

 

 

 

 

 

nc pwnable.kr 9005를 입력하니까, 뭔 10초 안에 페이로드를 짜서 달라는데, 그 뒤에는 수천?? 개의 문자를 주더라.

 

머리에 ????????? 가 수백개 떴다가 aeg의 맨 위 문장에서 base64 encoding 되어있다는 글을 보고, 바로 복호화한 후 압축을 풀어봤다.

 

 

 

 

hmm.. strip 옵션이 적용됬나.. 싶다가도 plt 주소가 보이는걸 보면 그건 또 아닌 것 같고. (사실 오래되서 strip가 정확히 뭘지우는지 기억안난다)

 

여튼 main entry 주소가 안보이니, readelf 도구를 사용해봤다.

 

 

 

 

보인다. 이 쯤 어딘가에 있나보다.

 

0x658000 주변의 어셈을 쭉 훑어보다가 왠지 entry point인 것 같은 부분을 찾은 것 같다. 그 부분을 쭉 읽어봤다.

 

보니까 대충..

1. argv[1]에 값이 들어있는지 확인하고

2. argv[1]의 값이 2000 byte를 넘기지 않았는지 확인한 후, 넘기지 않았다면 각 문자를 특정 값과 xor한다.

  - 홀수번째 문자와 짝수번째 문자를 각각 다른 값으로 xor하여 문자열을 encoding한다.

3. encoding한 값이 해당 바이너리(aeg_binary)의 특정 연산을 통해 만들어진 문자열과 값이 같은지 비교한다.(cmp) 

  - 총 48바이트를 비교한다.

4. 값이 모두 일치하면 ebp - 10인 위치에 우리가 입력한 값을 덮는다. 단, 우리가 입력한 문자열은 2번과정에서 encoding된 값이 들어간다.

5. aeg 서버에서 바이너리를 받아올 때마다 entry 주소값, xor 값, 48바이트 비교를 위한 문자열 연산식이 무작위로 바뀐다.

 

 

간단하게 훑어봤을 때 내린 결론은 이렇다. aeg 서버에서 주는 바이너리에 48바이트의 특정 값을 계산해서 argv[1]에 넣으면, memcpy 함수를 이용해 48바이트 이후의 문자열을 특정 주소에 덮을 수 있다. 덮는 부분에 ebp가 존재하니, ebp 컨트롤을 통해 쉘코드가 들어있는 곳을 가리키면 flag를 얻을 수 있을 것 같았다.

 

근데 여기서 문제는 48바이트를 어떻게 계산하느냐이다. 어떻게할까 한참 생각하다가 angr이라는 모듈이 생각났다. 몇년 전부터 엄청 핫해서 얘기는 많이 들어봤지만, 그 때는 대학원생이어서 만질 기회조차 없었던.. 그 angr을 써보면 될 것 같았다.

 

angr을 적당히 찾아보니, symbolic execution으로 바이너리를 실행하는 것 같았다.

a라는 목적지 주소(find)와 n개의 회피 주소(avoid)를 입력해주면, angr가 symbolic execution을 통해 입력 주소를 알아서 tracing하는 것 같았다.

angr을 이용하기로 마음먹었으니 목적지 주소와 회피 주소를 찾아내야 했다.

목적지 주소야 뭐.. memcpy가 실행되는 곳으로 설정하면 될 것 같고, 회피 주소는.. 아마도 48바이트를 계산하는 과정에서 자꾸 leave, ret으로 보내는 jne 점프문을 활용하면 되지 않을까 싶었다.

그래서 이런 명령어를 입력해봤다.

 

 

 

 

다행히 중간에 걸리적거리는 명령어가 없었다. 3번째줄부터가 48바이트 비교문에서 볼 수 있는 jne 명령어인데, 이걸 avoid 주소로 쓰면 되지 않을까 생각했다.

근데 명령어를 저렇게 쓰면 원하는 avoid 주소를 받아오기 어려우니,,

 

 

 

 

 

이런 느낌으로 한줄씩 받아오면 되지 않나?? 생각했다.

objdump로 받아온 값 중 원하는 값을 잘 저장해서 find, avoid 주소로 지정한 뒤 exploit 코드를 짜면 flag를 얻을 수 있을 것 같은데..

내일 시간된다면 이어서 풀어봐야겠다.

 

2020.10.02

===============================================================

 

 

angr 사용이 미숙하다보니 이리저리 삽질을 좀 많이 하게 됐다.

역시 삽질을 많이 해야 하나씩 지식이 얻어지는 듯 하다.

 

아직까지는 aeg key값 48바이트를 얻을 때 너무 오래걸린다. 10초 안에 구해야하는데!

 

2020.10.03

===============================================================

풀었다. 첫날(2020.10.01)에 깔짝 봤을 때는 그냥 rbp 컨트롤해서 쉘코드만 때려넣으면 되는 줄 알았는데, heap에는 실행권한이 없더라.

그래서 mprotect 이용해서 rop exploit코드를 작성했고, 권한을 요리요리조리조리 잘 줘서 풀었다.

angr entry point를 잘 바꿔보니까 48바이트 키가 한 3초안에 나오더라..

 

정말 신박하고 재밌었던건 gadget을 꼭 pppr을 찾을 필요가 없다는걸 깨달았다.

이제 서버공격용으로 코드 간단하게 수정하고 .. 글 쓸 준비해야겠다.

..

 

개인적으로 이 문제는 너무 재밌어서 PoC 코드도 공개하고 싶은데, 후... 260명만 푼 문제라 공개하기엔 애매하고..

고민좀 해봐야겠다.

 

 

문제 풀고 느낀건데, angr에 미숙해서 클리어타임이 늦은 것도 있는데 symbolic execution 원리만 알았다면 훨씬 더 빨리 풀지 않았을까 싶다. 나중에 꼭 symbolic execution을 공부해봐야겠다.

'Storehouse > Diary' 카테고리의 다른 글

책 집필을 슬슬 준비하고 있습니다.  (2) 2020.12.21
[Grotesque] maze 클리어  (0) 2020.10.11
책을 써보고 싶은데..  (2) 2020.09.30
[Grotesque]asg (2020.08.09 클리어)  (0) 2020.07.19
SANE 연구실 소개  (0) 2020.07.13