728x90
반응형

KISA 사물인터넷(IoT) 보안 시험 · 인증 기준 해설서 (2019. 02.)

STANDARD | KISA-GD-2019-0005

BASIC | KISA-GD-2019-0006

LITE | KISA-GD-2019-0007

 

2019_IoT_보안_시험인증기준_해설서_STANDARD.pdf
1.41MB
2019_IoT_보안_시험인증기준_해설서_BASIC.pdf
1.27MB
2019_IoT_보안_시험인증기준_해설서_LITE.pdf
1.20MB

728x90
728x90

'Security & Analysis > Security' 카테고리의 다른 글

[Openssl] CA 인증서 생성 및 공개키  (0) 2023.12.12
[Wireshark] packet DNS  (0) 2023.11.23
[SecureCoding] 정보 보안 표준  (0) 2023.04.07
728x90
반응형

Opcode: 스택

x64 아키텍쳐에서는 다음의 명령어로 스택을 조작할 수 있음

push val: val을 스택 최상단에 쌓음 (연산: rsp -= 8, [rsp] = val)

[Register]
rsp = 0x7fffffffc400

[Stack]
0x7fffffffc400 | 0x0 ≦ rsp
0x7fffffffc408 | 0x0

[Code]
push 0x31337

 

해석

rsp(Stack Pointer): 현재 스택의 최상위 주소
rsp 주소에 현재 스택의 최상위 값이 존재 - '0x0'

rsp 주소에서 8바이트(64비트 아키텍처에서는 8바이트가 한 워드) 위로 올라가면 또 다른 8바이트 값이 있음 - '0x0'

스택에 0x31337 푸시 - c400 - c3f8 -> 8만큼 차이

 

결과

[Register]
rsp = 0x7fffffffc3f8

[Stack]
0x7fffffffc3f8 | 0x31337 ≦ rsp
0x7fffffffc400 | 0x0
0x7fffffffc408 | 0x0

 

pop reg: 스택 최상단의 값을 꺼내서 reg에 대입 (연산: reg = [rsp], rsp += 8)

[Register]
rax = 0
rsp = 0x7fffffffc3f8

[Stack]
0x7fffffffc3f8 | 0x31337 <= rsp 
0x7fffffffc400 | 0x0
0x7fffffffc408 | 0x0

[Code]
pop rax

결과

[Register]
rax = 0x31337
rsp = 0x7fffffffc400

[Stack]
0x7fffffffc400 | 0x0 <= rsp 
0x7fffffffc408 | 0x0

 

Opcode: 프로시저

특정 기능을 수행하는 코드 조각

호출(Call): 프로시저를 부르는 행위

반환(Return): 프로시저에서 돌아오는 것

call 다음의 명령어 주소(return address, 반환 주소)를 스택에 저장하고 프로시저로 rip 이동

x64 어셈블리언어에는 프로시저의 호출과 반환을 위한 call, leave, ret 명령어 존재

call addr: addr에 위치한 프로시져 호출

연산: push return_address / jmp addr

예제

[Register]
rip = 0x400000
rsp = 0x7fffffffc400

[Stack]
0x7fffffffc3f8 | 0x0
0x7fffffffc400 | 0x0 <= rsp

[Code]
0x400000 | call 0x401000  <= rip
0x400005 | mov esi, eax
...
0x401000 | push rbp

 

해석

Register(레지스터): rip(명령 포인터 레지스터), rsp(스택 포인터)

after call 0x401000 - 현재 위치의 다음 명령어의 주소(0x400005)가 스택에 푸시됨

rsp는 8만큼 감소하여 스택의 새로운 맨 위를 가리킴

 

결과

[Register]
rip = 0x401000
rsp = 0x7fffffffc3f8

[Stack]
0x7fffffffc3f8 | 0x400005  <= rsp
0x7fffffffc400 | 0x0

[Code]
0x400000 | call 0x401000
0x400005 | mov esi, eax
...
0x401000 | push rbp  <= rip

 

leave: 스택프레임 정리

연산: mov rsp rbp / pop rbp

예제

[Register]
rsp = 0x7fffffffc400
rbp = 0x7fffffffc480

[Stack]
0x7fffffffc400 | 0x0 <= rsp
...
0x7fffffffc480 | 0x7fffffffc500 <= rbp
0x7fffffffc488 | 0x31337 

[Code]
leave

 

해석

Register(레지스터): rsp(스택 포인터), rbp(베이스 포인터)

mov rsp, rbp / pop rbp

leave 명령: 현재 함수의 프롤로그에서 설정된 스택 프레임이 제거됨

rsp가 rbp로 복원되고 rbp의 원래 값인 0x7fffffffc500이 rbp로 복원됨

 

결과

[Register]
rsp = 0x7fffffffc488
rbp = 0x7fffffffc500

[Stack]
0x7fffffffc400 | 0x0
...
0x7fffffffc480 | 0x7fffffffc500
0x7fffffffc488 | 0x31337 <= rsp
...
0x7fffffffc500 | 0x7fffffffc550 <= rbp

스택 프레임이란?

함수별로 자신의 지역변수 또는 연산과정에서 부차적으로 생겨나는 임시 값들을 저장하는 영역
스택 영역을 구분 없이 사용한다면, 서로 다른 두 함수가 같은 메모리 영역을 사용할 수 있음

A라는 함수가 B라는 함수를 호출하는데, 같은 스택 영역을 사용한다면 B에서 A의 지역변수를 모두 오염시킬 수 있음, B에서 반환한 뒤 A는 정상적인 연산을 수행할 수 없음

ret: return address로 반환

연산: pop rip

예제

[Register]
rip = 0x401021
rsp = 0x7fffffffc3f8

[Stack]
0x7fffffffc3f8 | 0x400005    <= rsp
0x7fffffffc400 | 0x123456789abcdef

[Code]
0x400000 | call 0x401000
0x400005 | mov esi, eax
...
0x401000 | push rbp
0x401001 | mov rbp, rsp
0x401004 | sub rsp, 0x30
0x401008 | mov BYTE PTR [RSP], 0x3
...
0x401020 | leave
0x401021 | ret <= rip

해석

Register: rip(명령 포인터 레지스터), rsp(스택 포인터)

Stack: rsp 주소에 현재 스택의 맨 위 값이 있음, 0x400005
rsp 주소에서 8바이트 아래로 내려가면 다음 슬롯이 있고 값은 0x123456789abcdef

call 0x401000: rip은 0x401000으로 변경됨

call 0x401000: 스택과 레지스터 상태

 

결과

[Register]
rip = 0x400005
rsp = 0x7fffffffc400

[Stack]
0x7fffffffc3f8 | 0x400005
0x7fffffffc400 | 0x123456789abcdef    <= rsp

[Code]
0x400000 | call 0x401000
0x400005 | mov esi, eax   <= rip
...
0x401000 | push rbp
0x401001 | mov rbp, rsp
0x401004 | sub rsp, 0x30
0x401008 | mov BYTE PTR [RSP], 0x3
...
0x401020 | leave
0x401021 | ret

 

스택 프레임의 할당과 해제

func 함수를 호출, 다음 명령어의 주소인 0x4000005는 스택에 push

main: rip

stack: rsp(0x7fffffffc400), rbp(0x7fffffffc480)

 

스택

push val: rsp를 8만큼 빼고, 스택의 최상단에 val을 쌓음

pop reg: 스택 최상단의 값을 reg에 넣고, rsp를 8만큼 더함

 

프로시저

call addr: addr의 프로시저 호출

leave: 스택 프레임 정리

ret: 호출자의 실행 흐름으로 돌아감

 

Q1. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?

[Register]
rbx = 0x401A40

=================================

[Memory]
0x401a40 | 0x0000000012345678
0x401a48 | 0x0000000000C0FFEE
0x401a50 | 0x00000000DEADBEEF
0x401a58 | 0x00000000CAFEBABE
0x401a60 | 0x0000000087654321

=================================

[Code]
1: mov rax, [rbx+8]
2: lea rax, [rbx+8]

0xC0FFEE

 

Q2. Code를 2까지 실행했을 때, rax에 들어있는 값은?

0x401A48

 

Q3. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?

[Register]
rax = 0x31337
rbx = 0x555555554000
rcx = 0x2

=================================

[Memory]
0x555555554000| 0x0000000000000000
0x555555554008| 0x0000000000000001
0x555555554010| 0x0000000000000003
0x555555554018| 0x0000000000000005
0x555555554020| 0x000000000003133A

==================================

[Code]
1: add rax, [rbx+rcx*8]
2: add rcx, 2
3: sub rax, [rbx+rcx*8]
4: inc rax

0x3133A

 

Q4. Code를 3까지 실행했을 때, rax에 저장된 값은?

0

 

Q5. Code를 4까지 실행했을 때, rax에 저장된 값은?

1

 

Q6. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?

[Register]
rax = 0xffffffff00000000
rbx = 0x00000000ffffffff
rcx = 0x123456789abcdef0

==================================

[Code]
1: and rax, rcx
2: and rbx, rcx
3: or rax, rbx

 

0x1234567800000000

 

Q7. Code를 2까지 실행했을 때, rbx에 저장된 값은?

0x000000009ABCDEF0

 

Q8. Code를 3까지 실행했을 때, rax에 저장된 값은?

0x123456789ABCDEF0

 

Q9. 레지스터, 메모리 및 코드가 다음과 같다. Code를 1까지 실행했을 때, rax에 저장된 값은?

[Register]
rax = 0x35014541
rbx = 0xdeadbeef

==================================

[Code]
1: xor rax, rbx
2: xor rax, rbx
3: not eax

0xEBACFBAE

 

35014541

deadbeef

3d 5e (0a) (1d) 4b 5e (4e) (1f)

EB AC FB AE

 

728x90
728x90
728x90
반응형

openssl

 

1. CA(Certificate Authority)) 개인키 생성

openssl genrsa -out rootCA.key 2048

 

2. CA CSR(Certificate Signing Request) 생성

openssl req -new -key rootCA.key -out rootCA.csr

- 인증 서명 요청, 인증서를 발급하는데 필요한 인증 신청서

3. CA CRT 생성

openssl x509 -req -in rootCA.csr -signkey rootCA.key -out rootCA.crt

CA 인증서 생성

 

공개키 생성(.pem)

# Generate a private key
openssl genpkey -algorithm RSA -out private_key.pem

# Extract the public key from the private key
openssl rsa -pubout -in private_key.pem -out public_key.pem

공개키 변환(.der)

# unable to load certificate
openssl x509 -pubkey -noout -inform PEM -in public_key.pem -outform DER -out public_key.der
# create public_key.pem
openssl pkey -pubout -inform PEM -in private_key.pem -outform DER -out public_key.der

1. ASN.1 구조 확인

openssl asn1parse -inform DER -in public_key.der

2. 16진수 콘텐츠 보기

xxd public_key.der

 

 

 

 

 

 

참고

goldsony.tistory.com/223

 

728x90
728x90
728x90
반응형

 

공격자는 비지박스(busybox)라는 리눅스 명령어 패키지를 이용해서 wget 명령으로 악성코드를 다운로드 해 실행

 

x86-64 아키텍처

인텔의 32비트 CPU 아키텍처, 64: CPU가 한번에 처리할 수 있는 데이터의 크기
- 인텔의 x86 아키텍처와 호환되는 64bit 아키텍처 IA-64 발표

Intel 회사에서 개발한 컴퓨터의 중앙처리장치(CPU)
ISA(Instruction Set Architecture)

 

범용 레지스터(General Register)

이름 주용도
rax (accumulator register) 함수의 반환 값
rbx (base register) x64에서는 주된 용도 없음
rcx (counter register) 반복문의 반복 횟수, 각종 연산의 시행 횟수
rdx (data register) x64에서는 주된 용도 없음
rsi (source index) 데이터를 옮길 때 원본을 가리키는 포인터
rdi (destination index) 데이터를 옮길 때 목적지를 가리키는 포인터
rsp (stack pointer) 사용중인 스택의 위치를 가리키는 포인터
rbp (stack base pointer) 스택의 바닥을 가리키는 포인터

세그먼트 레지스터(Segment Register)

x64 아키텍처에는 cs, ss, ds, es, fs, gs 총 6가지 세그먼트 레지스터 존재

