profile image

L o a d i n g . . .

article thumbnail image
Published 2021. 3. 11. 14:39

NOP은 "No OPeration"의 약자로, 명령어 중의 하나다. NOP은 xchg eax, eax와 같이 프로그램의 실행에 영향을 주지 않는 명령어이기 때문에, 프로그램이 실행 중에 NOP 명령어를 만나면 다음 명령어로 넘어가는 것과 같은 효과를 준다.

 

x86 아키텍처의 NOP 명령어 바이트코드는 0x90이다.

NOP Sled, 혹은 NOP Slide주로 셸코드의 주소를 정확히 알아내기 힘들 경우 큰 메모리를 확보하여 셸코드 주소의 오차 범위를 크게 만들 때 사용한다.

 

예를 들어, 0x100 주소에 셸코드가 저장되어 있다고 가정해 보자. 만약 NOP Sled가 없다면 정확히 0x100 주소로 실행 흐름을 바꿔야 셸코드가 실행된다. 하지만 셸코드 앞에 0x10000바이트의 NOP Sled를 붙인다면 0x100 ~ 0x10100 주소 중 임의의 주소로 실행 흐름을 바꾸기만 하면 된다.

 

 

#include <stdio.h>
int vuln(char *src) {
  
  char buf[32] = {};
  
  strcpy(buf, src);
  return 0;
}
int main(int argc, char *argv[], char *environ[]) {
  if (argc < 2){
    exit(-1);
  }
  vuln(argv[1]);
  return 0;
}
//example1.c

실습에 쓸 example.c 코드이다. 이를 gcc로 컴파일 해주면 된다.

 

 

1. example을 gdb로 실행한 뒤 vuln을 disassemble한다.

 

 

2. strcpy를 호출하는 시점에 브레이크 포인트를 건다.

 

 

3. 실행 시킨다. 파이썬을 이용해 좀 더 쉽게 인자를 전달할 수 있다.

 

 

4. strcpy를 호출하는 시점에 스택에 들어가 있는 매개변수들의 주소를 확인하자.

 

 

5. 해당 주소에는 다음과 같은 문자들이 채워져있다.

복사 버퍼인 argv[1]의 주소인 0xffffc292를 알아낸 것이다.

 

 

 

6. NOP Sled 중간 지점의 주소(argv1 + 0x500)를 계산해 보겠다.

NOP Sled 중간 지점 주소는 0xffff0f95이다. 이 주소를 이용한 새로운 공격 코드는 아래와 같이 구성할 수 있다.

"A" * 36 + 0xffffc792 + "\x90" * 0x1000 + shellcode

 

 

7. 만들어진 공격 코드를 이용해 익스플로잇을 시도해 보겠다.

성공적으로 셸이 실행되었다!!

 

 

설명 : argv[1]이라는 것은 vuln 함수의 인자로 전달되기도 하지만, main 함수의 스택 프레임에도 있다. 따라서 vuln 함수에서 bof가 일어났을 때 buffer를 모두 더미 값으로 채운 뒤, RET를 main 함수 상의 argv[1]로 하고, 뒤에 shellcode를 붙여주면 argv[1]으로 돌아갔을 때 쉘코드가 실행될 것이다.

다만, 이때 쉘코드의 정확한 위치를 알기 어렵기 때문에 쉘코드 앞에 NOP을 주고, NOP의 중간지점쯤 주소를 구해 그곳으로 RET을 하면 NOP 명령어를 계속 만나다가 마침내 쉘코드를 만나 쉘이 실행될 것이다.

 

 

+ 만약 NOPsled 실습이 안 될 경우 다음 두 가지 경우을 생각해보세요.

1. NOP을 너무 많이 줘서 오버플로우가 일어났을 수 있으니, 적당한 크기로 주면 된다.

2. ASLR을 끄고 실습해보는 것도 하나의 방법..

 

 

참고
dreamhack - Linux Exploitation & Mitigation Part 1

'Hacking > Pwnable' 카테고리의 다른 글

[P4C] 우리집에 GDB 있는데… 메모리 보고갈래? 정리  (0) 2021.03.11
[Pwnable] ASLR  (0) 2021.03.11
[Pwnable] RTL 실습  (0) 2021.03.07
[Pwnable] NX bit  (0) 2021.03.07
[Pwnable ] Return Address Overwrite 실습  (0) 2021.03.01
복사했습니다!