pro.jpg

 

진정한 프로그래머한테 필요한 자판은 단지 3개뿐!!!!!!!!!!!!!!!!!

 

 

버퍼 오버플로우에 대해 알려고 한다면 어셈블리어를 어느정도 간단히 알고 있어야 한다.

간단하게 어셈블리를 보자.

 

cpu에는 범용 레지스터라는게 있다.

범주

이름

내용

범용레지스터

EAX(AH,AL)

Accumlaor

누산기, 산술연산, 입출력

EBX(BH,BL)

Base Register

인덱스 로서 사용할 수 있는 범용 레지스터

ECX(CH,CL)

Count Register

Loop의 반복 횟수나 좌우 방향으로 비트를 쉬프트할 숫자를 기억

EDX(DH,DL)

Data Register

입출력 명령에 사용 큰수의 곱셉 및 나눗셈에서는 DX,AX 를 쌍으로 사용

오프셋레지스터

ESI

Source Index

출발지 주소에 대한 값 저장

Memory 이동이나 데이터 복사 때 원본 주소

EDI

Destination Index

박사할 때 목적지의 주소

ESP

Stack Pointer

스택의 가장 윗부분을 가진다.

EBP

Base Pointer

스택의 가장 아랫부분을 가진다.

IP

Instruction Pointer

다음 명령어의 오프셋을 저장

세그먼트레지스터

EDS

Data Segment Register

변수의 기본 베이스 주소 저장

EES

Extra Segment Register

변수의 추가 베이스 주소 저장

ESS

Stack Segment Register

스택의 베이스 주소 저장

ECS

Code Segment Register

명령어 코드의 베이스 주소 저장

 

어셈블리어

 데이터 전송 명령

Mov

데이터를 복사한다.

사칙연산 명령

ADD

덧셈

ABC

덧셈

SUB

뺄셈

SBB

뺄셈

MUL

곱셈

CBW

바이트에서 워드로 부호확장

DIV

나눗셈

CWD

워드에서 더블워드로 부호확장

INC

하나 증가

DEC

하나 감소

논리연산. 쉬프트 명령

AND

논리곱

OR

논리 합

XOR

배타적 논리 합

NOT

부정

NEG

부호 반전

SHL

S는 Shift, H는 0을 넣을 것인가 L은 left

ROR

R은 Rotate

 

함수호출규약

일반적 호출규약은 인수를 뒤에서부터 전달하며, 인수 전달에 사용된 스택 영역은 호출원이 정리하는데, 이는 C++의 기본 규약인

 __cdcel의 수택 프레임 모양일 뿐임 호출규약이 변경되면 스택 프레임의 모양과 관리 방법도 달라짐

 호출규약

인수전달

스택정리

이름규칙

__cdecl

오른쪽 먼저

호출원

_함수명

__stdcall

오른쪽 먼저

함수

_함수명@인수크기

__fastcall

EXC, EDX에 우선 나머 지는 오른쪽 먼저

함수

@함수명@인수크기

Naked

오른쪽 먼저

함수

없음

__cdecl 은 함수가 스택을 정리할 책임이 없다. 함수가 끝나고 나서 호출원이 스택을 정리한다. 함수를 호출하는 쪽에서 인수를 몇개나 전달했는지 알 수 있으므로, 실제 전달한 인수 크기만큼 스택을 정리할 수 있다는 장점이 있음. printf나 scanf 같은 가변인수를 지원하는 함수는 모두 __cdecl 호출 규약을 사용함. winAPI 함수의 대부분 규약이기도 하지만, wsprintf는 예외적으로 __stdcall 로 제작되어 있음

__cdecl 같은 가변인수를 사용하는 함수가 공격대상이 된다.

 

 

아래 왼쪽 함수를 어셈블리로 바꾼것이 오른쪽이다. 기본호출 규약인 __cdecl 이다.

int fun(int b, int c)

{

       b = b+c;

       return b;

}

int main(void)

{

       int a;

       a = fun(2,3);

       return 0;

 8: int fun(int b, int c)

 9: {

00111000  push        ebp 

00111001  mov         ebp,esp

 10:   b = b + c;

00111003  mov         eax,dword ptr [b]

00111006  add          eax,dword ptr [c]

00111009  mov         dword ptr [b],eax

 11:   return b;

0011100C  mov         eax,dword ptr [b]

 12: }


int main()

 {

00111020  push        ebp 

00111021  mov         ebp,esp

00111023  push        ecx 

    16:  

    17:   int a;

    18:

    19:   a = fun(2,3);

00111024  push        3   

00111026  push        2   

00111028  call          fun (111000h)

0011102D  add         esp,8          // 스택에 push 했던 3,2를 호출원쪽(main)에서 정리하고 있다.

00111030  mov         dword ptr [a],eax

    20:

    21:   return 0;

00111033  xor          eax,eax

    22: }

00111035  mov        esp,ebp

00111037  pop         ebp 

00111038  ret

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

memo.jpg

스택에는 push에 의한 명령어로 값이 채워진다. 스택은 높은 주소에서 낮은 주소로 채워진다.

힙에는 사용자에 의해 값이 채워지며 Data는 전역변수, static 변수, 클래스 등이 채워지며 Code에는 코드들이 들어간다.

힙,data,code는 낮은 주소에서 높은 주소로 채워진다.

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

저기 위에 어셈 코드를 보면 제일 아래에 ret 것이 있다. 그것은 리턴이라고 함수를 끝내고 호출원쪽으로 가겠다는건데.

호출원의 Instruction Pointer 가 있다. 함수가 끝나면 실행되어질 다음 명령어가 있는곳을 가리키고 있는것이다.

 

int main(int argc, char* argv[])

{

      char buff[4];

     

       strcpy(buff,argv[1]);

       return 0;

}

저것이 실행이 된다면 스택에는 ret가 제일 먼저 올라가고 다음 buff[4]가 올라갈 것이다.

 strcpy를 이용  argv에 있는 내용을 buff 에 복사를 하면 buff[4]를 넘어 ret 주소까지 바꾸게 될것이다.

asd.jpg

asdd.jpg

 

근대 AAAA가 아닌 내가 만든 해킹프로그램의 메모리주소를 넣는다면.........................해킹프로그램이 실행되게 되는것이다.

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 Visual Studio 에는 보안옵션이 있는데 그것을 활성화 하면 컴파일 할때 버퍼 오버플로우를 방지하기 위해 아래 코드가 들어가게 된다.

 

013B339E  mov      eax,dword ptr [___security_cookie (13B7018h)]

 

Data영역에 security_cookie 값이 랜덤한 값으로 들어가는데 이 값을 프로그램이 실행될때 스택에 올려 놓는다.

ret 를 바꾸기 위해 오버플로우가 발생 했다면 security_cookie 값도 같이 바뀌게 될것이다.

함수가 종료될때 'Data 영역의 security_cookie 값과 Stack 의 security_cookie 값을 비교해서 같지가 않다면 버퍼 오버런 오류를 발생 시킨다.'

fsdfsdfs.jpg

dafsa.jpg

 

출처: http://wearekorean.co.kr/zbxe/dic/34345