arm, mips, mpsl, x86

 

Q1. rax = 0x0123456789abcedf일 때, eax의 값은?

0x89abcdef

 

Q2. rax = 0x0123456789abcdef일 때, al의 값은?

0xef

 

Q3. rax에서 rbx를 뺐을 때, ZF가 설정되었다. rax와 rbx의 대소를 비교하시오.

==

 

Q4. rax = 0x0123456789abcdef일 때, ax의 값은?

0xcdef

 

Q5. rax = 0x0123456789abcdef일 때, ah의 값은?

0xcd

 

프로세스 메모리 구조

섹션

윈도우의 PE 파일은 PE 헤더와 1개 이상의 섹션으로 구성됨

".text" 섹션: PE코드, 실행 가능한 기계 코드가 위치하는 영역

".data" 섹션: PE가 실행중에 참조하는 데이터, 컴파일 시점에 값이 정해진 전역 변수들이 위치, 읽기/쓰기 권한 부여

".rdata" 섹션: 컴파일 시점에 값이 정해진 전역 상수와 참조할 DLL 및 외부 함수들의 정보 저장, 읽기 권한 부여(쓰기 불가능), str_ptr: "readonly" 문자열

섹션이 아닌 메모리

윈도우의 가상 메모리 공간에는 섹션 + 스택/힙 등이 적재됨

스택: 지역 변수나 함수의 리턴 주소가 저장됨, 읽기/쓰기 권한 부여 (기존 주소보다 낮은 주소로 확장됨)

어셈블리어와 x86-64

어셈블리 언어

컴퓨터의 기계어와 치환되는 언어, 명령어 집합구조(Instruction Set Architecture, ISA)

x64 어셈블리 언어

명령어(Operation Code, Opcode)와 목적어에 해당하는 피연산자(Operand)

x86-64 어셈블리어 문법 구조

mov eax, 3

(opcode: 대입해라, operand1: eax에, operand2: 3을)

명령어

인텔의 x64에는 매우 많은 명령어가 존재함, 본 커리큘럼에서는 이 코스와 다음 코스에 걸쳐, 이 중 중요한 21개의 명령어를 자세히 학습할 것.

명령 코드  
데이터 이동(Data Transfer) mov, lea
산술 연산(Arithmetic) inc, dec, add, sub
논리 연산(Logical) and, or, xor, not
비교(Comparison) cmp, test
분기(Branch) jmp, je, jg
스택(Stack) push, pop
프로시져(Procedure) call, ret, leave
시스템 콜(System call) syscall

피연산자

상수(Immediate Value), 레지스터(Register), 메모리(Memory)

크기 지정자(Size Directive) TYPE PTR

여기에 타입에는 BYTE, WORD, DWORD, QWORD가 올 수 있으며, 각각 1바이트, 2바이트, 4바이트, 8바이트의 크기 지정

메모리 피연산자의 예

메모리 피연산자  
QWORD PTR [0x8048000] 0x8048000의 데이터를 8바이트만큼 참조
DWORD PTR [0x8048000] 0x8048000의 데이터를 4바이트만큼 참조
WORD PTR [rax] rax가 가르키는 주소에서 데이터를 2바이트 만큼 참조

자료형 WORD의 크기가 2바이트인 이유

초기에 인텔은 WORD의 크기가 16비트인 IA-16 아키텍처를 개발했음
CPU의 WORD가 16비트였기 때문에, 어셈블리어에서도 WORD를 16비트 자료형으로 정의하는 것이 자연스러웠음

이후에 개발된 IA-32, x86-64 아키텍처는 CPU의 WORD가 32비트, 64비트로 확장됨
이 둘의 아키텍처에서는 WORD 자료형이 32비트, 64비트의 크기를 지정하는 것이 당연할 것

하지만 인텔은 WORD 자료형의 크기를 16비트로 유지함 (새로운 아키텍처 호환 여부)

DWORD(Double Word, 32bit), QWORD(Quad Word, 64bit) 자료형을 추가로 만듦

논리 연산 - and & or

# add
[Register]
eax = 0xffff0000
ebx = 0xcafebabe

[Code]
and eax, ebx

[Result]
eax = 0xcafe0000
# or
[Register]
eax = 0xffff0000
ebx = 0xcafebabe

[Code]
or eax, ebx

[Result]
eax = 0xffffbabe

논리 연산 - xor & not

[Register]
eax = 0xffffffff
ebx = 0xcafebabe

[Code]
xor eax, ebx

[Result]
eax = 0x35014541

xor dst, src: dst와 src의 비트가 서로 다르면 1, 같으면 0

- f0 e1 d2 c3 b4 a5

[Register]
eax = 0xffffffff

[Code]
not eax

[Result]
eax = 0x00000000

 

정리

종류 연산자 의미
데이터 이동 연산자 mov dst, src src의 값을 dst에 대입
데이터 이동 연산자 lea dst, src src의 유효 주소를 dst에 대입
산술 연산 add dst, src src의 값을 dst에 더함
산술 연산 sub dst, src src의 값을 dst에서 뺌
산술 연산 inc op op의 값을 1 더함
산술 연산 dec op op의 값을 1 뺌
논리 연산 and dst, src dst와 src가 모두 1이면 1, 아니면 0
논리 연산 or dst, src dst와 src 중 한 쪽이라도 1이면 1, 아니면 0
논리 연산 xor dst, src dst와 src가 다르면 1, 같으면 0
논리 연산 not op op의 비트를 모두 반전
비교 cmp op1, op2 op1에서 op2를 빼고 플래그를 설정
비교 test op1, op2 op1과 op2에 AND 연산을 하고, 플래그를 설정
분기 jmp addr addf로 rip 이동
분기 je addr 직전 비교에서 두 피연산자의 값이 같을 경우 addr로 rip 이동
분기 jg addr 직전 비교에서 두 피연산자 중 전자의 값이 더 클 경우 addr로 rip 이동

 

728x90
728x90
728x90
반응형

전처리(Preprocessing)

컴파일러가 소스 코드를 어셈블리어로 컴파일하기 전에, 필요한 형식으로 가공하는 것

add.c를 add.i로 전처리

$ gcc -E add.c > add.i
$ cat add.i

 

컴파일(Compile)

C로 작성된 소스 코드를 어셈블리어로 변역하는 것

소스 코드를 어셈블리 코드로 컴파일: "-S" 옵션

$ gcc -S add.i -o add.S
$ cat add.S

 

어셈블(Assemble)

컴파일로 생성된 어셈블리어 코드를 ELF 형식의 목적 파일(Object file)로 변환하는 과정

* ELF: 리눅스 실행파일 형식, PE: 윈도우 목적 파일 형식

목적 파일 변환 - 어셈블리 코드가 기계어로 번역되므로 더이상 사람이 해석하기 어려워짐

gcc "-c" 옵션을 통해 add.S를 목적 파일로 변환하고, 결과로 나온 파일을 16진수로 출력한 것

링크(Link)

여러 목적 파일들을 연결하여 실행 가능한 바이너리로 만드는 과정

디컴파일러(Decompiler)

-

정적 분석(Static Analysis), 동적 분석(Dynamic Analysis)

정적 분석

장점

1. 프로그램의 전체 구조를 파악하기 쉬움
2. 분석 환경의 제약에서도 비교적 자유로움
3. 바이러스와 같은 악성 프로그램의 위협으로부터 안전함

단점

1. 난독화(Obfuscation)가 적용되면 분석이 매우 어려워짐

2. 다양한 동적 요소를 고려하기 어려움

동적 분석

장점

1. 코드를 자세히 분석해보지 않고도 프로그램의 개략적인 동작을 파악할 수 있음

단점

1. 분석 환경을 구축하기 어려울 수 있음

2. 안티 디버깅(Anti Debudding)

if (is_debugging())
	exit(-1);
Func();

 

컴퓨터 구조(Computer Architecture)

컴퓨터가 효율적으로 작동할 수 있도록 하드웨어 및 소프트웨어의 기능을 고안하고, 이들을 구성하는 방법

폰 노이만 구조, 하버드 구조, 수정된 하버드 구조

명령어 집합구조(Instruction Set Architecture, ISA)

CPU가 처리해야하는 명령어를 설계하는 분야

(e.g., ARM, MIPS, AVR, 인텔의 x86 및 x86-64 아키텍처)

마이크로 아키텍처(Micro Architecture)

정의된 명령어 집합을 효율적으로 처리할 수 있도록, CPU의 회로를 설계하는 분야

 

> 폰 노이만 구조와 명령어 집합 구조(Instruction Set Architecture) 중 x86-64 아키텍처

폰 노이만: 초기 컴퓨터 과학자 중 컴퓨터에 연산, 제어, 저장의 세 가지 핵심 기능이 필요하다고 생각함

근대의 컴퓨터는 연산과 제어를 위해 중앙처리장치(Central Processing Unit, CPU)를, 저장을 위해 기억장치(memory)를 사용함

장치간에 데이터나 제어 신호를 교환할 수 있도록 버스(bus)라는 전자 통로를 사용함

중앙처리장치

산술논리장치(Arithmetic Logic Unit, ALU): CPU의 산술/논리 연산 처리

제어장치(Control Unit): CPU 제어

레지스터(Register): CPU에 필요한 데이터 저장

기억장치

컴퓨터가 동작하는데 필요한 여러 데이터를 저장하기 위해 사용됨

