C-> ASM( 기계어 )
1. 시스템 프로그래밍
- 윈도우즈: win API(Advanced Programing Interface)
- 리눅스: system call
shell (user)
----------------
커널
----------------
H/w (Device)
사용자가 커널을 통해 장치에 접근한다
인터페이스는 함수형태로 제공
세개의 개념을 통틀어서 운영체제
! ltrace Vs. strace
ltrace: 라이브러리 추적 명령어
strace: 시스템콜 추적 명령어
리눅스 시스템 콜 같은경우 win api와는 다르게 웹상에 공개되어있어 쉽게 찾아볼 수 있다.
주로 이용하는 시스템 콜 참조 사이트
https://syscalls.kernelgrok.com/
write 함수를 살펴보면
2. write system call
1). C 언어
-systemcall과 동일한 래퍼 함수 제공
-fd: 0,1,2
<파일 디스크립터 번호>
할당되있는 파일디스크립터 번호
0 : 표준입력(키보드)
1 : 표준출력(모니터)
2 : 표준에러
(* 3번부터는 실행파일에 파일핸들을 준다.)
printf 대신 write 를 사용한다
#include <stdio.h>
int main()
{
write(1,"Hello,world\n",13);
return 0;
}
2). 어셈블리
- 함수 호출을 통한 시스템콜 함수는 사용하지 않는다.
- 인터럽트를 통한 시스템콜 함수를 사용
-하드웨어 인터럽트 (물리적인 인터럽트)
-소프트웨어 인터럽트
WRITE 함수
_start:
mov eax, 0100b //eax 의 역할은 시스템콜의 번호를 저장한다 wirte 시스템콜이 4번이다.
mov ebx, 1d // fd =1 표준 출력을 의미한다
mov ecx, string //const char __user *buf
mov edx, 20o // 최대 길이
int 80h //int 가 인터럽트고 80은 시스템콜을 의미한다
차례 대로 쓰는 인자를 레지스터에 넣고 시스템콜을 한다 급한경우는 edi ,esi 까지 사용이 가능하다
만약 인자가 3개가 넘어가면 스택을 사용한다.
read 함수
;read(0,path,1024);
mov eax, 3 ;call number
mov ebx, 0 ;fd 값
lea ecx, [ebp-1024] ;user *buf 사용하고자 하는주소
mov edx, 1024 ;최대 길이
int 80h
OPEN 함수
;open
mov eax, 5 ;시스템 콜 번호
lea ebx, [ebp-1024] ; open할 파일 이름
mov ecx, 0 ;flags
mov edx, 0 ;int mode
int 80h
execve 함수
[실습]
1). 디렉터리 생성 :makedir
-read, write, mkdir
#> ./mkdir
path: path
success or fail
C언어로 연습
int main()
{
char path[1024] = {0,};
int end=0;
read(0,path,1024);
while( path[end] != '\n' ){
end++;
}
path[end]=0;
printf("%s",path);
return 0;
}
- read 는 \n까지 읽어들인다
- read는 읽어들인 문자열의 길이를 반환
- 메모리는 지역변수만 사용
C언어
int main()
{
char path[1024] = {0,}; // [ebp-1024]
int end=0; // [ebp-1028]
int result = 0; // [ebp-1032]
write(1,"input:",7);
read(0,path,1024);
while( path[end] != '\n' ){ //마지막 라인을 찾아준다
end++;
}
path[end]=0; // 뉴라인을 삭제
result=mkdir(path, 0755); // sys_mkdir 0x27(콜번호) const char __user *pathname int mode(권한)
if (result < 0){
write(1,"failed\n",7);
} else {
write(1, "success\n",8);
}
return 0;
}
어셈블리어
segment .data
fail db 'failed',10,00
success db 'success',10,00
input db 'input:',00
segment .text
global _start
_start:
push ebp ;프롤로그
mov ebp, esp
sub esp, 1032 ;배열 1024 + 변수 2개 (8) 1032
mov ecx, 256 ; 배열 초기화 1024/4 256번 반복한다
mov eax, 0
lea edi, [ebp-1024]
rep stosb ;path 초기화
mov dword [ebp-1028], 0 ;end 초기화
mov dword [ebp-1032], 0 ;result 초기화
;write(1,"input:",7);
mov eax, 4 ;call number
mov ebx, 1 ; 표준 출력
mov ecx, input ; const char __user *buf
mov edx, 7 ; 최대 길이
int 80h ; 시스템콜
;read(0,path,1024);
mov eax, 3 ;call number
mov ebx, 0 ;표준 입력 0
lea ecx, [ebp-1024] ;const char __user *buf
mov edx, 1024 ;최대 길이
int 80h ; 시스템콜
while:
lea eax, [ebp-1024] ;path start address
mov ebx, [ebp-1028] ;end memory
cmp byte [eax+ebx*1], 10 ;new 라인 인지 비교한다
je end ;뉴 라인이면 end로 jmp 하고
inc dword [ebp-1028] ;end 값을 하나 늘려서 while 문을 반복한다
jmp while
end:
;path[end]=0;
lea eax, [ebp-1024] ;path 시작 위치를 eax에 두고
mov ebx, [ebp-1028] ; [ebp -1028] end 를 ebx에 저장한다
mov byte [eax +ebx *1], 0 [eax+ebx *1] 에 0을 저장한다
;result=mkdir(path, 0755);
mov eax, 27h ;mkdir 콜 번호
lea ebx, [ebp-1024] // 시작 위치
mov ecx, 0755o // 권한 설정
int 80h ; 시스템콜
mov dword [ebp-1032], eax ; 값을 1032 result 에 저장한다
;if (result < 0){
;write(1,"failed\n",7);
;} else {
;write(1, "success\n",8);
;}
if:
cmp dword [ebp-1032], 0 ;result 값을 비교하고
jge .else ;크거나 같으면 .else로 이동한다
mov eax, 4 ;write 시스템 콜 번호
mov ebx, 1 ;fd 표준 입출력
mov ecx, fail ; fail 출력
mov edx, 7 ;최대 길이
int 80h ; 시스템콜
jmp .end ;분기문
.else:
mov eax, 4
mov ebx, 1
mov ecx, success
mov edx, 8
int 80h
.end:
xor eax, eax
leave
ret
2). 파일 입/출력: mycat
- open, read, wirte
#> ./mycat
input: /etc/passwd
......
read를 한번 쓸때 마다 얼만큼 썼는지 리턴이 될것이다.
open 할때 flag 0번
mode 는 0으로 하면된다
C언어
int main()
{
char path[1024] = {0,};
char buffer[1024] = {0,};
int size = 0;
int fd = 0;
int end = 0;
write( 1, "input: ", 7 );
read( 0, path, 1024 );
while( path[end] != '\n' ) {
end++;
}
path[end] = 0;
fd = open( path, 0, 0 );
size = read( fd, buffer, 1024 );
while(size == 0) {
write( 1, buffer, 1024 );
size = read( fd, buffer, 1024 );
}
어셈블리어
segment .data
input db 'input: ', 00
segment .text
global _start
_start:
push ebp ;프롤로그
mov ebp, esp
sub esp, 2060 ;1024+1024+4+4+4
mov ecx, 512 ;2048 을 한번에 초기화 한다
mov eax, 0 ; eax에 0을 넣어주고
lea edi, [ebp-2048] ; 배열 시작 위치
rep stosd ; 반복해서 초기화 한다
mov dword [ebp-2052], 0 ; size
mov dword [ebp-2056], 0 ; fd
mov dword [ebp-2060], 0 ; end
;write
mov eax, 4 ;시스템콜 번호
mov ebx, 1 ;파일 출력
mov ecx, input ; *buf
mov edx, 7 ;최대 사이즈
int 80h ;시스템콜
;read
mov eax, 3 ;시스템 콜 번호
mov ebx, 0 ;파일 입력
lea ecx, [ebp-1024] ;path 시작 주소
mov edx, 1024 ;최대 길이
int 80h ;시스템 콜
while1:
lea eax, [ebp-1024] ;path 시작 주소 위치
mov ebx, [ebp-2060] ;end 값 ebx에 저장
cmp byte [eax + ebx * 1], 10 ; eax+ end *1이 뉴라인 인지 비교한다
je .end ; 뉴라인이면 .end로 이동
inc dword [ebp-2060] ; end값을 1씩 증가 해서 while1 반복문 처리한다
jmp while1
.end:
;path[end] = 0;
lea eax, [ebp-1024] ;path 시작위치 주소를 가지고오고
mov ebx, [ebp-2060] ; end가 뉴라인인 값을 가지고 오고 ebx에 저장한다
mov byte [eax + ebx *1], 0 ; eax+end가 뉴라인 *1 ,0을 대입해준다
;open
mov eax, 5 ;시스템 콜번호
lea ebx, [ebp-1024] ;open할 파일 이름
mov ecx, 0 ;flag
mov edx, 0 ;open 0
int 80h ; 시스템콜
mov dword [ebp-2056], eax eax를 fd에 저장 한다
;size = read( fd, buffer, 1024 );
mov eax, 3 ;시스템 콜 번호
mov ebx, [ebp-2056] ;위에 저장한 fd 번호 [ebp-2056]
lea ecx, [ebp-2048] ;시작 위치 주소를 가져온다 buffer의 시작 주소
mov edx, 1024 ;최대 길이
int 80h ; 시스템 콜
mov dword [ebp-2052], eax ;size 에 대입해준다
while2:
cmp dword [ebp-2052], 0 ;;size 가 0 즉 남은 내용이 없으면 end로 끝낸다
je end ;에필로그 하고 끝낼려고
;write
mov eax, 4 ;만약 size가 남았으면 write 해준다 콜번호
mov ebx, 1 ;fd 1
lea ecx, [ebp-2048] ;시작 위치
mov edx, 1024 ; 최대 길이
int 80h ; 시스템 콜
;read
mov eax, 3
mov ebx, [ebp-2056] ;fd 번호
lea ecx, [ebp-2048]
mov edx, 1024
int 80h
mov dword [ebp-2052], eax ;size에 대입해준다
jmp while2
end:
xor eax, eax
leave
ret
3). 쉘: myshell
- read, execve
-명령어를 입력-> 실행
-execve, read
int execve (const char *filename, char *const argv [], char *const envp[]);
1. 실행할 명령어의 종류
2. 아규먼트(포인터 배열)
3. 환경 변수에 대한 포인터
'시스템 해킹' 카테고리의 다른 글
[시스템 해킹] 파일 분석하기 실습! (0) | 2018.01.29 |
---|---|
[시스템 해킹] GDB 디버거 사용법 (0) | 2018.01.27 |
[시스템 해킹] main 함수의 인자 (0) | 2018.01.27 |
[시스템 해킹] 배열 지역 변수로 구현하기 (0) | 2018.01.27 |
[시스템 해킹] 어셈블리 함수 표현 (Stack) (0) | 2018.01.23 |