목록전체 글 (33)
미역줄기의 이모저모

스택 카나리는 함수의 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 값을 삽입하고, 함수의 에필로그에서 해당 값의 변조를 확인하는 보호 기법이다. 스택버퍼 오버플로우 공격을 한층 더 어렵게 만든다. 스택 버퍼 오버플로우로 반환 주소를 덮으려면 반드시 카나리를 먼저 덮어야 하므로 카나리 값을 모르는 공격자는 반환 주소를 덮을 때 카나리 값을 변조하게 된다. 이 경우, 에필로그에서 변조가 확인되어 공격자는 실행 흐름을 획득하지 못한다. 그림은 저렇게 그렸지만!!! 사실은 sfp 앞에 있고 !! 정확히 buf 보다는 데이터 인자 라고 하는게 맞겠다!!!! 카나리의 작동 원리 // Name: canary.c #include int main() { char buf[8]; read(0, buf, 32); ret..

문제코드 리뷰 #include #include int main() { char buf[0x50]; printf("Address of the buf: %p\n", buf); printf("Distance between buf and $rbp: %ld\n", (char*)__builtin_frame_address(0) - buf); printf("[1] Leak the canary\n"); printf("Input: "); fflush(stdout); read(0, buf, 0x100); printf("Your input is '%s'\n", buf); puts("[2] Overwrite the return address"); printf("Input: "); fflush(stdout); gets(buf);..

1, 문제 확인 참고 코드 $ cat write.asm section .text global _start _start: ;/* write(fd=1, buf='hello', n=48) */ ;/* push 'hello\x00' */ mov rax, 0x0a6f6c6c6568 push rax mov rsi, rsp push 1 pop rdi push 0x6 pop rdx ;/* call write() */ push 1 pop rax syscall $ nasm -f elf64 write.asm $ objcopy --dump-section .text=write.bin write.o $ xxd write.bin 00000000: 48b8 6865 6c6c 6f0a 0000 5048 89e6 6a01 H.hello..

시간을 두어 아래 코드의 취약점을 스스로 찾아보기!!! // Name: rao.c // Compile: gcc -o rao rao.c -fno-stack-protector -no-pie #include #include void init() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); } void get_shell() { char *cmd = "/bin/sh"; char *args[] = {cmd, NULL}; execve(cmd, args, NULL); } int main() { char buf[0x28]; init(); printf("Input: "); scanf("%s", buf); return 0; } 지금부터는 내가 아는걸 토대로 분석하는 것이기 ..
디버거는 프로그램을 어셈블리 코드 단위로 실행하면서, 실행 결과를 사용자에게 직관적으로 보여준다. gdb는 리눅스의 대표적인 디버거 중 하나이다. (나는 우분투 22.04 환경에서 진행했다.) pwndbg를 다운로드 한다. $ git clone https://github.com/pwndbg/pwndbg $ cd pwndbg $ ./setup.sh 실습예제 코드 // Name: debugee.c // Compile: gcc -o debugee debugee.c -no-pie #include int main(void) { int sum = 0; int val1 = 1; int val2 = 2; sum = val1 + val2; printf("1 + 2 = %d\n", sum); return 0; } gdb ..
Opcode: 스택 push val: val을 스택 최상단에 쌓음 #예제 [Register] rsp = 0x7fffffffc400 [Stack] 0x7fffffffc400 | 0x0
어셈블리 언어 컴퓨터의 기계어와 치환되는 언어이다. 기계어의 종류만큼 어셈블리어의 종류도 존재한다. x64 어셈블리 언어 기본구조 동사에 해당하는 명령어와 목적어에 해당하는 피연산자로 구성된다. movr4, r0 해석: r4에 r0를 대입해라! ( r4,r0는 레지스터이다 ) 그럼 여기서 명령어는 뭘까? 바로 mov이다. 피연산자는? r4, r0이다~ 명령어 명령코드 데이터 이동 mov, lea 산술 연산 inc, dec, add, sub 논리 연산 and, or, xor, not 비교 cmp, test 분기 jmp, je, jp 스택 push, pop 프로시져 call, ret, leave 시스템 콜 syscall 피연산자 상수 레지스터 메모리 이렇게 세 가지의 종류가 있다. ( 좀 전의 예시에도 레지..

리눅스 프로세스의 메모리 구조 세그먼트(Segment) 세그먼트란 적재되는 데이터의 용도별 메모리의 구획이다. 리눅스에선 프로세스의 메모리를 코드 세그먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트 이렇게 5개로 구분한다. 각 용도에 맞게 권한을 부여할 수 있다. 그럼 CPU는 메모리에 대해 권한이 부여된 행위를 한다. 코드 세그먼트 실행 가능한 기계 코드가 위치하는 영역이다. 텍스트 세그먼트라고도 불린다, 읽기와 실행 권한이 부여된다. 쓰기권한이 없는 이유는 공격자가 악의적인 코드를 삽입하는 것을 막기 위해서이다. int main() { return 31337; } 31337을 반환하는 main함수가 컴파일 되면 31337은 기계코드로 변환되고 이것은 코드 세그먼트에 위치한다. ..