1 / 65

어셈블리

어셈블리. 어셈블리 구조. 어셈블리는 다음과 같이 다섯 영역으로 구성된다 . 레이블 (Label), 명령 (OP-code), 인수 1(Operand 1), 인수 2(Operand 2), 주석 (comment) 레이블 직접적인 수행과는 관계가 없으며 jmp, call 을 통해서 참조할때 사용된다 . C 언어의 goto 문장에서 사용하는 레이블 ( 레이블명 :) 과 같이 사용된다 . 명령 기종에 따라 약간의 차이가 있다 . 인수 인수에 따라 명령어 구사가 달라진다 .

naif
Download Presentation

어셈블리

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 어셈블리

  2. 어셈블리 구조 • 어셈블리는 다음과 같이 다섯 영역으로 구성된다. • 레이블(Label), 명령(OP-code), 인수 1(Operand 1), 인수 2(Operand 2), 주석(comment) • 레이블 • 직접적인 수행과는 관계가 없으며 jmp, call 을 통해서 참조할때 사용된다. • C 언어의 goto 문장에서 사용하는 레이블(레이블명:)과 같이 사용된다. • 명령 • 기종에 따라 약간의 차이가 있다. • 인수 • 인수에 따라 명령어 구사가 달라진다. • movb $0x1, %eax  1바이트 데이터를 eax 레지스터에 저장한다. • movw $0x1, %eax  2바이트(word) 데이터를 eax 레지스터에 저장한다. • movl $0x1, %eax  4바이트(long) 데이터를 eax 레지스터에 저장한다. 실습 포인트 어셈블리 기초 명령어

  3. 어셈블리 구조(실습 포인트) • eax 에 4 바이트 형의 1 을 저장하라. • eax 에 들어있는 값에 1을 더하라. • eax 에 들어있는 값에서 1을 빼라. • eax 의 값에서 1을 증가시켜라. • eax 의 값에서 1을 감소시켜라. • label_123 위치로 분기하라. • 서브루틴(sub1) 을 호출하라. • 서브루틴에서 원래의 위치로 복귀하라. • 시스템콜을 위한 인터럽트를 발생시켜라. • eax 에 ‘esi+8’ 의 주소를 저장하라. • ebp 값을 스택에 저장하라. • 스택에 저장된 값을 꺼내어 esi 에 저장하라.

  4. 어셈블리 구조(문제 풀이) • eax 에 4 바이트 형의 1 을 저장하라. • mov1 $0x1, %eax • eax 에 들어있는 값에 1을 더하라. • addl $0x1, %eax • eax 에 들어있는 값에서 1을 빼라. • subl $0x1, %eax • eax 의 값에서 1을 증가시켜라. • incl %eax • eax 의 값에서 1을 감소시켜라. • decl %eax • label_123 위치로 분기하라. • jump label_123 • 서브루틴(sub1) 을 호출하라. • call sub1 • 서브루틴에서 원래의 위치로 복귀하라. • ret • 시스템콜을 위한 인터럽트를 발생시켜라. • int $0x80 • eax 에 ‘esi+8’ 의 주소를 저장하라. • leal 0x8(%esi), %eax • ebp 값을 스택에 저장하라. • push %ebp • 스택에 저장된 값을 꺼내어 esi 에 저장하라. • pop %esi

  5. 어셈블리 - 인텔계열과 AT&T 계열 비교 • Register naming • 인텔 계열은 아무것도 붙지 않지만 AT&T 계열은 명령어 앞에 ‘%’ 가 붙는다. • 인텔 : ecx AT&T : %ecx • Source, Destination Ordering • 인텔 계열은 오른쪽에서 왼쪽으로 대입되고 AT&T 계열을 반대로 왼쪽에서 오른쪽으로 대입된다. • 인텔 : mov ecx, ebx AT&T : movl %ebx, %ecx • Operation size specification • 레지스터의 크기는 정해주는 것이 좋다(b, w, l). • 인텔 : mov cx, bx AT&T : movw %bx, %cx • Constant value/immediate vale format • AT&T 계열은 value 앞에 ‘$’ 가 붙는다. • 인텔 : mov ebx, _hack AT&T : movl $_hack, %ebx

  6. 어셈블리 - 인텔계열과 AT&T 계열 비교 • Referencing memory • 32 비트 주소를 어드레싱 • 인텔 : [base + index * scale + immediate32] • AT&T : immediate_value(32){base, index, scale} • 특정 포인터를 어드레싱 • 인텔 : [ebx] • AT&T : (%eax) • C 언어 변수를 어드레싱 • 인텔 : [_hack] • AT&T : _hack • 오프셋 어드레싱 • 인텔 : [ebx +1] • AT&T : 1(%ebx) 실습 포인트 해킹개념 상시 유지용 문제

  7. 해킹개념 상시 유지용 문제 - Brutus Attack(실습 포인트) • 221.154.130.98 (추후 변동가능 있음) 를 대상으로 FTP 서버공격으로 ID/PW 를 획득하라. • 아이디/비밀번호를 획득한 후에 숨겨져 있던 쉐도우 파일을 크랙하라. • 힌트 크랙용 사전이 생성되는 시간 관계상 여기서 제공되는 DIC 생성기의 범위는 91919190 부터 91919210 으로 제한한다.

  8. 해킹개념 상시 유지용 문제 - Brutus Attack(문제 풀이) • 221.154.130.98 (추후 변동가능 있음) 를 대상으로 FTP 서버공격으로 ID/PW 를 획득하기. • FTP 크랙 프로그램 다운로드 위치 • http://hackersnews.org/tools/MFTPB.exe • Dic Generator(사전 생성기) 다운로드 위치 • http://hackersnews.org/tools/numero.zip • 샘플용으로 생성된 사전 다운로드 위치 • http://hackersnews.org/tools/RESULT.TXT • 위의 결과로 나온 아이디와 비밀번호를 이용하여 FTP 클라이언트을 이용하여 쉐도우을 빼낸다. • 아이디/비밀번호를 획득한 후에 숨겨져 있던 쉐도우 파일을 크랙하기. • 쉐도우(shadow) 파일 크랙용 크래커 다운로드 위치 • http://hackersnews.org/tools/john_win.zip

  9. 어셈블리 - 메모리 • 1바이트(byte)가 메모리의 기본단위이다. • 2바이트(word), 4바이트(double word), 8바이트(quad word), 16바이트(paragraph) • 메모리의 데이터는 숫자로 구성되어 있음. • ASCII 는 하나의 문자를 코딩하기 위해 1바이트를 사용. • Unicode 는 하나의 문자를 코딩하기 위해 2바이트를 사용.

  10. 어셈블리 – segment:offset • 16비트 BUS 의 한계를 극복하기 위해 20 비트 BUS를 사용하기 위해 고안. • segment 는 바이트의 집합. • offset 는 메모리의 접근 위치를 지정하기 위함. • physical address = segment x 10h + offset • 31337:12345 의 물리적 주소 = 325715 313370 31337 x 10h + 12345 ------- 325715

  11. 어셈블리 - 기초 명령어 • Jump if Above • JA : 비교 결과가 크면 점프 • JAE : 크거나 같으면 점프 • Jump if Below • JB : 비교 결과가 작으면 점프 • JGE : 크거나 같으면 점프 • JMP : 조건없이 점프 • JLE : 작거나 같으면 점프 • Jump if Not Greater or Equal • JNGE : 결과가 작으면 점프 • MOV : 오퍼랜드에 값을 이동시킴 • MUL : 곱하기 • NOP : 3 사이클 동안 작동안함 • POP : 스택에서 꺼냄 • PUSH : 스택에 넣음 • SUB : 나누기 • XCHG : 두 오퍼랜드의 값을 서로 바꿈 • Ascii Adjust for Addition • AAA : 덧셈후 10진 보정 • AAD : 나누기전에 10진 보정 • AAM : 곱한후 10진 보정 • AAS : 뺄셈후 10진 보정 • ADC : 더할때 carry 도 포함 • ADD : 오른쪽에 왼쪽으로 더하기 • CALL : 서브루틴을 호출 • CBW : 바이트를 워드로 저장 • CLD : 방향 플래그를 클리어 • CLI : 인터럽트 플래그를 클리어 • CMP : 오퍼랜드 비교하기 • Decimal Adjust for Addition • DAA : 덧셈후 AL 레지스터에 보정 • DEC : 오퍼랜드 값에서 1을 뺌 • DIVIDE : 나눗셈을 수행 • IMUL : 곱셈을 수행 • INC : 오퍼랜드 값을 1 증가시킴 • INT : 인터럽트를 호출 실습 포인트 기초 명령어 사용법

  12. 어셈블리 - 기초 명령어(실습 포인트) • EAX 레지스터에서 00ch 에 해당하는 값을 빼라. • EBX 레지스터의 값이 81010100h 일때 00000004h 주소로 점프하라. • 서브루틴 00000007h 를 호출하라.

  13. 어셈블리 - 기초 명령어(문제 풀이) • EAX 레지스터에서 00ch 에 해당하는 값을 빼는 법. • SUB EAX, 00ch • EBX 레지스터의 값이 81010100h 일때 00000004h 주소로 점프하라. • CMP EBX, 81010100h • JZ 00000004h • 서브루틴 00000007h 를 호출하라. • CALL 00000007h 실습 포인트 기초 명령어 사용법 AT&T 방식

  14. 어셈블리 - 기초 명령어(실습 포인트) • EAX 레지스터에서 00ch 에 해당하는 값을 AT&T 어셈블리 방식을 이용하여 빼라.

  15. 어셈블리 - 기초 명령어(문제 풀이) • EAX 레지스터에서 00ch 에 해당하는 값을 AT&T 어셈블리 방식을 이용하여 빼는 법. • SUB $0x00ch, %EAX

  16. 어셈블리 - 레지스터 • 레지스터란 무엇인가 ? • 레지스터는 수학적인 연산이 가능하다. • 레지스터는 CPU 내에 내장되어 있다. • 메모리는 읽고 쓰기는 가능하지만 연산은 불가능하다. • 메모리의 느린 처리능력을 레지스터가 보강해 준다. • 레지스터의 종류 • 일반 레지스터(General Purpose Register) • 포인터 레지스터(Pointer Register) • 스택 레지스터(Stack Register) • 플래그 레지스터(Flag Register) • 세그먼트 레지스터(Segment Register)

  17. 어셈블리 - 일반 레지스터 1 • eax • 32비트중 오른쪽 16비트 = AX[왼쪽 상위 AH(8비트)+오른쪽 하위 AL(8비트)] • 입출력과 산술연산에 사용 • 곱셈, 나눗셈, 변환 명령어 • ebx • 32비트중 오른쪽 16비트 = BX[왼쪽 상위 BH(8비트)+오른쪽 하위 BL(8비트)] • 베이스 레지스터 • 주소지정용 인덱스로 사용 • 계산에 사용 • 특정주소 지정때 DI 나 SI 와 함께 사용 • ecx • 32비트중 오른쪽 16비트 = CX[왼쪽 상위 CH(8비트)+오른쪽 하위 CL(8비트)] • 카운터 레지스터 • 루프횟수를 제어 32 비트 16 비트

  18. 어셈블리 - 일반 레지스터 2 • edx • 32비트중 오른쪽 16비트 = DX[왼쪽 상위 DH(8비트)+오른쪽 하위 DL(8비트)] • 데이터 레지스터 • 일부 연산에서 반드시 edx 를 사용해야 한다. • 큰수의 곱셈과 나눗셈 연산 • si • 16비트 원시 인덱스 레지스터 (source index register) • 문자 연산에 사용 • DS 와 함께 사용 • ESI(80386 의 32비트 확장 레지스터) • di • 16비트 목적지 인덱스 레지스터 (destination index register) • 문자 연산에 사용 • ES 와 함께 사용 • EDI(80386 의 32비트 확장 레지스터) 32 비트 16 비트

  19. 어셈블리 - 세그먼트 레지스터 • CS(Code Segment) • 코드를 저장 • DS(Data Segment) • 테이터를 저장 • EX(Extra Segment) • 스트리밍을 저장 • SS(Stack Segment) • 리턴어드레스를 저장

  20. 어셈블리 - 인덱스 레지스터 • SI(Source Index) • 문자열, 배열의 소스 인덱스를 저장. • DI(Destination Index) • 문자열, 배열의 목적지 인덱스를 저장. • IP(Instruction Pointer) • 차후 실행될 명령어의 주소를 저장.

  21. 어셈블리 - 스택 레지스터 • BP(Base Pointer) • 상위주소를 가리킴. • SP(Stack Pointer) • 하위 주소를 가리킴. 실습 포인트 스택 관련 명령어 사용법

  22. 어셈블리 - 스택 레지스터 (실습 포인트) • 다음의 문제는 AT&T 어셈블리 방식을 적용하여 푼다. • 베이스 포인터(Base Pointer) 의 값을 스택에 저장하라. • 스택 포인터(Stack Pointer) BP 에 넣어 스택을 초기화 시켜라.

  23. 어셈블리 - 스택 레지스터 (문제 풀이) • 다음의 문제는 AT&T 어셈블리 방식을 적용하여 푼다. • 베이스 포인터(Base Pointer) 의 값을 스택에 저장하기. • push %ebp • 스택 포인터(Stack Pointer) BP 에 넣어 스택을 초기화 시켜라. • movl %esp, %ebp

  24. 어셈블리 - 기초 명령어 사용법 실습 포인트 어셈블리 명령어 사용법 응용편 • Jump if Above • JA : 비교 결과가 크면 점프 • JAE : 크거나 같으면 점프 • Jump if Below • JB : 비교 결과가 작으면 점프 • JGE : 크거나 같으면 점프 • JMP : 조건없이 점프 • JLE : 작거나 같으면 점프 • Jump if Not Greater or Equal • JNGE : 결과가 작으면 점프 • MOV : 오퍼랜드에 값을 이동시킴 • MUL : 곱하기 • NOP : 3 사이클 동안 작동안함 • POP : 스택에서 꺼냄 • PUSH : 스택에 넣음 • SUB : 나누기 • XCHG : 두 오퍼랜드의 값을 서로 바꿈 • Ascii Adjust for Addition • AAA : 덧셈후 10진 보정 • AAD : 나누기전에 10진 보정 • AAM : 곱한후 10진 보정 • AAS : 뺄셈후 10진 보정 • ADC : 더할때 carry 도 포함 • ADD : 오른쪽에 왼쪽으로 더하기 • CALL : 서브루틴을 호출 • CBW : 바이트를 워드로 저장 • CLD : 방향 플래그를 클리어 • CLI : 인터럽트 플래그를 클리어 • CMP : 오퍼랜드 비교하기 • Decimal Adjust for Addition • DAA : 덧셈후 AL 레지스터에 보정 • DEC : 오퍼랜드 값에서 1을 뺌 • DIVIDE : 나눗셈을 수행 • IMUL : 곱셈을 수행 • INC : 오퍼랜드 값을 1 증가시킴 • INT : 인터럽트를 호출

  25. 어셈블리 - 기초 명령어 사용법 1(실습 포인트) • ax 의값을 36h 으로 설정하여라. • ax 의 값은 bx 주소값으로 대체하여라. • dx 의 값을 36h 으로 설정하여라. • dx 의 값을 증가 시켜라. • dx 의 값을 감소 시켜라.

  26. 어셈블리 - 기초 명령어 사용법 2(문제 풀이) • ax 의값을 36h 으로 설정하기. • mov ax, 36h • ax 의 값은 bx 주소값으로 대체하기. • mov ax, bx • dx 의 값을 36h 으로 설정하기. • mov dx, 50h • dx 의 값을 증가 시키기. • inc dx <--- 37h(dx++) • dx 의 값을 감소 시키기. • dec dx <--- 35h(dx--)

  27. 어셈블리 - 기초 명령어 사용법 2(실습 포인트) • ax 의값을 36h 으로 설정하여라. • ax 의 값은 bx 주소값으로 대체하여라. • dx 의 값을 36h 으로 설정하여라. • dx 의 값을 증가 시켜라. • dx 의 값을 감소 시켜라.

  28. 어셈블리 - 기초 명령어 사용법 2(문제 풀이) • ax 의값을 36h 으로 설정하기. • mov ax, 36h • ax 의 값은 bx 주소값으로 대체하기. • mov ax, bx • dx 의 값을 36h 으로 설정하기. • mov dx, 50h • dx 의 값을 증가 시키기. • inc dx <--- 37h(dx++) • dx 의 값을 감소 시키기. • dec dx <--- 35h(dx--)

  29. 어셈블리 - 기초 명령어 사용법 3 • 나중에 사용하기 위한 용도로 ax 에 임시로 값을 저장하라. • push ax <-- 16비트 레지스터만 가능함. • 다음의 예제에서 최종 ax 와 bx 의 값을 구하라. • mov ax, 36h <-- ax = 36h • mov bx, 2fh <-- bx = 2fh • xchg ax, bx <-- ax = 2fh, bx = 36h • push ax <-- ax 의 값을 저장. • mov ax, 21h <-- ax 의 값에 21h 를 대신 저장. • pop bx <-- bx 의 원래값인 2fh 를 회복시킴. • push bx <-- bx 의 값(2fh)를 저장. • pop ax <-- ax 의 새로운 값인 21h 에서 원래값인 2fn 을 회복시킴. 실습 포인트 어셈블리 명령어 사용법 응용편

  30. 어셈블리 - 기초 명령어 사용법 3(실습 포인트) • 다음의 dx 의 값과 ax 의 값을 교환하라. • mov dx, 36h • mov ax, 2fh • 참고 • xchg 사용시 8비트(h/l) 레지스터와 16비트(x) 레지스터는 절대 교환해서는 안된다. • xchg ah, bx <--- 8비트, 16비트가 같이 혼용 되어서는 안된다.

  31. 쉘코드 만들기(문제 풀이) 문자열을 넣고 주소를 계산한다. 계산된 문자열의 주소를 가리키는 주소를 레지스터에 넣는다.

  32. 쉘코드의 모습 쉘코드 만들기 실습 포인트 쉘실행 코드 만들기 • 쉘 실행코드란 무엇인가 ? • 쉘을 실행하는 기능을 가진 짧은 코드를 의미한다. • 쉘코드로 변환되어 사용된다. • execve(시스템 콜 번호 11) 와 setreuid(시스템 콜 번호 70) 의 함수가 필수적이다. • execve() 콜은 /bin/sh 를 실행시킬때 사용된다. • setreuid()콜은 suid root 프로그램에 보안상 설정된 일반사용자 권한을 루트권한으로 바꾸어 준다. • 쉘코드에서 이 권한을 복구하지 않으면 루트쉘이 아닌 일반쉘이 뜨기 때문에 반드시 복구해야 한다.

  33. 쉘코드 만들기(실습 포인트) • 쉘 실행코드를 제작한 후 어셈블과 링크과정을 거친 후 실행여부를 테스트 하라.

  34. 쉘코드 만들기(문제 풀이) 문자열을 넣고 주소를 계산한다. 계산된 문자열의 주소를 가리키는 주소를 레지스터에 넣는다.

  35. 쉘코드 만들기(문제 풀이) • mov [ebx + 7], al 분석하기 • al 에 들어있는 내용을 ebx +7 레지스터 주소에 저장하라는 명령이다. • 32 비트 eax 레지스터 대신에 8비트 al 레지스터를 사용하여 eax 의 처음 1바이트 만을 사용하고 있다. • eax 의 처음 1 바이트를 문자열의 7번째 주소로 복사한다. • ebx 에는 문자열 “/bin/shXAAAABBBB”에 대한 주소가 들어있다. 7번째 위치

  36. 쉘코드 만들기(문제 풀이) • mov [ebx + 8], ebx 분석 • mov [ebx + 12], eax 분석 • 32 비트(4바이트) 레지스터 하나를 통째로 사용하여 “AAAA” “BBBB” 부분에 값을 복사한다. • “AAAA” 부분인 ebx + 8 에는 문자열의 주소(ebx)가 저장된다. • “BBBB” 부분인 ebx + 12 에는 널주소인 0(eax) 이 저장된다.

  37. 쉘코드 만들기(문제 풀이) • lea ecx, [ebx + 8] • 주소 읽기 명령인 lea 를 이용하여 소스메모리의 주소를 목적지에 저장한다. • 문자열의 “AAAA” 부분에 해당되는 주소를 ecx 에 넣는다. • lea edx, [ebx + 12] • 주소 읽기 명령인 lea 를 이용하여 소스메모리의 주소를 목적지에 저장한다. • 문자열의 “BBBB” 부분에 해당되는 주소를 edx 에 넣는다. • 참고 : 주소값을 담고 있는 메모리의 주소값을 저장하는 이중법을 쓰는 이유는 execve() 함수가 마지막 2개의 인자를 받아들일때 포인터의 포인터 값으로 받아들이기 때문이다. 다시 말하면 인자의 값은 주소값을 담고 있느 메모리의 주소값이 되어야 한다.

  38. 쉘코드 만들기(문제 풀이) • 어셈블과 링크과정을 거친 후 실행하기. • $ nasm -f elf shell.asm • $ ld shell.o • $ ./a.out 실습 포인트 루트 장악용 쉘실행 코드 만들기

  39. 쉘코드 만들기(실습 포인트) • shell.asm 으로 생성된 a.out 를 루트 장악용 쉘실행코드로 변환하라.

  40. 쉘코드 만들기(문제 풀이) • shell.asm 으로 생성된 a.out 를 루트 장악용 쉘실행코드로 변환하기. • # chown root a.out • # chmod +s a.out • # exit • $ ./a.out

  41. 쉘코드 만들기 - 단일 세그먼트에서 처리하기 • shell.asm 은 아직은 미완성된 쉘코드라고 볼 수 있다. • 쉘코드는 단독으로 작동할 수 없으며 공격대상 프로그램내에 삽입되어야 그 기능이 작동된다. • 데이터 세그먼트에 들어있는 문자열을 명령코드 쪽에 저장하고 그 주소를 찾아내는 것이 관건이다. • 문자열 주소는 명령어가 들어있는 주소와 같은 곳에 존재한다. • 쉘코드 실행시의 정확한 메모리주소를 알 수 없기 때문에 EIP 를 참조하여 찾아내야 한다. • jmp 와 call 은 EIP 와 특정한 규칙관계를 가지고 있는 점을 이용한다. • jmp 와 call 은 EIP 를 메모리의 특정한 곳으로 이동하도록 지시하는 기능을 가지고 있다. • 프로그램 시작 > call 명령과 문자열이 있는 코드의 끝으로 jump > call 명령 실행 > 문자열 주소가 스택에 삽입 > call 명령은 맨처음의 jump 명령 바로 다음위치로 제어를 이동 > 프로그램은 문자열 주소를 스택에서 꺼낸뒤 쉘코드를 실행

  42. 쉘코드 만들기 - 단일 세그먼트에서 처리하기 • 프로그램 실행후 two 로 jump > 리턴주소(문자열 주소)를 스택에 삽입 > one 으로 이동 > 스택에서 문자열 주소를 꺼냄 > EBX 에 저장 > 쉘코드 실행 • jmp two • one : • pop ebx • [프로그램 코드부분] • two : • call one • db ‘예제에 사용되는 문자열’ • 다음 페이지에서 위의 알고리즘을 처리하는 코드를 제공하니 참고하시기 바란다.

  43. 쉘코드 만들기 - 단일 세그먼트에서 처리하기 shellcode_1.asm

  44. 쉘코드 만들기 - 널바이트 없애기 • 개선된 코드 ‘shellcode_1.asm’을 헥사 편집기를 이용하여 분석한다. • $ nasm shellcode_1.asm • $ hexedit shellcode1 ’00’ 으로 되어 있는 부분이 널바이트 이다. 문자열의 끝으로 인식하기 때문에 첫 2바이트만 버퍼에 복사한다. 쉘코드 모두를 버퍼로 복사하기 위해서는 모든 널바이트를 제거해야 한다.

  45. 쉘코드 만들기 - 널바이트 없애기 • ‘0’ 이라는 값을 사용하지 않고 레지스터에 ‘0’을 저장하기 위해서는 임의의 32 비트 값을 레지스터로 불러온 다음에 다시 그 값을 레지스터에 빼는 방법을 사용한다. • 이 방법은 용량이 늘어나기 때문에 쉘코드가 커진다는 단점을 가지고 있다. • 쉘코드는 실행의 특성상 되도록이면 용량을 작게 만드는 것이 좋은 방법이다. • mov ebx, 0x11223344 • sub ebx, 0x11223344

  46. 쉘코드 만들기 - 널바이트 없애기 • 레지스터와 그 레지스터 본인을 XOR 연산하게 되면 값이 ‘0’ 이 되기 때문에 널바이트 제거의 한 방법이 된다. • OR 연산 • 0 OR 0 = 0 • 0 OR 1 = 1 • 1 OR 0 = 1 • 1 OR 1 = 1 • XOR 연산 • 0 XOR 0 = 0 • 0 XOR 1 = 1 • 1 XOR 0 = 1 • 1 XOR 1 = 0 OR 연산과 XOR 연산의 차이점

  47. 쉘코드 만들기 - 단일 세그먼트에서 처리하기 shellcode_2.asm

  48. 쉘코드 만들기 - 널바이트 없애기 • 개선된 코드 ‘shellcode_2.asm’을 헥사 편집기를 이용하여 분석한다. • $ nasm shellcode_2.asm • $ hexedit shellcode2 shellcode.1.asm 보다 널바이트가 줄어든 것을 확인할 수 있다.

  49. 쉘코드 만들기 - 널바이트 없애기 • 어셈블된 기계어를 비교해 보면 다음과 같이 분석된다. • mov eax, 70 = B8 46 00 00 00 • 복사될 ’70’ 은 1바이트인데 32비트(4바이트) 레지스터의 특성상 3개의 널바이트가 생성된다. • EAX 의 8비트 레지스터인 AL 을 사용하여 널바이트를 제거할 수 있다. 0xB8 0x00000046 shellcode.1.asm 보다 널바이트가 줄어든 것을 확인할 수 있다.

  50. 쉘코드 만들기 - 널바이트 없애기 • 다음과 같이 EAX 대신 AL 을 사용하여 널바이트를 제거한다. • mov al, 70 ; = B0 46 • 위 같은 방식에서는 처음 1바이트만이 ‘0’으로 바뀌고 나머지는 바뀌지 않기 때문에 다음과 같이 레지스터 전체를 ‘0’으로 바꾸고 난후 다음 1바이트를 AL 로 복사하면 된다. • xor eax, eax ; 반드시 다음 명령을 위해 eax 를 0 으로 설정해야만 한다. • mov al, 70 ;

More Related