본문 바로가기
정보보안

정보보안3 3차시

by 뭔가해보겠습니다 2024. 6. 8.

disp $ebp
disp $esp
disp /x $eip
disp /i $pc
disp /4xw $esp

-

 

 

 

set disassembly-flavor intel

=> 문법을 인텔로 변경

 

(gdb) disas main
Dump of assembler code for function main:
   0x080484ad <+0>:     push   ebp
   0x080484ae <+1>:     mov    ebp,esp
   0x080484b0 <+3>:     sub    esp,0x4
   0x080484b3 <+6>:     mov    DWORD PTR [ebp-0x4],0x1
   0x080484ba <+13>:    push   DWORD PTR [ebp-0x4]
   0x080484bd <+16>:    push   0x804856c
   0x080484c2 <+21>:    call   0x8048350 <printf@plt>
   0x080484c7 <+26>:    add    esp,0x8
   0x080484ca <+29>:    mov    eax,0x0
   0x080484cf <+34>:    leave
   0x080484d0 <+35>:    ret

 

intel 문법

- 레지스터에 %가 없고, 즉시값에 $가 없다

- 주소에 [] 대괄호를 사용 ex) DWORD PTR [ebp-0x4]

- att 문법과 피연산자 순서가 뒤바뀌어있음

att가 movl $0x4, $esp 라면

intel은 mov esp, 0x4 가 된다

- intel_syntax noprefix 가 있어야 레지스터에 %를 생략한다

 

intel 문법 샘플

 

mov (기본적으로 32bit=4바이트 단위)
movb 1바이트
movw 2바이트
movq 8바이트

 

DWORD는 4바이트, BYTE는 1바이트

(gdb) x/4xw $esp
0xffffd444:     0x12345678

 

(gdb) /i $pc
mov    BYTE PTR [esp+0x1],0x01

(gdb) x/4xw $esp
0xffffd444:     0x12345601

 

(gdb) /i $pc
mov    WORD PTR [esp+0x1],0x23            <- 0x23은 0x0023과 같다. 2바이트이기 때문에, 빈곳은 0으로 채워짐

(gdb) x/4xw $esp
0xffffd444:     0x12002301

 

(gdb) /i $pc

mov    WORD PTR [esp+0x2],0x4567

(gdb) x/4xw $esp
0xffffd444:     0x45672301

 

(gdb) /i $pc

mov    DWORD PTR [esp],0x12345678

(gdb) x/4xw $esp
0xffffd444:     0x12345678

 

movb나 movw에 DWORD PTR을 사용하면 형식이 맞지 않아 에러가 난다

test-intel-mov2.s: Assembler messages:
test-intel-mov2.s:14: Error: conflicting operand size modifiers
shell returned 1

 

intel 문법으로 문자열 출력하기

.LC0 선언은 같지만,

push OFFSET FLAT:.LC0 으로 참조하는 부분이 달라졌다

LC0이 아니라 다른 이름으로 사용해도 됨

(Local Constant 문자열 상수라는 뜻)

 

(gdb) x/i $pc
=> 0x80484c1 <main+3>:  push   0x80484ad            <- .LC0

(gdb) x/4xw $esp
0xffffd444:     0x080484ad 

 

 

OFFSET FLAT:

=> 특정 주소를 참조할 때 사용한다. 레이블은 메모리 내 특정 위치, OFFSET은 레이블의 실제 주소

FLAT는 메모리 모델을 지정한다

 

32비트, 64비트 환경에선 보통 평면메모리 모델을 사용한다

평면 메모리 모델에서는 세그먼트 레지스터의 영향을 받지 않고 메모리 공간이 연속적이고 평평하게 배치된다

주로 DOS, 윈도우, 리눅스 등에서 사용

 

gef 설치

dnf -y install git

git clone https://github.com/hugsy/gef.git 

 

# tree gef/
gef/
├── LICENSE
├── README.md
├── docs
│   ├── api
│   │   └── gef.md
│   ├── api.md
│   ├── commands
│   │   ├── aliases.md
│   │   ├── arch.md