주기억장치: 프로그램 실행과정에서 필요한 데이터들을 임시로 저장하기 위해 사용 (e.g., 램(Random-Access Memory, RAM)

보조기억장치: 운영 체제, 프로그램 등과 같은 데이터를 장기간 보관하고자 할 때 사용 (e.g., 하드 드라이브(Hard Disk Drive, HDD), SSD(Solid State Drive))

버스

컴퓨터 부품과 부품 사이 또는 컴퓨터와 컴퓨터 사이에 신호를 전송하는 통로

데이터 버스(Data Bus): 데이터 이동

주소 버스(Address Bus): 주소 지정

 

  • 범용 레지스터(General Register)
  • 세그먼트 레지스터(Segment Register)
  • 플래그 레지스터(Flag Register)
  • 명령어 포인터 레지스터(Instruction Pointer Register, IP)

 

728x90
728x90
728x90
반응형

WAN(Wide Area Network): ISP가 제공하는 광역 네트워크

(e.g., 인터넷, 전송망, 백업LTE)

LAN(Local Area Network): 근거리 지역 내의 공유 네트워크 - 스위치와 보안장비로 구성됨

(e.g., 인터넷 스위치, 전송장비, LTE라우터 - 업무, 인터넷, 무선, IPT)

 

네트워크는 ES(End System)와 IS(Intermediate System)를 주체로 구성됨

 

IPv4 IP와 IPv6 IP는 주소체계가 서로 다른데 어떻게 통신이 가능한가?

3가지 방식의 기술 사용: 듀얼스택(Dual Stack) + 터널링(Tunneling) + 헤더 변환(Translation)

 

듀얼스택: 물리적인 시스템은 하나이지만, 논리적으로 IPv4/IPv6 둘 다 지원

터널링: 이기종 네트워크를 경유할 경우 사용, IPv6 패킷을 IPv4 패킷 속에 또는 반대로 캡슐화함

헤더 변환: IPv4/6 망 사이의 연동 기술, NAT-PT(Network Address Translation-Protocol Translation)

 

DHCP(Dynamic Host Configuration Protocol)

네트워크에 접속할 때 단말 장치에 동적으로 IP를 할당해주는 역할을 하는 Protocol

 

침입차단(Firewall)

네트워크 접근제어

 

-

[DNS RFC]

RFC 1034: 도메인 이름 - 개념 및 기능
RFC 1035: 도메인 이름 - 구현 및 사양
RFC 1122: 인터넷 호스트에 대한 요구 사항 - 통신 계층
RFC 1123: 인터넷 호스트에 대한 요구 사항 - 애플리케이션 및 지원
RFC 1876: 도메인 이름 시스템에서 위치 정보를 표현하는 수단
RFC 1995: DNS에서 증분 영역 전송
RFC 1996: 영역 변경에 대한 프롬프트 알림 메커니즘(DNS 알림)
RFC 2136: DNS 업데이트(Domain Name System)의 동적 업데이트
RFC 2181: DNS 사양에 대한 설명
RFC 2308: DNS 쿼리의 부정 캐싱(DNS NCACHE)
RFC 2535: 도메인 이름 시스템 보안 확장
RFC 2782: 서비스 위치를 지정하기 위한 DNS RR(DNS SRV)
RFC 2845: DNS에 대한 비밀 키 트랜잭션 인증(TSIG)
RFC 2915: NAPTR(명명 기관 포인터) DNS 리소스 레코드
RFC 2930: DNS에 대한 비밀 키 설정(TKEY RR)
RFC 2931: DNS 요청 및 트랜잭션 서명( SIG(0)s )
RFC 3110: DNS(도메인 이름 시스템)의 RSA/SHA-1 SIG 및 RSA KEY
RFC 3445: RR(KEY Resource Record) 범위 제한
RFC 3596: IP 버전 6을 지원하는 DNS 확장
RFC 3645: DNS에 대한 비밀 키 트랜잭션 인증을 위한 일반 보안 서비스 알고리즘(GSS-TSIG)

DNS

클라이언트가 DNS(Domain Name System) 요청

DNS서버가 클라이언트에게 요청에 대한 응답을 줌(DNS 응답 패킷)

 

Flags

Response(Query)

요청 패킷(0), 응답 패킷(1)

dns.flags.response == 1 (응답)

dns.flags.response == 0 (요청)

Opcode

쿼리 유형 지정, 보통은 0000 포함

Authoritative Answer

도메인 이름에 대해 믿을 수 있는 서버로부터의 응답임을 표시

Truncation

응답이 잘렸는지, 아니라면 0 비트로 표시

Recursion Desired

재귀를 사용하는지 여부(대부분의 DNS는 재귀 쿼리 사용)

Reserved

예약된 비트, 비워 놓음. 0으로 설정

 

참고

https://learn.microsoft.com/ko-kr/windows/win32/dns/dns-standards-documents

 

728x90
728x90
728x90
반응형
목차
1. 프리다(Frida)란?
2. 프리다의 주요 기능
3. 프리다 환경 구축
  - 녹스(Nox) 앱플레이어 설치
  - 아나콘다 파이썬 환경 구축
  - 프리다 설치 및 실행
4. 프리다 기능 살펴보기

  - 기본 명령어 활용(Frida CLI 이해)
  - 기본 명령어 활용(프로세스, 트레이스, 디바이스 제어)
  - 기본 명령어 활용(프로세스 중지)
5. 프리다 기본 문법
  - Java.perform(fn)

  - Java.use(className)
  - Java.choose(className, callbacks)
  - Java.enumerateLoadedClasses(callbacks)
  - setImmediate(fn)
  - Overloading
-
프리다 CLI 활용
자바스크립트 파일 사용
파이썬 바인딩 이해
프리다 챌린지로 연습해보기
프리다 실무 활용

5. 프리다 기본 문법

Java.perform(fn)

Java.use(className)

Java.enumerateLoadedClasses(callbacks)

Java.choose(className, callbacks)

setImmediate(fn)

Overloading

 

기본 뼈대 구조

Java.perform(fn)

  • 현재 스레드가 가상머신에 연결되어 있는지 확인하고 fn을 호출

- Java.perform이 실행이 되면 fn 내부로 입력한 코드가 지정한 앱애 접근하여 실행하게 됨

Java.perform(function() {
/*
	...
    do sth
    ...
*/
})

Java.use(className)

  • Java.use ()는 변수와 메소드에 액세스 할 수 있는 클래스 객체를 반환
  • 메소드 구현을 변경하려면 새로운 메소드로 덮어 써야 함
  • 인스턴스를 반환하는 것이 아닌 클래스 객체를 반환함

- className 클래스를 사용하겠다고 선언

- 인스턴스를 다루기 위해서는 Java.choose라는 API를 사용해야 함

  • 앱에서 사용하는 클래스와 연동되는 myClass를 정의
  • .implementation: 앱에서 정의된 메소드의 구현 내용을 재작성
Java.perform(function() {
	var myClass = Java.use(com.mypackage.name.class)
    
    myClass.myMethod.implementation = function(param) {
    	// do sth
    }
}

myClass 내 myMethod 메소드를 다룸, implementation를 하여 myMethod를 재작성하여 진단자 마음대로 해당 메소드를 재작성

위의 코드는 parameter가 하나인 경우, 인자값이 두 개 이상이라면 function(p1, p2)로 기재


Java.choose(className, callbacks)

  • Java.choose(className, callbacks)
  • 힙에서 인스턴스화 된 객체 찾기 가능
  • callbacks: onMatch, onComplete
  • onMatch: 실시간으로 인스턴스에 대해 호출
  • onComplete: function()의 모든 인스턴스가 열거될 때 호출
Java.perform(function() {
	Java.choose(com.mypackage.name.class, {
    	"onMatch": function(instance) {
        	console.log(instance.toString())
        },
        "onComplete": function() {}
    })
})

Java.perform: 가상머신 연결 확인

Java.choose: com.mypackage.name.class라는 클래스를 지정하고, 해당 클래스에 대한 인스턴스(instance) 객체로 받게 됨

onMatch는 Frida가 요청에 일치하는 것을 찾으면 하나 이상의 인수로 호출됨

console.log라는 함수를 통해 해당 인스턴스를 문자열 값(toString)으로 주게 됨 -> 찾은 인스턴스에 대한 값이 콘솔로 출력됨

모든 출력을 마치면(일치하는 것을 모두 찾으면) onComplete 사용 -> Java.choose 사용


Java.enumerateLoadedClasses(callbacks)

  • 로드된 모든 클래스를 열거하고 모든 일치 항목을 출력
  • onMatch: 일치하는 것을 찾으면 호출
  • onComplete: 가능한 일치(Match)를 모두 마치면 사용됨
Java.perform(function() {
	Java.enumerateLoadedClasses( {
    	"onMatch": function(className) {
        	console.log(className)
        },
        "onComplete": function() {}
    })
})

setImmediate(fn)

  • Process terminated 오류 해결하기
setImmediate(function() {	// prevent timeout
	console.log("[*] Starting script");
    
    Java.perform(function() {
    	myClass = Java.use("com.packagen.name.class.name");
        myClass.implementation = function(v) {
        	// do sth.
	}
})})

 

메소드 구현을 재작성할 때 유의 (다형성)

만약 다음과 같이 세 가지의 경우는 어떻게 처리할까? overload() 제공

  • 첫 번째, 입력받는 인수가 없는 메소드
  • 두 번째, 두 개의 바이트 배열을 인수로 입력받는 메소드
  • 세 번째, 앱의 context와 Boolean 형태의 인수로 입력받는 메소드
// 1) 입력받는 인수가 없는 메소드
myClass.myMethod.overload().implementation = function() {
	// do sth
}

// 2) 두 개의 바이트 배열을 인수로 입력받는 메소드
myClass.myMethod.overload("[B", "[B").implementation = function(param1, param2) {
	// do sth
}

// 3) 앱의 context와 Boolean 형태의 인수로 입력받는 메소드
myClass.myMethod.overload("android.context.Context", "boolean").implementation = function(param1, param2) {
	// do sth
}

Overloading

overload() 매개변수 카테고리

.overload()

.overload('int')

.overload('float')

.overload('[B') // byte array

.overload('[B', '[B', '[B')

.overload('java.io.File')

.overload('java.lang.String')

.overload('android.view.View')

.overload('android.app.Activity')

.overload('android.content.Context')

.overload('android.content.Context', 'java.lang.String')

.overload('java.lang.String', 'java.lang.String')

.overload('android.graphics.Bitmap')

.overload('java.util.List')

.overload('android.content.Context', 'java.lang.String', 'java.lang.String')

.overload('android.app.Activity', 'int', 'int', 'int', 'boolean')

 

 

728x90
728x90
728x90
반응형
목차
1. 프리다(Frida)란?
2. 프리다의 주요 기능
3. 프리다 환경 구축
  - 녹스(Nox) 앱플레이어 설치
  - 아나콘다 파이썬 환경 구축
  - 프리다 설치 및 실행
4. 프리다 기능 살펴보기

  - 기본 명령어 활용(Frida CLI 이해)
  - 기본 명령어 활용(프로세스, 트레이스, 디바이스 제어)
  - 기본 명령어 활용(프로세스 중지)

-
프리다 기본 문법
프리다 CLI 활용
자바스크립트 파일 사용
파이썬 바인딩 이해
프리다 챌린지로 연습해보기
프리다 실무 활용

4. 프리다 기능 살펴보기

독립된 가상 환경으로 접속한 상태

frida-trace -i "open" -U com.android.chrome

Nox Chrome에서 동작 시 open() 함수에 대해 출력

open: Auto-generated handler at "C:\\Users\\user\\__handlers__\\libc.so\\open.js"

해당 경로로 open.js 파일 확인해보면,

onEnter할 때, open()이라는 함수를 출력하도록 되어 있음

onLeave는 별도 처리하지 않음

(py3) user@DESKTOP-JII5KL2 C:\Users\user\__handlers__\libc.so
$ type open.js
/*
 * Auto-generated by Frida. Please modify to match the signature of open.
 * This stub is currently auto-generated from manpages when available.
 *
 * For full API reference, see: https://frida.re/docs/javascript-api/
 */

{
  /**
   * Called synchronously when about to call open.
   *
   * @this {object} - Object allowing you to store state for use in onLeave.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {array} args - Function arguments represented as an array of NativePointer objects.
   * For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8.
   * It is also possible to modify arguments by assigning a NativePointer object to an element of this array.
   * @param {object} state - Object allowing you to keep state across function calls.
   * Only one JavaScript function will execute at a time, so do not worry about race-conditions.
   * However, do not use this to store function arguments across onEnter/onLeave, but instead
   * use "this" which is an object for keeping state local to an invocation.
   */
  onEnter(log, args, state) {
    log('open()');
  },

  /**
   * Called synchronously when about to return from open.
   *
   * See onEnter for details.
   *
   * @this {object} - Object allowing you to access state stored in onEnter.
   * @param {function} log - Call this function with a string to be presented to the user.
   * @param {NativePointer} retval - Return value represented as a NativePointer object.
   * @param {object} state - Object allowing you to keep state across function calls.
   */
  onLeave(log, retval, state) {
  }
}

 

log('open()'); 를 다음과 같이 코드 변경하여

onEnter function의 args를 통해 호출 인수가 어떻게 접근이 가능한지 알아볼 것

 

notepad open.js 로 메모장 열어서 파일 내용 수정

log('open(' + 'pathname=' + args[0] + ', flags=' + args[1] + ')');

* 참고: Windows 명령 프롬프트(cmd) 파일 편집 방법

1) notepad (file.js)

2) 리눅스 기반의 vi, vim 사용 (bash  사용 - 리눅스 프로그램 설치 후 사용)

 

다시 open trace 실행

frida-trace -i "open" -U com.android.chrome:privileged_process0

(py3) user@DESKTOP-JII5KL2 C:\Users\user
$ frida-trace -i "open" -U com.android.chrome:privileged_process0
Instrumenting...
open: Loaded handler at "C:\\Users\\user\\__handlers__\\libc.so\\open.js"
Started tracing 1 function. Press Ctrl+C to stop.
           /* TID 0x1132 */
  9955 ms  open(pathname=0xd6fb8a31flags=0x2)
           /* TID 0x1133 */
  9971 ms  open(pathname=0xd6fb8a31flags=0x2)
           /* TID 0x10d4 */
 10010 ms  open(pathname=0xd6fb8a31flags=0x2)
           /* TID 0x10f4 */
 32908 ms  open(pathname=0x55833950flags=0x80000)
 35102 ms  open(pathname=0x55836060flags=0x80000)

fride.re > DOCS > API Reference - JavaScript API > find "Memory" 참조

https://frida.re/docs/javascript-api/

open.js 수정

log('open(' + 'pathname=' + Memory.readUtf8String(args[0]) + ', flags=' + args[1] + ')');

메모리 주소가 아닌 어느 경로에서 불러오는지 확인

 

프로세스 중지(process Name이나 PID)

frida-kill -U Chrome

Chrome process 종료

 

 

