목록분류 전체보기 (194)
Information Security
권한 상승 기법 -스택 버퍼 오버플로우 공격은 보통 SetUID(Set User ID)가 설정된 root 권한의 프로그램을 공격대상으로 한다. -> 스택에 정해진 버퍼보다 큰 공격 코드를 반환주소를 변경함으로써 임의의 공격 코드를 root 권한으로 실행하도록 한다. 권한 상승 기법을 공부하기 위해 OverTheWire의 Leviathan 문제를 풀어볼 것이다. 다음 레벨로 접속하는 패스워드를 찾아야 하고 /etc/leviathan_pass 디렉터리에 패스워드가 저장되어 있다. ★ leviathan1 leviathan1에 접속해서 파일 목록을 확인했더니 check 실행 파일이 존재한다. -> 특수 권한 SetUID가 설정되어 있다. 특수 권한에 의해 check 프로그램이 실행되는 중에는 소유자(leviat..
스택 버퍼 오버플로우(stack buffer overflow) -스택에 정해진 버퍼보다 큰 공격 코드를 삽입하여 반환 주소를 변경함으로써 임의의 공격 코드를 루트 권한으로 실행하도록 하는 방법이다. -취약한 함수 scanf, gets, strcpy, ... 등을 사용해서 발생하는 취약점이다. 1. 취약점 확인 - strcpy 함수 오버플로우 공격을 시도하기 위해서 취약한 코드를 작성 했다. strcpy(dest, src); strcpy 함수로 인해 입력받은 인자가 buffer2로 복사된다. 인자를 전달하면서 파일을 실행하면 buffer2의 값이 출력된다. 이번에는 길이가 긴 인자를 전달했다. -> 그랬더니 buffer1의 값이 출력되었다. ??? strcpy( buffer2, argv[1] ); 이 부분..
시스템 콜을 이용한 mkdir 프로그램 작성 실습 -시스템 콜만 가지고 리눅스의 mkdir 명령어와 비슷하게 프로그램을 구현해볼 것이다. -필요한 시스템 콜 함수는 다음과 같다. -> read: 경로 입력 -> write: 디렉터리 생성 성공, 실패 출력 -> mkdir: 디렉터리 생성, 성공시 0 반환 1. C언어로 작성 먼저 C로 작성하고 어셈블리어로 변환할 것이다. 일단 read 함수로 경로를 입력받는다. -> fd = 0 (표준 입력) read 함수는 입력받은 문자열에 자동으로 개행 문자가 들어가게 된다. 경로에는 개행 문자(\n)가 들어갈 수 없기 때문에 제거해야 한다. while 문을 이용해서 개행 문자를 찾으면 0으로 값을 변경하도록 한다. 다시 확인해보면 개행이 되지 않는 것을 확인할 수 ..
System Call -커널은 하드웨어 특성으로부터 프로그램들을 격리시키고, 하드웨어와 직접 상호 작동하며 프로그램에게 일관된 서비스를 제공한다. -Shell(user)은 정의된 System Call에 의해서 커널과 통신한다. 1. C 언어에서 시스템 콜 사용 -라이브러리에 이미 시스템 콜과 동일한 Wrapper 함수가 존재한다. printf 함수 대신에 write 시스템 콜 함수를 이용해서 문자열을 출력할 것이다. # man 2 write -> write 함수의 원형 확인 write(fd, 출력할 문자열, 문자열의 개수) -> fd = file descriptor -> fd : 1(표준 출력) -> 공백, 개행 문자 포함 문자열의 개수 : 13 2. 어셈블리어에서 시스템 콜 사용 -어셈블리어에서는 호출..
우리는 메인 함수를 정의할 때 int main()을 사용하지만 사실 메인 함수의 원형은 다음과 같다. int main(int argc, char *argv[]); saved ebp saved eip argc *argv 여기서 ebp는 main 함수의 기준점이다. argc, *argv는 main 함수가 호출되기 전에 항상 존재하고 있다. argc는 인자의 개수를 저장하고 있다. 값을 확인해보면 인자를 입력하지 않아도 무조건 `1이다. -> 실행 파일명(./a.out)도 인자로 간주하기 때문이다. 프로그램을 실행할 때 main 함수로 전달되는 인자를 space로 구분해서 지정할 수 있다. -> 실행 파일 + 3개의 인자 = 4 위의 C 코드를 어셈블리어로 변환한 것이다. -> argc는 main 함수의 기준..
함수 어셈블리어에서 함수라는 개념은 없다. 하지만 함수처럼 동작하도록 구현할 수는 있다. 어셈블리어에서 함수를 구현해보기 위해서는 스택 메모리에 대한 이해가 필요하다. 프로세스가 사용하는 메모리의 구조를 알아보기 위해서 간단한 C코드를 작성했다. C코드를 컴파일한 후, 실행 파일을 실행한다. -> sleep에 의해서 대기 상태가 된다. -> Ctrl+Z로 빠져나온 후 ps -ef로 프로세스 목록을 확인한다. 백그라운드로 실행 중인 것을 알 수 있다. 여기서 프로세스의 PID를 확인한다. (817) proc 디렉터리에는 이름이 PID인 디렉터리들이 존재한다. -> 우리는 PID 817 디렉터리를 확인해야 한다. 프로세스는 파일 형태로 저장되어 있고, 그에 대한 정보도 파일이다. -> 817 디렉터리 중 m..
관계 연산: cmp(compare) cmp는 플래그 레지스터의 값을 변경하기 위한 명령어이다. cmp vleft, vright sub vleft, vright 연산을 수행한 결과 값에 따라 플래그 레지스터를 변경한다. 1) vleft가 더 크면 sub vleft, vright의 결과는 양의 정수가 나온다. -> SF(Sign Flag)의 값은 0, ZF(Zero Flag)의 값은 0으로 변경된다. 2) vright가 더 크면 음의 정수가 나온다. (부호 발생) -> SF의 값은 1, ZF의 값은 0으로 변경된다. 3) vleft와 vright가 같으면 0이 나온다. -> SF의 값은 0, ZF의 값은 1로 변경된다. pushfd로 EFLAGS 레지스터를 확인할 수 있다. cmp 20, 30 sub 20,..
레지스터(Register) CPU가 연산에 필요한 데이터를 기억하는 고속의 임시 기억 장치이다. 용도별로 여러 개의 레지스터가 존재한다. 속도 레지스터 >> 메모리(주기억장치) >> 보조기억장치(디스크, USB) 1) 범용 레지스터 EAX(Extended Accumulator Register) EBX(Extended Base Register) ECX(Extended Counter Register) EDX(Extended Data Register) 2) 포인터 레지스터 ESI(Extended Source Index) EDI(Extended Destination Index) -> 문자열 복사(Source -> Destination)에 이용 EBP(Extended Base Pointer) ESP(Extende..
주소 vs 메모리 C언어는 포인터를 통해 메모리에 대한 직접 접근이 가능하지만, 어셈블리어는 변수를 선언해서 사용하지 않고, 메모리를 직접 사용한다. 주소는 메모리 상의 위치(정수)를 나타낸다. 파일에서 오프셋과 동일한 의미를 가진다. 메모리는 데이터가 들어있는 실제 공간이다. ★ C언어 코드를 어셈블리어로 변환하기 int a; int b; int main() { scanf("%d", &a); scanf("%d", &b); printf("a: %d", a); printf("b: %d", b); return 0; } 두 변수를 입력받고 입력받은 변수를 출력하는 C언어 코드이다. 코드에서 사용할 함수는 printf, scanf 두 개이다. extern printf extern scanf extern을 통해 ..
C언어 프로그램 실행과정 이해하기 CPU가 프로그램을 실행하는 과정 중에 취약점이 발생하기 때문에, 소스코드가 실행 파일로 만들어지는 과정을 알아야 한다. IDE를 사용하지 않고 C언어로 작성된 소스 코드를 직접 컴파일, 어셈블하면서 과정을 파악해볼 것이다. ※ 우리가 이때까지 C언어를 배우면서 사용한 Visual Studio, 자바를 배우면서 사용한 이클립스는 컴파일러가 아니고 IDE(Integrated Development Environment: 통합 개발 환경)이다. IDE는 컴파일러, 편집기, 디버거를 하나로 묶은 소프트웨어이다. 일단 vi 편집기로 Hello World를 출력하는 소스를 작성한다. gcc 명령어로 해당 파일을 컴파일 한다. 명령어 실행 후 아무것도 출력되지 않으면 에러 없이 컴파..