... 하략

 

# echo "source ~/gef/gef.py" > ~/.gdbinit

=> .gdbinit에 gef 관련 설정 넣어줌

 

=> gef가 적용된 모습. 기본적으로 intel 문법으로 나타난다

 

si를 통해 함수 내부로 들어갔을 때 표시됨 func1

 

복귀주소 0x080484cf

이후 push ebp 되면서 esp가 이동하면서 esp에 이전 ebp값이 담겼고

ebp와 esp의 위치가 같아지면서, ebp에 esp값을 복사해두어 ebp에 ebp의 복귀주소가 담긴다

 

gef config 설정 조회

gef 데이터가 너무 많아서 화면에 다 보이지 않을때엔 context 명령어를 입력하면 조정된다

레지스터만 지정해서 출력

 

[ Legend: Modified register | Code | Heap | Stack | String ]

=> gef 출력 목록 리스트

 

실습) for문을 intel 문법으로 작성

 

기본적인 코드 형태

int main()
{
   int i = 1;
   for(i = 0; i < 3; i++){
        printf("i= %d\n", i);
   }
    printf("for test end...");
   return 0;
}

 

(gdb) disas main
Dump of assembler code for function main:
   0x080484c7 <+0>:     push   ebp
   0x080484c8 <+1>:     mov    ebp,esp
   0x080484ca <+3>:     sub    esp,0x4
   0x080484cd <+6>:     mov    DWORD PTR [ebp-0x4],0x1
   0x080484d4 <+13>:    mov    DWORD PTR [ebp-0x4],0x0
   0x080484db <+20>:    jmp    0x80484dd <main+22>
   0x080484dd <+22>:    cmp    DWORD PTR [ebp-0x4],0x2
   0x080484e1 <+26>:    jle    0x80484e5 <main+30>
   0x080484e3 <+28>:    jmp    0x80484fb <main+52>
   0x080484e5 <+30>:    push   DWORD PTR [ebp-0x4]
   0x080484e8 <+33>:    push   0x80484ad
   0x080484ed <+38>:    call   0x8048350 <printf@plt>
   0x080484f2 <+43>:    add    esp,0x8
   0x080484f5 <+46>:    add    DWORD PTR [ebp-0x4],0x1
   0x080484f9 <+50>:    jmp    0x80484dd <main+22>
   0x080484fb <+52>:    push   0x80484b6
   0x08048500 <+57>:    call   0x8048350 <printf@plt>
   0x08048505 <+62>:    add    esp,0x4
   0x08048508 <+65>:    mov    eax,0x0
   0x0804850d <+70>:    leave
   0x0804850e <+71>:    ret
   0x0804850f <+72>:    nop

 

컴파일 전에 주소를 알 수 없으므로, 라벨을 붙여 그곳으로 점프한다

 

실습2)

sub esp, 12로 처음부터 미리 변수 세 자리를 확보해 놓는 경우

 

printf("%d", i); 의 i 에 대한 복사
  push DWORD PTR[ebp-0x04]
  => mov eax, DWORD PTR[ebp-0x04]
  mov DWORD PTR[ebp-0x08], eax

 

mov는 메모리주소에서 메모리주소로 옮길 수 없기 때문에

eax 레지스터로 값을 한 번 옮겨야 한다

 

printf("%d", i); 의 "%d" 에 대한 복사

  push OFFSET FLAT:.LC0

  => mov DWORD PTR[ebp-12], OFFSET FLAT:.LC0           ( [ebp-12] = [ebp-0xc] )

 

 

'정보보안' 카테고리의 다른 글

버퍼오버플로우 복습  (0) 2024.06.11
정보보안3 4차시  (0) 2024.06.09
정보보안3 2차시  (0) 2024.06.02
정보보안3 1차시  (0) 2024.06.01
정보보안2 8차시  (0) 2024.05.26