728x90
728x90
728x90
반응형
목차
1. 프리다(Frida)란?
2. 프리다의 주요 기능
3. 프리다 환경 구축
  - 녹스(Nox) 앱플레이어 설치
  - 아나콘다 파이썬 환경 구축
  - 프리다 설치 및 실행
4. 프리다 기능 살펴보기

  - 기본 명령어 활용(Frida CLI 이해)
-
프리다 기본 문법
프리다 CLI 활용
자바스크립트 파일 사용
파이썬 바인딩 이해
프리다 챌린지로 연습해보기
프리다 실무 활용

4. 프리다 기능 살펴보기

frida

프리다 CLI인 REPL 인터페이스, 신속한 프로토타이핑과 손쉬운 디버깅을 목표로 하는 도구

* REPL: Read, Eval, Print, Loop - 읽고, 실행하고, 출력하고, 반복하는 과정

frida-ps

프리다에 연결된 프로세스 목록을 출력하기 위한 도구

frida-ls-devices

연결된 디바이스를 출력하는 도구

frida-trace

함수 호출을 동적으로 추적하기 위한 도구

frida-kill

프로세스를 종료하는 도구

frida -U

Nox 애뮬레이터에 대해 사용

 

Playstore에서 Chrome 다운로드

frida-ps -U

Chrome에 해당하는 프로세스 옵션을 확인

Failed to attach: unable to connect to remote frida-server: closed

에러 원인: 에뮬레이터 프로세스 실행하지 않음

frida를 (USB를 통해) 안드로이드 애뮬레이터에 연결하고 chrome 디버깅을 시작

* 참고: https://github.com/frida/frida/issues/92

user@DESKTOP-JII5KL2 C:\Users\user
$ nox_adb devices
List of devices attached
127.0.0.1:62001 device


user@DESKTOP-JII5KL2 C:\Users\user
$ nox_adb shell
d2q:/ # whoami
root
d2q:/ # cd /data/local/tmp/frida-server-16.0.11-android-x86/
d2q:/data/local/tmp/frida-server-16.0.11-android-x86 # ls -al
total 52368
drwxrwxr-x 2 root  root      4096 2023-03-31 08:38 .
drwxrwxrwx 4 shell shell     4096 2023-04-07 09:02 ..
-rwxrwxrwx 1 root  root  53612252 2023-03-31 08:37 frida-server-16.0.11-android-x86
d2q:/data/local/tmp/frida-server-16.0.11-android-x86 # ./frida-server-16.0.11-android-x86 &
[1] 4871
1|d2q:/data/local/tmp/frida-server-16.0.11-android-x86 # ps | grep frida-server
root      4871  4860  62676  49640            d4415cc0 S ./frida-server-16.0.11-android-x86

다시 시도

frida -U com.android.chrome

Tab 입력 시 사용 가능한 명령어 확인

frida -U com.android.chrome -l chrome.js

frida를 USB를 통해 android 에뮬레이터에서 실행 중인 chrome app에 연결하고, chrome.js를 load함

(py3) user@DESKTOP-JII5KL2 C:\Users\user
$ frida -U com.android.chrome -l chrome.js
usage: frida [options] target
frida: error: [Errno 2] No such file or directory: 'C:\\Users\\user\\chrome.js'

파일 생성 후 다시 시도..

-Ua 옵션: 현재 실행중인 앱만 출력

(py3) user@DESKTOP-JII5KL2 C:\Users\user
$ frida-ps -Ua
 PID  Name      Identifier
4  --------  --------------------
4024  Chrome    com.android.chrome
2686  Facebook  com.facebook.katana
2344  설정        com.android.settings
frida-ls-devices
frida-ps -D 127.0.0.1:62001

frida-ls-devices: 프리다에 연결된 디바이스 출력 도구(여러 개의 디바이스와 상호작용할 때 유용)

 

 

728x90
728x90
728x90
반응형
목차
CVE(Common Vulnerabilities and Exposures)
NVD(National Vulnerability Database)
- CVSS(Common Weakness Enumeration)
CWE(Common Weakness Enumeration)

e.g., CVE-2022-1009 / CVE-2023-1009

CVE (Common Vulnerabilities and Exposures)

https://www.cve.org/

공통 취약성 및 노출

MITRE에서 관리하는 공개된 취약점 및 노출 목록


1) CVE-2022-1009 - https://www.cve.org/CVERecord?id=CVE-2022-1009

설명: 악의적인 사전 설정 구성을 업로드할 때 관리 페이지에 다시 출력하기 전에 구성 매개변수를 삭제하고 반환하지 않음 → Reflected Cross-Site Scripting 발생 가능성(공격자가 admin 계정으로 악성 구성 파일을 업로드 해야 함)

제품: 3.9.9 이전의 Smush WordPress 플러그인 / Smush - Lazy Load Images, Optimize & Compress Images

생성 날짜: (Published/Updated) 2022-05-30

피해규모: 중간(NVD 참조)

참조https://wpscan.com/vulnerability/bb5af08f-bb19-46a1-a7ac-8381f428c11e

 

2) CVE-2023-1009 - https://www.cve.org/CVERecord?id=CVE-2023-1009

설명: /cgi-bin/mainfunction.cgi 파일의 sub_1DF14 함수가 영향을 받음, /../etc/password 입력으로 인수 옵션을 조작하여 경로 순회가 발생(로컬 네트워크 내에 공격이 이루어짐)

악의적인 사전 설정 구성을 업로드할 때 관리 페이지에 다시 출력하기 전에 구성 매개변수를 삭제하고 반환하지 않음 → Reflected Cross-Site Scripting 발생 가능성(공격자가 admin 계정으로 악성 구성 파일을 업로드 해야 함)

제품: DrayTek Vigor 2960 1.5.1.4 / Vigor 2960

생성 날짜: (Published/Updated) 2023-02-24

피해규모: 중간-낮음(NVD 참조)

참조: https://vuldb.com/?id.221742


NVD (National Vulnerability Database) (CVSS 포함)

https://nvd.nist.gov/

SCAP(Security Content Automation Protocol) 기반 표준 형태의 취약점 관리 용 미 정부 저장소

CVSS(Common Vulnerability Scoring System)으로 취약점 평가

* CVSS: 취약점 지표, 소프트웨어 취약점의 특성 및 피해 심각도를 표현하기 위한 개방형 프레임워크


1) CVE-2022-1009 - https://nvd.nist.gov/vuln/detail/CVE-2022-1009

설명/참조 동일(CVE)

심각성: 6.1(MEDIUM) - CVSS v3.0 Ratings / 4.3(MEDIUM) – CVSS v2.0 Ratings

 

2) CVE-2023-1009 - https://nvd.nist.gov/vuln/detail/CVE-2023-1009

설명/참조 동일(CVE)

심각성: 5.5(MEDIUM) - CVSS v3.0 Ratings / N/A – CVSS v2.0 Ratings


CWE (Common Weakness Enumeration)

https://cwe.mitre.org/

community-developed list of software and hardware weakness types

한 기관에서 개발한 것이 아님


1) CVE-2022-1009(CWE-79) - https://cwe.mitre.org/data/definitions/79.html

설명: 웹 페이지 생성 중 제어할 수 있는 입력을 무효화시킴(Cross-site Scripting)

세부 설명: XSS 취약점이 발생하는 경우 및 종류 설명

Reflected XSS (or Non-Persistent) Stored XSS (or Persistent) DOM-Based XSS

악용 가능성: High

 

2) CVE-2023-1009(CWE-22) - https://cwe.mitre.org/data/definitions/22.html

설명: 제한된 디렉토리에 대해 경로 이름을 부적절하게 제한함/순회(Path Traversal)

세부 설명: 파일 작업은 제한된 디렉토리 내에서 발생하도록 되어 있으며, “..” “/”과 같은 특수 구분 기호를 이용하여 공격자는 제한된 위치의 외부 경로로 이동하여 다른 위치의 파일 또는 디렉터리에 액세스할 수 있음

“../”: 현재 위치의 상위 디렉터리 상대경로 순회

“/usr/local/bin”: 파일 액세스 절대 경로 순회

악용 가능성: High

 

728x90
728x90
728x90
반응형
목차
1. 프리다(Frida)란?
2. 프리다의 주요 기능
3. 프리다 환경 구축
  - 녹스(Nox) 앱플레이어 설치
  - 아나콘다 파이썬 환경 구축
  - 프리다 설치 및 실행 

-
프리다(Frida) 주요 기능 이해
프리다 환경 구축
프리다 기능 살펴보기
프리다 기본 문법
프리다 CLI 활용
자바스크립트 파일 사용
파이썬 바인딩 이해
프리다 챌린지로 연습해보기
프리다 실무 활용

3. 프리다 환경 구축

아나콘다 파이썬 환경 구축

아나콘다(Anaconda)란?

파이썬을 포함한 데이터 과학에 필요한 다양한 언어 및 패키지의 배포

 

프리다는 파이썬 기반으로 동작, 파이썬 필수 설치

프리다는 파이썬 버전의 영향을 많이 받아 버전 관리 필요(2.x버전 → 3.x버전만 Frida 동작)

아나콘다라는 프로그램을 이용해 독립된 파이썬 실행환경 구축 가능(버전 변경 번거로움 없이 콘솔 창으로 전환 가능)

수학과 과학 분야의 라이브러리 포함됨(numpy, matplotlib, pandas 등 라이브러리 포함되어 데이터 과학/기계학습 쉽게 사용 가능)

 

아나콘다 설치

https://www.anaconda.com/products/distribution

Download 혹은 Download 하단 아이콘 클릭 - OS 환경에 맞는 Installer 설치(64-Bit Graphical Installer (786 MB)

Anaconda 설치 도중, Advanced Options - Add Anaconda to my PATH environment variable 체크 후 Install

Destination Folder: C:\Users\user\anaconda3

[참고] ConEmu 설치: color scheme default 설정값 <ConEmu>

cmd 창에서 'conda --version', 'python --version' 입력하여 버전 확인

# 독립된 가상 환경 설정: 이름 py3, 버전 3.10

conda create -n py3 python=3.7

Downloading and Extracting Packages

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate py3
#
# To deactivate an active environment, use
#
#     $ conda deactivate

activate py3 - 프롬프트 가장 앞에 (py3) 생성

python 2 version도 설치

conda create -n py2 python=2.7

py3 에서

pip install frida-tools

frida version은 16.0.11 / Android는 32bit


프리다 설치 및 실행

frida.re (상단바) DOCS > Tutorials - Android > releases page 이동 (https://github.com/frida/frida/releases)

- download the latest frida-server for Android from our releases page and uncompress it.

frida-server-16.0.11-android-x86.xz

압축 해제 후, 로컬 컴퓨터와 녹스와 통신 가능하도록 설정

권한 상승 후 백그라운드로 실행(& 연산자), 실행 프로세스 확인(4077)

New console dialog...

py3에서 안드로이드에서 실행 중인 프로세스 목록 나열(PID, Name)

-U: USB 장치 확인

frida-ps -U

 

728x90
728x90
728x90
반응형
목차
1. Mathworks 계정 생성 및 라이선스 설정
2. Polyspace 초기 화면 및 Code Prover 기본
3. 최대값 출력 프로그램 작성
  - 메모리 동적 할당
4. 프로그램 Code Prover 분석
  1) Non-initialized local variable
  2) Illegally dereferenced pointer
  3) Non-initialized variable


1. Mathworks 계정 생성 및 라이선스 설정

https://kr.mathworks.com 

 

MathWorks - MATLAB 및 Simulink 개발 회사

MathWorks Korea의 공식 홈페이지로서, MATLAB(매트랩) 및 Simulink(시뮬링크) 제품 및 서비스, 다운로드, 교육 및 강좌, 커뮤니티 등 다양한 정보를 제공합니다.

kr.mathworks.com

Mathworks 라이선스 설정

우측 상단 아이콘 - 내 계정 > 내 소프트웨어

다운로드 아이콘 클릭하여 R2023a 릴리스 버전 다운로드(계정 내 라이선스 필요)

R2023a 버전 installer 실행

대상 폴더: /Applications/Polyspace/R2023a

제품 선택: Polyspace Bug Finder + Polyspace Code Prover

필요 용량: 3.72 GB 정도


