[exploit writing] 1_스택 기반 오버플로우 (6)
목표
EIP 가 쉘코드의 시작 주소로 점프도록 하는 것이 좋지 않은 방법이라는 것을 깨달음(즉, 0x000ff730으로 EIP를 덮어씀)
과정
1. 그럼 이제 간단한 테스트를 해보자. 먼저 26,064개의 A를 입력하고, 000ff730으로 EIP를 덮어쓰며, 그런 다음 25개의 NOP를 입력하고 브레이크, 마지막으로 추가적으로 NOP를 입력한다. 만약 모든 것이 정상이라면 EIP는 NOP를 가지는 0x000ff730으로 점프할 것이다. 그리고 나서, 해당 코드는 브레이크까지 이동하게 된다.my $file = "crash25000_jump.m3u";
my $junk = "\x41" x 26064;
my $eip = pack('V', 0x000ff730);
my $shellcode = "\x90" x 25; # 0x90 = NOP
$shellcode = $shellcode."\xcc"; # 0xcc = Break
$shellcode = $shellcode."\x90" x 25;
open($FILE, ">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created Successfully \n";
NOP는 no operation, 아무것도 하지는 않으나 EIP 값을 다음 명령줄 코드로 바꿔주는 역할을 하는 명령어이다. 그래서 위의 코드는 25개의 NOP를 지나 CC를 만나 BREAK 될 것이다.
2. 우리는 어플리케이션에 충돌이 발생한 다음 access violation이 아닌 break 발생을 의도했다. EIP를 보면 의도대로 0x000ff730을 가리키고, ESP 또한 그렇다. 하지만 ESP를 덤프해 보면 우리의 예상과 어긋났다는 것을 확인할 수 있다.
3. 여기서 얻은 교훈은 바로 '특정 메모리 주소로 직접 점프하는 것'이 좋은 솔루션이 아니라는 것이다. 0x000ff730은 null 바이트를 가지고 있으며, 이는 흔히 말하는 종단 문자이기 때문에 원하는 지점까지 프로그램을 도달하게 하지 못해 공격에 실패하게 한다.
4. 결론적으로, 앞서 의도한 것처럼 0x000ff730과 같이 직접적인 메모리로 EIP를 덮어쓸 수는 없다. 대신에, 어플리케이션이 우리가 제작한 코드로 점프하게 만들도록 하는 방법이 있다.
5. 이상적으로 우리는 레지스터(혹은 레지스터에 대한 offset)를 참조할 수 있어야 하며(현재의 경우 ESP), 그 레지스터로 점프하는 함수를 찾아야 한다. 그런 다음, 우리는 그 함수의 주소로 EIP를 덮어쓸 수 있을 것이다.
6. 우리는 ESP가 가리키는 곳에 정확히 우리의 쉘코드를 삽입할 수 있었다. (엄밀히 말하자면, ESP가 쉘코드의 시작 부분을 직접적으로 가리키게 했다.) ESP의 주소로 EIP를 덮어쓰는 이유는 프로그램이 ESP로 점프해 쉘코드를 실행하기를 원하기 때문이다.
7. ESP로 점프하는 것은 윈도우 어플리케이션에선 아주 흔한 일이다. 사실 윈도우 어플리케이션은 자체적으로 명령어 코드를 가지는 하나 이상의 dll을 가져와 사용한다. 그리고 이 dll에 의해 사용되는 주소들은 정적이다.
8. 만약 우리가 ESP로 점프하는 명령을 가진 dll을 발견할 수 있다면, 그리하여 우리가 해당 dll에 있는 그 명령의 주소로 EIP를 덮어쓸 수 있다면 쉘코드 실행이라는 소기의 목적을 달성할 수 있을까?
출처 : Exploit Writing By Corelan
댓글
댓글 쓰기