hackctf에서 풀어보는 첫번째 포너블이다. 재밌겠다ㅎㅎ
문제파일을 ida로 열어봤다.
사진은 짤렸지만 fgets에서 stdin으로 입력을 받고, buf의 내용과 check의 주소를 출력해준다.
check와 0x4030201을 비교하고 같으면 0xDEADBEEF와 비교한다. 그것도 같으면 you are on the right way ! 을 출력한다.
하지만 check가 두개의값을 동시에 만족할수는 없으니 눈속임에 불가하다. 두 값을 비교해 맞았든 틀렷든
loc_8048543 으로 이동하고 check와 0xDEADBEEF를 비교한다. 맞으면 Shell을 열어준다.
GDB로 열어보면 버퍼의 주소는 EBP-0x34이고, check의 주소는 EBP-0xC이다.
fgets로 입력받기때문에 버퍼오버플로우가 발생하고, 우리는 EBP-0xC값을 수정할수있다.
0x34 - 0xC = 28h (40) 이므로 DUMMY 40개 + DEADBEEF 로 payload 를 작성해 nc로 보내면 된다.
최종payload = (python -c "print 'a'*40+'\xEF\xBE\xAD\xDE' ";cat) | nc ctf.j0n9hyun.xyz 3000
[cat를 붙이는 이유]
payload를 전송하고 세션을 유지해야 쉘을 사용할수있기때문이다
[DEADBEEF를 역순으로 전송하는 이유는]
리틀엔디언에서 정수는 역순으로 저장되어 check값과 비교하는 0xDEADBEEF는
메모리에 EF BE AD DE 로 저장되어있다. fgets는 문자열로, 순서대로 입력을 받기때문에
정수인 check값에 정수형식으로 똑같이 EF BE AD DE 이렇게 넣어줘야 check에 0xDEADBEEF가 들어가게된다.
[\x 를 붙이는 이유]
문자로 넣어줘야하기때문이다. \x 없이 EF를 전송한다면 [E의 ASCII코드값] + [F의 ASCII코드값] 이 들어가게된다.
\x를 붙이면 문자가된다. ex ) A = \x41 (16진수값)