2. Polyspace 초기 화면 및 Code Prover 기본

terminal 연결하여, Polyspace 설정 경로로 이동 후, 실행

cd /Applications/Polyspace/R2023a/polyspace/bin
./polyspace &

실행 완료되면 하단 Polyspace R2023a 연결

Run-time Check 중

Red Check: 특정 에러가 100%로 발생하는 경우

Gray Check: Dead code, Unreachable code

Orange Check: 특정 에러에 대해 증명할 수 없는 경우

Green Check: 런타임 에러가 발생하지 않는 경우(정상)

Purple Category: Coding rules


3. 최대값 출력 프로그램 작성

arr 배열에 대한 초기값을 넣어주지 않아 에러 발생

// 초기 코드
#include <stdio.h>

int main(int argc, const char * argv[]) {
    int n, arr[n];
    
    printf("Enter full array size\n");
    scanf("%d", &n);
    
    printf("Enter values to store in the array\n");
    for (int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }
    
    int max = arr[0];
    for (int j = 1; j < n; j++) {
        if (max < arr[j])
            max = arr[j];
    }
    printf("The maximum value of an array element is %d\n", max);
    return 0;
}

arr 배열을 만들기만 하고 값을 넣어주지 않음 – 선언(Declare)의 상태

선언한 변수에 처음 값을 넣어 줌 – 초기화(Initialize)

초기화한 이후 변수에 값을 넣어 줌 – 할당(Allocaiton)

→ arr 배열 동적 할당 필요

메모리 동적 할당

컴퓨터 프로그램이 실행되는 런타임 도중 사용할 메모리 공간을 할당

동적 할당되는 메모리는 힙 영역에 생성

sizeof(int) 4byte 할당 * n

이후 동적 할당 메모리 해제(free)

// sol1
#include <stdlib.h>	// malloc, free 함수가 포함된 헤더 파일
#include <strings.h>	// memset 함수가 포함된 헤더 파일

int* arr = (int *)malloc(sizeof(int) * arr_size);
memset(arr, 0, sizeof(int) * arr_size);

free(arr);

malloc 할당 이후 memset 초기화하는 과정은 calloc 함수 하나로 대체 가능

// sol2
#include <stdlib.h>	// calloc 함수가 포함된 헤더 파일

int* arr = (int *)calloc(0, sizeof(int) * arr_size);

// 1차 수정
//
//  main.c
//  week.04_SecureCoding
//
//  Created by sehee on 2023/03/27.
//

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int max(int* ptr, int n);

int main(int argc, const char * argv[]) {
    // 최대값을 출력하는 프로그램, 배열은 동적 할당 받기
    int arr_size;
    
    // 첫번째 입력: 전체 배열 크기
    printf("Enter full array size\n");
    scanf("%d", &arr_size);
    int* arr = (int *)malloc(sizeof(int) * arr_size);
//    memset(arr, 0, sizeof(int) * arr_size);
    
    // error
    if (arr == NULL) {
        printf("malloc error");
        exit(1);
    }
    
    // 두번째 입력: 배열 내 저장할 함수 - 각 index에 해당 값 할당
    printf("Enter values to store in the array\n");
    for (int i = 0; i < arr_size; i++) {
        scanf("%d", &arr[i]);
    }
    
    // 출력: 최대값
    printf("The maximum value of an array element is %d\n", max(arr, arr_size));
    free(arr);
    return 0;
}

int max(int* ptr, int n) {
    int max_val = ptr[0];
    for (int i = 1; i < n; i++) {
        if (max_val < ptr[i]) {
            max_val = ptr[i];
        }
    }
    return max_val;
}

4. 프로그램 Code Prover 분석

1) Non-initialized local variable

초기 변수(arr_size) 선언 후 초기화

int arr_size = 0;

2) Illegally dereferenced pointer

3) Non-initialized variable

max 함수의 ptr에 대해 초기화하지 않음(의미X) - 변경X

// type1
int max(int* ptr, int n);
// type2
int max(int n[], int size);

// 최종 코드
//
//  main.c
//  week.04_SecureCoding
//
//  Created by sehee on 2023/03/27.
//

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int max(int n[], int size);

int main(int argc, const char * argv[]) {
    // 최대값을 출력하는 프로그램, 배열은 동적 할당 받기
    int arr_size = 0;
    
    // 첫번째 입력: 전체 배열 크기
    printf("Enter full array size\n");
    scanf("%d", &arr_size);
    int* arr = (int *)malloc(sizeof(int) * arr_size);
//    memset(arr, 0, sizeof(int) * arr_size);
    
    // error
    if (arr == NULL) {
        printf("malloc error");
        exit(1);
    }
    
    // 두번째 입력: 배열 내 저장할 함수 - 각 index에 해당 값 할당
    printf("Enter values to store in the array\n");
    for (int i = 0; i < arr_size; i++) {
        scanf("%d", &arr[i]);
    }
    
    // 출력: 최대값
    printf("The maximum value of an array element is %d\n", max(arr, arr_size));
    free(arr);
    return 0;
}

int max(int n[], int size) {
    int max_val = n[0];
    for (int i = 1; i < size; i++) {
        if (max_val < n[i]) {
            max_val = n[i];
        }
    }
    return max_val;
}

 

728x90
728x90
728x90
반응형
목차
1. 프리다(Frida)란?
2. 프리다의 주요 기능
3. 프리다 환경 구축
  - 녹스(Nox) 앱플레이어 설치

-
프리다(Frida) 주요 기능 이해
프리다 환경 구축
프리다 기능 살펴보기
프리다 기본 문법
프리다 CLI 활용
자바스크립트 파일 사용
파이썬 바인딩 이해
프리다 챌린지로 연습해보기
프리다 실무 활용

1. 프리다(Frida)란?

  • Ole가 개발한 DBI* 프레임워크
  • 프로세스를 모니터/디버깅하는 데 사용할 수 있는 툴킷
  • 다양한 플랫폼에서 프로세스에 대한 인젝션이 가능, 확장성이 큼
  • 자바스크립트를 Native App에 삽입 가능

* DBI: Dynamic Binary Instrumentation, 앱이 실행 중인 상태에서 코드 명령어를 삽입해 동적으로 바이너리 프로세스를 추적·분석·디버깅하는 도구


2. 프리다의 주요 기능

  • 프리다를 기반으로 사용하는 도구: AppMon*, Needle**
  • 함수 후킹(특정 함수에 연결하여 반환 값 변경 및 함수 재작성 가능)
  • 실행 중인 애플리케이션의 디버깅 수행 가능(실행 중인 함수를 추적하여 함수 재작성 가능 - 로그 출력, 내부 로직 변경 등)
  • 힙 메모리 내 객체 인스턴스 검색 및 사용 가능(프리다 기본 문법인 java.choose라는 함수를 사용하여 손쉽게 힙을 스캔)
  • 실시간 트래픽 스니핑 또는 암호 해독(암호화되기 전의 값을 변조)
  • 탈옥 또는 루팅되지 않은 단말기에서도 사용 가능(제한적이므로 추천하지 않음)

* AppMon: 앱의 시스템 API 호출을 모니터링하고 변경하는 자동화된 프레임워크(macOS, iOS, Android OS) - system 및 API 호출을 모니터링할 수 있음

* Needle: iOS 보안 테스팅 프레임워크(안드로이드의 드로저와 유사)


3. 프리다 환경 구축

필요 도구: 녹스 앱플레이어(Nox), 아나콘다(파이썬), 프리다, 프리다 서버(Android)

녹스(Nox) 앱플레이어 설치

무료 안드로이드 에뮬레이터, 실제 디바이스와 유사한 환경에서 진단이 가능하며, 멀티 앱 플레이어 기능으로 다수 앱 동시 진단 가능

안드로이드 애플리케이션 취약점 분석 및 악성코드 분석에 주로 사용됨

우측 상단의 시스템 설정

성능 > 해상도 설정: (기본) 1600x900 설정되어 있음, (변경) 960x540

성능 > 그래픽 모드: (기본) 호환+모드, (변경) 기본모드(DirectX)

일반 > 시작항목: ROOT켜기 체크 (안드로이드 실제 단말기에서 루팅한 것과 동일한 환경을 만들어주는 것)

인터페이스 > 선택적으로 설정

모든 설치가 완료되면 Nox ADB를 환경변수 설정함

ADB(Android Debug Bridge): 안드로이드를 위한 디버깅 툴, 안드로이드 애뮬레이터와 통신 가능

설정 위치: C:\Program Files (x86)\Nox\bin\nox_adb.exe

 

윈도우 '시스템 환경 변수 편집' 내 시스템 속성 - 고급 - 환경 변수 > 시스템 변수(Path) 설정 클릭 후 편집

 > 새로 만들기(N) 후 위의 설정 위치(bin 까지) 추가 후 설정

명령 프롬프트(cmd)에서 nox_adb 입력 시 해당 정보 출력되는 정보 확인(환경변수 설정이 잘 이루어짐)

연결된 nox_adb 쉘 접속

-s <specific device> - directs command to the device or emulator with the given serial number or qualifier. Overrides ANDROID_SERIAL environment variable.
nox_adb -s 127.0.0.1:62001 shell

 

728x90
728x90
728x90
반응형
목차
1. char 자료형
  - limits.h 헤더 파일

2. scanf 오류
3. int 자료형
4. 이진탐색(Binary Search) 시 발생하는 오버플로우 대안

char 자료형

C언어에서는 정수 자료형인 char를 이용하여 문자 한 개를 저장함

이 때, char 자료형의 표현 범위는 -128~127이며, char에 문자를 저장할 때는 문자 자체를 저장하는 것이 아니라 문자에 해당하는 정수 값을 저장(ASCII)

(00000000~1111111까지 256가지 중 127까지 양수, 128부터 음수로 표현)

따라서, char로 선언한 변수에 ASCII 코드값 128을 저장한다면, 이에 overflow가 발생하여 -128이 됨

#include <stdio.h>
#include <limits.h>

int main() {
    printf("char min: %d, char max: %d\n", CHAR_MIN, CHAR_MAX);
    // char min: -128, char max: 127
    return 0;
}


scanf 오류가 발생하는 이유

보안 문제, 프로젝트에서 SDL(Security Development Lifecycle) 자동 검사를 수행하기 때문

문제: 문자열이나 파일에 대한 버퍼나 스택 등 메모리에 문제가 생길 수 있음

해결 방법

1) 코드 최상단에 #define _CRT_SECURE_NO_WARNINGS 추가

  - scanf 보안 경고로 인한 컴파일 에러 방지

2) scanf → scanf_s로 변경(visual studio에서만 호환 가능)

  - 메모리의 사이즈를 요구하는 함수(_s), C언어 표준 함수는 아님

3) scanf_s("%s", sentence, sizeof(sentence))라 명시(마지막에 sentence 사이즈)

(e.g. scanf_s(“%d”, &store, 10); → [10]개의 사이즈를 받는다고 명시)

 

[참고]

sscanf()란? 입력 대상: 표준 입력(X), 매개변수로 전달되는 문자열 버퍼(O)

fscanf()란? 입력 대상: 파일(f) 스트림에서 포맷 스트링에 맞게 데이터를 읽어들임


int 자료형

int 자료형의 표현 범위는 -2147483648~2147483647이며,

2,147,483,628 = 2³¹

따라서 부호 있는 32bit 정수가 보유할 수 있는 최대값은 2³¹-1 (int 범위: -2³¹ ~  2³¹-1)

#include <stdio.h>
#include <limits.h>

int main() {
    printf("int min: %d, int max: %d\n", INT_MIN, INT_MAX);
    // int min: -2147483648, int max: 2147483647
    return 0;
}


이진탐색(Binary Search)  시 발생하는 오버플로우 대안

first = 0;
last = n - 1;
middle = (first + last)/2;

부호 있는 32bit 정수가 보유할 수 있는 최대값이 2³¹-1임

이 때, 검색할 요소가 2³¹-2 (마지막에서 두번째 요소)라고 가정해 보자

 

[0, 1, 2, 3, … , 2³¹/2, …, (2³¹-3), (2³¹-2), (2³¹-1)]

 

첫 번째 반복 시 middle = (0 + (2³¹-1))/2

target은 해당 배열의 우측에 위치하므로,

first = middle + 1 = (2³¹-1)/2 + 1 = 2³⁰ + 1/2

(*)두 번째 반복 시, middle = (first + last)/2 = {(2³⁰ + 1/2) + (2³¹ - 1)}/2 = {(2³⁰ + 2³¹ - 1/2}/2 = 2²⁹+2³⁰-1/4 = 2²⁹(1+2) – 1/4 = 2³⁰ + 2²⁹ – 1/4 (= 2²⁹ * 3 – 1/4)

이 때 first = 2²⁹ * 3 – 1/4 + 1 = 2²⁹ * 3 + 3/4

세 번째 반복 시, middle = (first + last)/2 = {(2²⁹ + 2³⁰ + 3/4) +(2³¹ - 1)}/2 = 2³⁰ + 2²⁹ + 2²⁸ - 1/8

 

해당 함수를 n 번 반복 시, n번 째 middle = (2³⁰ + 2²⁹ + 2²⁸ + … + 2^(30-n)) - 1/2^(n)

원하는 값(2³¹-2)을 구하기까지 middle은 최대 2³¹을 넘지 않으므로 문제되지 않음

(∵ (2³⁰ + 2²⁹ + 2²⁸ + … + 2¹) = 2³¹ - 1 < 2³¹)

 

하지만 두 번째 연산 시,(*) first와 last의 합이 INT_MAX인 2³¹ - 1을 넘어가게 되어 오버플로우 발생

➡️ middle이 음수가 됨

 

따라서, middle 값을 다음과 같이 변경하여 문제 해결 가능

문제: first와 last의 합이 2³¹을 초과하게 되어 overflow 발생

기존 연산: middle = (first + last)/2;

변경 연산1: middle = first + (last – first)/2;

변경 연산2: middle. = ((unsigned int)first + (unsigned int)last)) >> 1

 

* unsigned int는 sign(부호)가 없는 정수형으로,

Overflow된 값을 정상적인 값으로 판단하여 unsigned 연산에서 고의적으로 wrap around 이용

 

[참고자료]

The curious case of Binary Search - The famous bug that remained undetected for20 years

https://thebittheories.com/the-curious-case-of-binary-search-the-famous-bug-that-remained-undetected-for-20-years-973e89fc212

 

The curious case of Binary Search — The famous bug that remained undetected for 20 years

Nearly all Binary Search and Merge Sort implementations are broken!

thebittheories.com

 

728x90
728x90
728x90
반응형

 

 

10진 16진 문자 10진 16진 문자 10진 16진 문자 10진 16진 문자
0 0x00 NUL 32 0x20 Space 64 0x40 @ 96 0x60 `
1 0x01 SOH 33 0x21 ! 65 0x41 A 97 0x61 a
2 0x02 STX 34 0x22 " 66 0x42 B 98 0x62 b
3 0x03 ETX 35 0x23 # 67 0x43 C 99 0x63 c
4 0x04 EOT 36 0x24 $ 68 0x44 D 100 0x64 d
5 0x05 ENQ 37 0x25 % 69 0x45 E 101 0x65 e
6 0x06 ACK 38 0x26 & 70 0x46 F 102 0x66 f
7 0x07 BEL 39 0x27 ' 71 0x47 G 103 0x67 g
8 0x08 BS 40 0x28 ( 72 0x48 H 104 0x68 h
9 0x09 TAB 41 0x29 ) 73 0x49 I 105 0x69 i
10 0x0A LF 42 0x2A * 74 0x4A J 106 0x6A j
11 0x0B VT 43 0x2B + 75 0x4B K 107 0x6B k
12 0x0C FF 44 0x2C , 76 0x4C L 108 0x6C l
13 0x0D CR 45 0x2D - 77 0x4D M 109 0x6D m
14 0x0E SO 46 0x2E . 78 0x4E N 110 0x6E n
15 0x0F SI 47 0x2F / 79 0x4F O 111 0x6F o
16 0x10 DLE 48 0x30 0 80 0x50 P 112 0x70 p
17 0x11 DC1 49 0x31 1 81 0x51 Q 113 0x71 q
18 0x12 DC2 50 0x32 2 82 0x52 R 114 0x72 r
19 0x13 DC3 51 0x33 3 83 0x53 S 115 0x73 s
20 0x14 DC4 52 0x34 4 84 0x54 T 116 0x74 t
21 0x15 NAK 53 0x35 5 85 0x55 U 117 0x75 u
22 0x16 SYN 54 0x36 6 86 0x56 V 118 0x76 v
23 0x17 ETB 55 0x37 7 87 0x57 W 119 0x77 w
24 0x18 CAN 56 0x38 8 88 0x58 X 120 0x78 x
25 0x19 EM 57 0x39 9 89 0x59 Y 121 0x79 y
26 0x1A SUB 58 0x3A : 90 0x5A Z 122 0x7A z
27 0x1B ESC 59 0x3B ; 91 0x5B [ 123 0x7B {
28 0x1C FS 60 0x3C < 92 0x5C \ 124 0x7C |
29 0x1D GS 61 0x3D = 93 0x5D ] 125 0x7D }
30 0x1E RS 62 0x3E > 94 0x5E ^ 126 0x7E ~
31 0x1F US 63 0x3F ? 95 0x5F _ 127 0x7F DEL

 

728x90
728x90
728x90
반응형

단축키

h: hex와 decimal 변환

n: 변수명 변경

쉘 스크립트 > 코드 변경 > 함수 변경
> 함수 변경

c: Directly convert to code, sh(쉘 스크립트에 대해) 코드 변경(Data → Instruction)

p: 코드에 대해 함수로 변경(Instruction → Regular finction)

m: (pseudo code) enum 변경, (e.g. 숫자 → RESOURCEDISPLAYTYPE_FILE)

 

d: db dd dw 변환

db: define byte(바이트), 1byte의 메모리 할당

dd: define double-word, 4byte 메모리

dw: define word, 2byte 메모리

a: (db) 문자열로 변환

 

pseudo code의 좌측에 함수가 많이 없으면 패킹되었을 확률이 큼

메모리를 할당하면 쉘 코드(v47)를 올릴 확률이 큼

 

v47 = VirtualAlloc(IpAddress, 3 * v46, flAllocationType, 16 * v17

shellcode = (int (__stdcall *)(_DWORD, _DWORD))v47;

 

더미코드: ① 정의하고 쓰지 않는 것 ② 연산한 후 다른 값으로 덮어씌우는 것

__DWORD 포인터에 저장된 데이터를 

 

좌측 Function에 연두색 배경 표시되어 있다면, 클라우드에 미리 알려진 name으로 설정된 것

 

PE 헤더가 들어가는 부분(60, 120 - 0x3C, 0x78)

terminus project

윈도우 헤더 정보들을 정리해놓은 것

이것은 PE 헤더이므로 dos로 검색

 

 

 

728x90
728x90
728x90
반응형
목차
0. MIPS란?
1. 파일 구조 분석
2. 함수 정리
3. 명령어 정리
참고

0. MIPS란?

1) Million Instructions Per Second, 컴퓨터 분야에서 컴퓨터의 연산 속도를 나타내는 단위

2) Microprocessor without Interlocked Pipeline Stages, MIPS Technologies에서 개발한 RISC 기반의 명령어 집합 체계(컴퓨터 아키텍처)

* CISC: Complex Instruction Set Computer, 연산에 처리되는 복잡한 명령어들을 수백 개 이상 탑재하고 있는 프로세서

* RISC: Reduced Instruction Set Computer, 하나의 명령어 실행으로 간단한 프로세스들을 신속하게 수행

MIPS, ARM

마이크로 프로세서 세계에서 사용할 수 있는 두 가지 ISA (명령어 세트 아키텍처), 레지스터의 한 유형


1. 파일 구조 분석

32bit로 명령어 주소들이 4byte 단위로 떨어진다면 MIPS는 RISC 구조


2. 함수 정리

strcoll() 함수

아래 나열된 것과 같이 관계를 나타내는 값을 리턴함

예제 반환값
strcoll(const char *string1, const char *string2); string1이 string2보다 작음 0보다 작음
string1이 string2와 같음 0
string1이 string2보다 큼 0보다 큼

if ( !strcoll(*a2, "UDP") ) : ① a2가 참조하는 값과 UDP가 같으면 → ② if (!0) 이므로 참 → ③ 다음 if문 수행 (∵ if 0은 거짓)

값이 다르면 result로 a1 반환

atol() 함수

정수 문자로 구성한 문자열, 부호와 정수 문자들을 long 형식 값으로 변환하여 반환함


3. 명령어 정리

어셈블리어 예제 의미
NOP   아무 명령도 수행하지 않는 코드, 명령어 사이의 빈공간을 채워주는 역할
LA la $v0, 0x420000 Load Address, 레지스터 $v0에 0x420000가 가리키는 주소 load
ADDIU addiu A B C B + C의 값을 A에 삽입
BNEZ bnez R, L 레지스터 R이 0이 아니면 L로 점프
LW lw $s3 n($0) $0 주소에 n을 더해 주소가 0000000n인 곳의 데이터를 $s3에 삽입

 

$a1에 aCnc 값 삽입 (∵ $a1 = $v0 + (aCnc - 0x420000) = 0x420000 + (aCnc - 0x420000) = aCnc)

 

[MIPS Register]

$0 = Always 0

$at = The Assembler Temporary used by the assembler in expanding pseudo-ops.

$v0, $v1 = 리턴값 저장. 1 word 인 경우 $v0 만 사용. 초과할 경우 $v1 과 나눠서 저장

$a0-$a3 = 함수 인자값 저장. 초과할 경우 스택에 저장

$t0-$t9 = 임시 저장 레지스터

$s0 - $s7 = 저장 용 레지스터 – 함수 호출 중 불변

$k0, $k1 = 커널에서 사용하는 레지스터

$gp = 전역 포인터 레지스터

$sp = 스택 포인터

$fp = 함수 프레임 포인터 ($s8)

$ra = 서브루틴 호출 시 반환 주소 저장

 

[MIPS 주요 명령어]

addiu [addiu A B C] = [A <- B + C]

sw [sw A B] = [A ->B]

lw [lw A B] = [A <- B]

li(load immediate) [li A B] = [A <- B]

move [move A B] = [A <- B]

movn [movn A B C] = [if C != 0 then A <- B]

la [la A B] = [A <- B’s Addr]

lb [lb $a, (0)$s0] = $a 에 byte 단위로 데이터 로드

sb [sb $a, (100)$s0] = *($s0 + 100) 에 $a 저장

jal [jal A] - 다음 명령어의 주소를 $ra에 저장하고, A로 점프

bal [bal function] = function call = jalr

beq [beq A B L] = A와 B가 같으면 L로 점프

beqz [beqz R L] = R이 0이면 L로 점프

bne [bne A B L] = A와 B가 다르면 L로 점프

bnez [bnez R, L] = 레지스터 R이 0이 아니면 L로 점프

lui [lui A, 0x47] = A 레지스터 상위 2byte에 0x47 저장

0x90+var_73($fp) 와 같이 괄호가 있을 경우 $fp+(0x90+var_73) 와 같은 표현

slt [slt rd, rs, rt] = rd <= (rs < rt) ? 1 : 0

sll [sll $a, 1] = $a << 1

 

[MIPS 함수 호출 과정]

$ra 에 caller 의 return address 저장 (마지막 호출 함수의 경우 저장하지 않을 수 있음)

$a0 ~ $a3 에 인자값 저장 인자가 4개를 초과할 경우 초과한 만큼 스택에 저장

func(param1, param2, param3, param4) 일 경우 $a0 = param1, $a1 = param2, $a2 = param3, $a3 = param4 가 삽입

bal, jal, jalr 등 으로 함수 호출

return 값은 $v0 (4byte 초과시 $v1 에 나눠서 저장)

호출시 $ra 값 스택에 백업

$s0 ~ $s7도 필요한 경우 스택에 백업

$s8 레지스터와 $sp에 같은 값이 저장되어 있어서 $s8의 의미는 추가 파악이 필요

 

참고

[MIPS] MIPS 기본 내용 정리

IoT 환경을 위협하는 '리눅스 악성코드 Top 5'

 

 

728x90
728x90
728x90
반응형
목차
1. DHCP 개념
2. DHCP 원리
- Discover, Offer, Request, Ack 등
3. DHCP 기능
- 임대(Lease), 갱신(Renewal), 반환(Release)
4. DHCP relay agent
- gi-address
5. DHCP 취약점
- DHCP starvation, DHCP spoofing

DHCP(Dynamic Host Configuration Protocol)

같은 네트워크 대역(LAN)에서 IP를 관리해주는 서버

특정 사용자가 IP가 없을 때, DHCP 서버로부터 요청을 받으면,

몇 번 IP를 얼마 동안 사용하라고 DHCP가 해당 네트워크 서버에서 사용할 수 있는 IP를 빌려줌

같은 네트워크 대역에서 사용할 수 있는 IP 주소를 DHCP 서버가 관리하면, 사용자들이 필요할 때마다 가져가 쓰면 됨

 

DHCP 서버가 없으면 같은 네트워크 대역에서 똑같은 IP를 두 명이 사용하거나, 누가 어떤 IP를 사용하는지 모르니 충돌이 일어날 것

그래서 이러한 IP 주소를 관리하는 서버

- 공유기나 WiFi에 DHCP 서버가 있음

구분 설명
개념 동적 호스트 구성 프로토콜(네트워크 정보 할당)
목적 DHCP 사용 없이 정적(static) 설정해도 되지만, 여러 개의 클라이언트를 관리해야 할 경우, user가 IP를 변경하면 IP 충돌로 관리가 어려움
→ DHCP server를 이용해서 동적으로 제공, 서버에서 관리
원리

Discover 클라이언트가 DHCP 서버를 찾기 위한 패킷, Broadcast로 전송
LAN 상에 DHCP가 있는지 찾는 과정
Offer 서버가 Discover 패킷을 받았으면, 자신이 임대해줄 수 있는 네트워크 정보와 함께 자신의 IP 전달, Broadcast
Request DHCP 서버에서만 패킷 전달, Broadcast
Ack DHCP가 최종적으로 승인을 내리고 네트워크 정보 임대, Broadcast/Unicast
Release client에서 DHCP server에 Binding된 configuration parameter를 해제한다는 message - 네트워크 주소 반환
Nak DHCP server에서 client에게 요구한 시간이 경과했다는 message

기능

초기 설정

ipconfig /release

PC에 부여받은 IP가 0.0.0.0으로 변경(무선 LAN 어댑터 WiFi), 반환 과정과 동일

임대(Lease)

ipconfig /renew

IP를 받는 과정, iptime의 경우 기본적으로 7200초(2시간) 설정

(+ 유동 인구가 많은 카페에 임대 시간을 길게 설정하면 더 이상 제공할 주소가 사라지므로, 적절히 설정)

물리적 네트워크(172.30.1.254) - Vmware 내부 네트워크(192.168.65.1)

갱신(Renewal)

IP 임대 시간 갱신

IP를 임대받은 클라이언트가 계속 사용중이어서 DORA의 과정을 거치면 불필요한 트래픽 발생

(갱신 시도 2회)

1) 임대시간 50% 경과 시, 갱신 시도 → 성공: 설정 임대시간만큼 추가 할당 / 실패: 갱신 보류

2) 임대시간 87.5% 경과 시, 두번째 갱신 시도 → ① 성공: 설정 임대시간만큼 추가 할당 / ② 실패: 갱신 종료

- 전반적인 과정: Unicast 통신 시도(이미 DORA 과정에서 DHCP의 IP를 알아왔으므로), 갱신이 2번 모두 실패할 경우 반환 과정을 거침

ipconfig /all

iptime(192.168.0.1) 고급 설정> 네트워크 관리 > DHCP 서버 설정

KT(172.30.1.254:8899) 장치설정 > 네트워크 관리 > LAN 연결 설정

DHCP 갱신

반환(Release)

ipconfig /release

DHCP에게 할당 받았던 IP 반환(갱신 과정 실패 시)

임대 시간이 모두 지났는데 Client와 DHCP server끼리 통신이 되지 않는 경우, DHCP는 반환받은 것으로 처리


DHCP relay agent

일반적으로 DHCP 메시지는 Broadcasting 되기 때문에 단말과 DHCP 서버는 반드시 동일 서브넷 상에 위치해야 함

(라우터가 브로드캐스트 패킷을 다른 인터페이스로 전달(IP Forwarding)하지 않기 때문)

단말이 송신한 DHCP 메시지(브로드캐스트 패킷)가 라우터를 통해 다른 서브넷에 위치한 DHCP 서버로 전달될 수 없음

그러나, DHCP 서버가 각 subnet(LAN) 마다 위치하는 것은 실제 통신 사업자망의 구성에 실용적이지 못함

→ DHCP Relay Agent 기능으로, 단말이 송신하는 DHCP Broadcast packet을 Unicast로 변환하여 DHCP 서버에 전달(L2 Switch)

구분   설명
Discover
기본 클라이언트가 DHCP 서버를 찾기 위한 패킷, Broadcast로 전송
LAN 상에 DHCP가 있는지 찾는 과정
변환 단말이 브로드캐스트 메시지를 보내면, DHCP Relay Agent가 수신하여 유니캐스트로 변환
(SIP=DHCP Relay Agent, DIP=DHCP Server) → DHCP 서버로 전달
Offer
기본 서버가 Discover 패킷을 받았으면, 자신이 임대해줄 수 있는 네트워크 정보와 함께 자신의 IP 전달, Broadcast
변환 DHCP 서버가 DHCP Relay Agent로 유니캐스트를 보내면,
이를 수신한 DHCP Relay Agent는 브로드캐스트로 변환해서 단말로 전송
Request
기본 DHCP 서버에서만 패킷 전달, Broadcast
변환 단말이 브로드캐스트 메시지를 보내면 DHCP Relay Agent가 수신해서 유니캐스트로 변환
(SIP=DHCP Relay Agent, DIP=DHCP Server) → DHCP 서버로 전달
Ack
기본 DHCP가 최종적으로 승인을 내리고 네트워크 정보 임대, Broadcast/Unicast
변환 DHCP 서버가 DHCP Relay Agent로 유니캐스트를 보내면,
이를 수신한 DHCP Relay Agent는 브로드캐스트로 변환해서 단말로 전송

* Request Broadcast 이유: 모든 DHCP 서버들이 DHCP Offer 메시지를 보내면서 해당 단말에 할당해 줄 IP 주소와 기타 정보를 내부적으로 저장해 놓기 때문, 선택받지 못한 DHCP 서버들이 이 IP 주소와 기타 정보들을 삭제할 수 있도록 하기 위함

# apt-get install isc-dhcp-server
# vi /etc/dhcp/dhcpd.conf

# 해당 옵션 추가(network range)
subnet 192.168.0.0 netmask 255.255.255.0 {
    range 192.168.0.10 192.168.0.20;
}
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.10 192.168.1.20;
}
# systemctl restart isc-dhcp-server
# ps -ef | grep dhcrelay

# apt-get install isc-dhcp-relay

# vi /etc/default/isc-dhcp-relay
SERVERS="192.168.0.1"
INTERFACES="eth0 eth1"

SERVERS: relay할 서버 설정, 여러개의 DHCP 서버로 relay 가능(space-seperated)

INTERFACES: relay service를 할 interface 설정, DHCP와 통신할 interface도 추가해야 하므로 2개 설정

# systemctl restart isc-dhcp-relay
# ps -ef | grep dhcrelay

gi-address

DHCP 패킷 테이블에 나열된 필드 중 하나

라우터 IP 주소, DHCP/BootP 릴레이 에이전트에 의해 채워지는 게이트웨이 IP 주소

DHCP server가 메시지에 대한 reply 패킷을 송신할 때, destination address를 'giaddr'로 사용

DHCP server가 DHCP Relay Agent로부터 DHCP 메시지를 수신하면, 메시지에 대한 reply를 giaddr(Gateway IP Address)로 보냄

 

부가 설명

Relay Agent가 request를 relay하기로 정했으면, 반드시 'giaddr' 필드를 검사해야 함

만약 'giaddr' 필드가 '0'이면, Relay Agent는 request를 'giaddr' 필드를 request를 수신한 인터페이스의 IP 주소로 채워야 함

즉, 'giaddr' 필드는 dhcrelay 데몬의 To client 인터페이스의 IP 주소가 됨

DHCP Server는 'giaddr'로 DHCP reply 패킷을 송신 DHCP Server가 DHCP 메시지를 수신하지만, DHCP Relay Agent로 reply 패킷이 도달하지 않는다면 DA가 'giaddr'인 패킷을 수신할 수 있도록 네트워크를 변경해야 함

 

게이트웨이 주소(gi addr)에서 DHCP

DHCP: IP 주소 관리의 효율성과 편의를 위한 프로토콜

DHCP는 네트워크 내 개별 호스트 TCP/IP 통신을 실행하기 위한 IP 주소를 자동으로 할당(+ 구성 정보, ...)

단점: 서버와 클라이언트간 상호 인증 체계가 없음

-> DHCP spoofing, release 공격과 같은 네트워크 공격에 취약


취약점

DHCP Starvation

dhcpx -vv -i eth1 -A -D 10.10.10.50 -t 1
(축약) dhcpx -i eth1 -D 10.10.10.50
(eth1: 공격 보낼 network interface), 10.x.x.x: 공격 대상(DHCP 서버))

(DHCP pool 고갈 = IP 고갈)

대응

1) port security(switch 기술)(Client-Switch 사이)

특정 LAN 포트에서 허용할 MAC Address 지정(개수 포함)

발견 시 ① Protect(blocking) ② Restrict (blocking + trap message 관리자 전송) ③ Shutdown (위반 시 포트 차단 - 관리자 no shut 해제)

2) trusted port(DHCP Server-Switch 사이)

다른 포트에서 들어오는 DHCP 패킷이 감지되면, 패킷 버림 (물리적인 포트)

 

DHCP Spoofing

ettercap -i eth1 -T -M dhcp: 10.10.10.60 -150 / 255.255.255.0 / 10.10.10.50
(ettercap: LAN에 대한 메시지 가로채기 공격을 위한 보안 도구
IP 순서대로 (할당할 IP 대역 / 서브넷 마스크 / DNS Server)

참고: kali linux → dhcp server spoofing & starving attack

DHCP server의 취약점 판단하여 공격자가 DHCP 서버가 되어, 패킷 스푸핑

(DHCP 서버가 Default GW, DNS Server까지 할당 가능 → 공격자가 만든 서버 참조


참고 자료

유권정, 김은기, 네트워크 공격 방지를 지원하는 DHCP의 설계 및 구현에 관한 연구, 한국정보통신학회논문지

DHCP Packet 분석

DHCP 성능 테스트

DHCP Relay Agent 이용

 

 

728x90
728x90
728x90
반응형
목차
0. AutoHotkey1 파일 실행
1. 오토핫키 이해
2. OllyDbg 디버깅
3. 오토핫키 스크립트 사용법
4. 오토핫키 취약점

[Review] (6주차) 실습

2022.08.24 - [Security & Analysis/IDA Pro] - [IDA Pro] chap.06 악성코드 정적분석 툴 사용법(Ransomware, reversing.kr)

 

[IDA Pro] chap.06 악성코드 정적분석 툴 사용법(Ransomware, reversing.kr)

목차 0. Ransomware 파일 내부 1) file 정보 2) readme.txt 파일 3) run.exe 파일 1. run.exe 파일 실행 1) Exeinfo.exe 설치 2) HxD 설치 3) UPX 설치 4) OllyDbg 설치 5) WOW64 설치 2. IDA run.exe 파일 분석 3..

sarahee.tistory.com


0. AutoHotkey1 파일 실행

readme.txt 파일 확인

Decrypt, EXE Key는 md5 값이며, 해당 md5를 복호화하여 인증키 획득 가능

문제에서 요구하는 key 값: decrypt, exe

AutoHotKey는 해당 언어로 된 소스코드를 exe로 컴파일할 때 비밀번호 지정(무분별한 디컴파일 방지를 위해)

→ DecryptKey: 디컴파일 시 필요한 비밀번호, 바이너리가 실행될 때 메모리 상에서 평문 형태로 존재

→ EXE's Key: 디컴파일된 소스코드 내 사용자에게 요구하는 값, 소스코드에서 확인 가능


1. 오토핫키(AutoHotkey) 이해

  • 윈도우 응용 프로그램 및 매크로를 만드는 오픈 소스 자유 소프트웨어이자 스크립트 언어
  • 사용자가 반복작업을 자동으로 할 수 있도록 도와줌, 간략하게 매크로 프로그램이라고 이해

참고. 접근성

// C Language
#include <stdio.h>
int main(void) {
	print("Hello world!");
    return 0;
}

// AutoHotKey
Msgbox, Hello world!

다운로드

https://www.autohotkey.com/

스크립트 확장자는 .ahk이고, 설치하면 Compiler 폴더의 Ahk2Exe를 사용하여 ahk를 exe로 컴파일 가능

→ AutoHotKey 프로그램에 비밀번호를 설정한 후, 입력 값 일치하면 프로그램을 실행할 수 있도록 하는 기능

따라서 ahk.exe 파일에 입력해야 하는 비밀번호가 decript's key가 됨

  • Exe2Aut.exe 디컴파일러
  • ank의 password: decript's key

ahk.exe 파일 확인

입력 창에 임의의 문자를 입력한 후, OK 버튼을 누르면 프로그램이 종료

패킹된 파일을 그대로 디버거로 로드하면, 함수나 문자열 등 제대로 확인하기 어려움

파일을 제대로 분석하기 위해서는, 디버깅 상태에서 다음과 같은 명령어를 확인해야 함

  • F2: 브레이크 포인트 설정
  • F7: 디버깅 중 프로그램을 한 줄 실행시킴
  • F8: 디버깅 중 프로그램을 한 줄 실행시킴(call 명령어가 있을 경우에는 해당 함수로 들어가지 않음)

exeinfope.exe로 파일 구조 파악

UPX(Ultimate Packer for eXecutables): 여러 운영체제에서 수많은 파일 포맷을 지원하는 오픈 소스 실행 파일 압축 프로그램

exe 파일이 압축되어 있어서 내부 구조 확인하기 어려움

(패킹: -o, 언패킹: -d 옵션)

다시 exe 파일 실행 시 출력 화면이 다음과 같이 변경

exe 파일 손상 등의 사유로 열 수 없음

파일 검증하는 CRC 체크 부분에서, 위와 같은 EXE corrupted 문구 출력

컴파일 후 변조가 되면 해당 문자열 출력

HS_EXEArc_Read::Open 함수에서 체크하여, 이후 어떤 분기문으로 이동할 지 스크립트를 실행시킴

→ UPX 언패킹한 바이너리 분석 시 CRC 체크 영역에 걸려서 에러

오토핫키 프로그램은 컴파일 시 자동으로 UPX 패커를 적용시키기 때문에 언패킹을 한 이후 분석을 하면 DecryptKey를 찾을 수 없음(디컴파일 시 필요한 비밀번호이므로)

+ 알고리즘을 숨기고 복원하는 과정에서 힌트를 얻고 디컴파일을 수행할 수 있겠지만, 해당 프로그램 특성 상 언패킹 시 분기문에서 탈락하도록 설정했으므로 의미 없음

하단의 >AUTOHOTKEY SCRIPT< , >AHK WITH ICON<

특정 함수의 반환값을 조건으로 "EXE corrupted" 메시지 박스를 띄우고 종료하는 분기

">AUTOHOTKEY  SCRIPT<" 문자열을 사용하는 함수를 호출하는 분기


2. OllyDbg 디버깅

OllyDbg: 바이너리 코드 분석을 위한 x86 디버거(소스 코드가 없을 때 주로 사용)

- 레지스터 추적, 함수/API 호출, 문자열 인식, 오브젝트 파일과 라이브러리 내 루틴 위치 검색

 

바로 Debug Run할 경우, (or F9 단축키)

Options > Debugging options (or) Alt + O > Events 버튼 클릭하여 Make first pause at: Entry point of main module 체크

* 제어가 운영 체제에서 컴퓨터 프로그램으로 이동하는 것 → 패킹된 파일의 실제 프로그램 시작 부분

OllyDbg 활용 OEP 확인

OEP란? unpacking에서 가장 중요한 부분(Original Entry Point)

packing되기 전으로 돌아간 곳, 덤프를 통해 packing 해제된 파일을 만듦

UPX로 압축하면 PUSHAD와 POPAD 어셈블리어는 필수적으로 생성

PUSHAD 실행 이후 맨 위의 스택 주소를 덤프하여 BYTE H/W BreakPoint를 지정하고 실행해서 POPAD 다음에서 멈추도록 함

JMP 명령어를 통해 OEP로 이동

* 스택에서 레지스터들이 POP이 되는 순간을 캐치하면 OEP로 진입할 수 있는 힌트를 찾아낼 수 있을 것

Entry point breakpoint

PUSHAD로 시작하는 첫번째 instruction 조회

PUSHAD 명령어: EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI 모든 레지스터를 stack에 PUSH하는 역할

일반적인 packer는 특정 위치의 레지스터들의 백업을 만들어 놓기 위해 처음에 PUSH 명령을 이용하여 저장

(∵ 패킹된 파일이 루프를 돌면서 연산을 하게 됨, 기존 레지스터가 수정될 수 있기 때문에 저장, 루틴이 모두 끝나고 정상 코드를 실행시킬 때 이 레지스터들을 돌려 받기 위함)

→ 파일 메인 프로그램이 실행되기 전에 POP instruction으로 레지스터를 복귀

(참고) System breakpoint 설정했을 경우

  • 2사분면(Code Window) 왼쪽: 주소 창(명령어가 실행되는 주소)
  • 2사분면(Code Window) 가운데: 기계어(OP 코드 창)
  • 2사분면(Code Window) 오른쪽: 어셈블리어(디스어셈블리 창)
  • 1사분면(Register Window): 레지스터 값 표시
  • 3사분면(Dump Window): 메모리 덤프 창 - 특정 시점에 작업 중이던 메모리 상태(주소, Hex dump, hex to ASCII 해석 내용) 기록
  • 4사분면(Stack Window): 스택 주소 값, comment 순으로 출력

PUSHAD 위아래 추가 설명

POPAD 명령어 실행 전 루프문들이, 압축된 코드를 해제하는 과정

Dump Window의 Ctrl+G > (Enter expression to follow in Dump:) ESP 입력 후 확인

* 스택 프레임의 끝지점 주소가 저장되는 최상단 구간(ESP)

Hex dump 부분 우클릭 > Breakpoint > Hardware, on access > Byte

다시 Run하면 하드웨어 브레이트 특성 상 Breakpoint 설정 명령어 이후 제어가 멈추므로 0x00471BCC에서 Paused됨

아래로 스크롤하다 보면 거의 마지막 코드에 POPAD

JMP 명령어 뒤에 오는 주소가 OEP임(ahk.00442B4F)

해당 주소로 점프(Ctrl+G)하여 조회

Ctrl+A: 코드 분석(다시 읽기)

Ctrl+F: POPAD 찾기

Compressed code?
Quick statistical test of module 'ahk' reports that its code section is either compressed, encrypted, or contains large amount of embedded data. Results of code analysis can be very unreliable or simply wrong. Do you want to continue analysis?

 

AutoHotKey의 패킹된 바이너리를 실행해서 OEP까지 간 다음 CRC 체크를 통해 에러가 발생했을 때 출력되는 문자열 영역을 기준으로,

바로 위에 있는 CRC 체크 함수 내부를 분석

hash 처리된 값 하나가 EBX에 추가됨

 

publicKeyToken="6595b64144ccf1df"

 

Exe's key = 54593f6b9413fc4ff2b4dec2da337806

decrypt key = 220226394582d7117410e3c021748c2a

 

MD5로 decrypt 수행

https://www.md5online.org/md5-decrypt.html

 

→ pawn isolated


3. 오토핫키 스크립트 사용법

오토핫키 스크립트는 오토핫키 소스코드가 보관되어 있는 곳

프로그램이 실행될 때 스크립트를 열어서 소스코드를 확인하면서 돌아가는 것

 

바탕화면 우클릭하여 새로 만들기(W) > AutoHotKey Script

새 script 생성(이름 바꾸기)

우클릭 > 더 많은 옵션 표시 or Shift+F10 단축키 클릭하여 Edit Script

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

본래 내용을 지우고 다음과 같이, F1버튼을 눌렀을 때 hello라는 메시지 창이 나오도록 코드 작성

이후 저장하고 창 닫기

  • .ahk 파일 우클릭하여 Compile Script 하면 .exe 파일이 생성
  • .exe 파일을 관리자 권한으로 실행하여 하단 바에 AutoHotKey icon 생성

F1 단축키 클릭 시 다음과 같은 화면 출력


4. 오토핫키 취약점

CVE-2020-18174 취약점

AutoHotkey 1.1.32.00의 setup.exe에 있는 프로세스 주입 취약점으로 인해 공격자가 권한을 상승시킬 수 있음

reversing.kr에서 다운로드 받은 파일 버전: 1.0.48.5

 

 

728x90
728x90
728x90
반응형
목차
1. APK 추출하기
2. JAR 변환하기
3. JAR 디컴파일
-
1. dex2jar download
  - apk/dex to jar
2. mapping download
  - proguard reverse
3. JD-GUI download
  - 소스코드 조회
4. AXMLPrinter2.jar download
  - packageinfo(for AndroidManifest.xml)
5. apktool download

개발자가 구현한 JAVA 코드 및 라이브러리가 APK 파일로 컴파일됨

안드로이드 가상머신에서 실행되는 DEX "classes.dex"로 저장됨

DEX를 직접 디컴파일하는 것보다, JAVA 디컴파일러로 열어보기 위해 JAR로 변환하는 작업을 진행할 것

APK(DEX)를 JAR로 변환하기 위해 DEX2JAR 사용

1. dex2jar download

https://github.com/pxb1988/dex2jar

 

다운로드 이후, 명령 프롬프트의 해당 동일 경로에 apk 파일 위치시키고, 코드 입력하여 확장자 변경

// - Linux: APK/DEX를 JAR로 변환
dex2jar -f -o app.jar app.apk
dex2jar -f -o app.jar app.dex

// - Windows
d2j-dex2jar.bat app.apk
d2j-dex2jar.bat app.dex

* DEX란? Dalvik Executable, 안드로이드의 실행 파일(윈도우 실행파일: PE)

다음과 같이 jar 파일 생성되는 것을 확인


2. mapping download

mapping.jar
0.67MB

명령 프롬프트에 아래와 같이 입력 후, 

java -jar mapping.jar​

Mapping Utility에

Load Jar: 언패킹할 jar 파일(e.g. app-dex2jar.jar)

Load Mappings: mapping.jar 파일 입력 후

Proguard Reverse 버튼 누르면,

다음과 같이 app-dex2jar.jar.correlated.jar 파일 생성

이후 jd-gui 프로그램 사용하여 소스코드 확인


3. JD-GUI download

http://java-decompiler.github.io/

jd-gui-windows-1.6.6.Zip
1.30MB

dex2jar를 사용하기 위해서는 apk 파일 또는 apk 내부 classes.dex 파일을 인자값으로 전달하면 됨

exe 파일 실행하여 jar 파일 open

해당 앱은 proguard로 난독화를 수행하지 않았는지.. mapping 이전과 이후 코드가 동일하게 나타남


4. AXMLPrinter2.jar download

AXMLPrinter2.jar
0.02MB

apk 파일 내에 있는 AndroidManifest.xml 파일을 가져와서, AXMLPrinter2.jar 파일 동일 경로에 위치

이후 다음 명령어 입력

(apkinfo.txt: 패키지 파일 내부를 확인할 수 있는 텍스트 파일 형식으로, 파일명은 임의로 지정)

java -jar AXMLPrinter2.jar AndroidManifest.xml > apkinfo.txt

다음과 같이 apkinfo.txt 파일이 생성되며, 패키지명 등 확인 가능


5. apktool download

https://ibotpeaches.github.io/Apktool/

apktool_2.6.1.jar
19.06MB

java -jar apktool_2.6.1.jar d app.apk

 

 

728x90
728x90

+ Recent posts