리버싱 1차시

이동규·2026년 5월 23일

Layer7과제

목록 보기
7/22

리버스 엔지니어링

역공학, 역설계
만들어진 장치가 어떻게 작동하는지 분석을 통해 원리를 이해하는 과정


컴파일 과정

소스코드 -> 실행파일

전처리기: 전처리

컴파일러: 어셈블리로 바꿈

어셈블러: 어셈블리를 목적파일

링커: 라이브러리와 목적파일을 병합한다


어셈블리어

기계어와 1대1 대응된다 저급함

mov rax,17

rax 에 17을 대입

기계어

64비트기준

어셈블리: MOV RAX, 116진수
기계어: 48 C7 C0 01 00 00 00
(몇비트 연산인지 접두어) (명령) (레지스터) (숫자)

  • 수는 리틀엔디안으로 표현

레지스터

초고속 저장공간
메모리에서 값을 가져와 사용한다
https://www.youtube.com/watch?v=5SICv-2tMgQ&t=1s

범용 레지스터

  • rax : 함수 반환값 설정
  • rbx : 목적이 딱히 없음
  • rcx : 반복문 할때 반복횟수
  • rdx : 임시공간
  • rbp : (베이스 포인터)스택 최상위 주소
  • rdi : 연산시 목적지
    syscall시 파일 디스크립터 1이면 터미널에 출력 0이면 파일로 저장같은
  • rsi : 이것도 걍 임시공간 느낌으로 사용하면됨
  • rsp : 스택 최하위 주소
  • rip : 현재 실행중인 코드

FLAG 레지스터

수행한 연산 결과를 기록한다

  • Zero Flag : 연산 결과가 0이면 1로 설정
  • Sign Flag : 연산 결과가 음수면 1
  • Carry Flag : 빌림/올림 발생시 1
  • Overflow Flag : 오버플로우시 1

Opcode

http://ref.x86asm.net/coder64.html

데이터 이동

  • mov : 첫 피연산자에 두번째 피연산자값 복사
  • lea : 첫 피연산자에 두번째 피연산자의 주소 복사
  • push : 스택에서 피연산자값 복사
  • pop : 스택에서 꺼낸갑 rax에 저장

산술 및 논리 연산

  • add : 첫 피연산자에 두번째 피연산자 더하기
  • sub : 첫 피연산자에서 두번째 피연산자 빼기
  • imul : 첫번째에 두번째 * 세번째 저장
  • idiv : rbx:rax / rbx
    몫 rax, 나머지 rdx 저장

비교 및 흐름제어

  • cmp : 첫 피연산자에서 두번째 피연산자를 뺀 것으로 플래그 설정
  • jmp : 주소로 jump
  • jz/je : 연산 결과가 0이면 주소로 이동
  • jne/jnz : 연산 결과 0이 아니면 주소로 이동
  • jg : 연산 결과 0초과시 주소로 이동
  • jge : 연산 결과 0이상이면 주소로 이동
  • jl : 연산 결과 0미만이면 해당주소로 이동
  • jle : 연산 결과 0이하이면 해당주소로 이동

System Call

프로그램이 커널에 자원을 요청하는 행위

어셈블리에서

레지스터에 인자를 저장한 후 호출한다

  • rax : 호출할 기능
  • rdi : 파라미터 1
  • rsi : 2
  • rdx : 3

계산기

section .data
    a dq (계산할 숫자) ;저장받을 공간
    b dq (계산할 숫자)

section .text
    global _start

_start:
    mov r8, [a] ; 더하는거
    add r8, [b]
    mov rdi, r8
    call print

    mov r8, [a] ;빼는거
    sub r8, [b]
    mov rdi, r8
    call print

    mov r8, [a] ;곱
    imul r8, [b]
    mov rdi, r8
    call print

    mov rax, [a] ;나눗셈
    cqo ;나눌때 쓰레기값 안나오게 128비트로 확장
    idiv qword [b]
    mov r8, rax
    mov rdi, r8
    call print

    mov rax, 60 ;종료
    xor rdi, rdi
    syscall

print:
    sub rsp, 32 ;버퍼 만듦

    mov rax, rdi
    lea rsi, [rsp + 31]
    mov byte [rsi], 10
    mov rcx, 1

    mov rbx, 10

.convert:
    xor rdx, rdx ;자릿수 하나하나 문자로 바꿔서 버펀에 넣는다
    div rbx

    add dl, '0'
    dec rsi
    mov [rsi], dl
    inc rcx

    cmp rax, 0
    jne .convert

    mov rax, 1 ;출력
    mov rdi, 1
    mov rdx, rcx
    syscall     ; write(1, rsi, rcx)

    add rsp, 32 ;버퍼 정리정돈
    ret ;돌아가

rev-basic-0

문제 풀이를 완료하고 클래스룸을 확인하니 풀이가 아니라 코드 해석 정리라는 것을 깨달았습니다.
아쉬운 대로 둘 다 때려 넣었습니다.
빈약한 내용 정리 죄송합니다.


; int __fastcall main(int argc, const char **argv, const char **envp)
main proc near

var_118= byte ptr -118h
var_18= qword ptr -18h

; __unwind { // __GSHandlerCheck
push    rdi ;스택 공간확보
sub     rsp, 130h
mov     rax, cs:__security_cookie ;오버플로우 막는거라함
xor     rax, rsp
mov     [rsp+138h+var_18], rax
lea     rax, [rsp+138h+var_118] ;0으로 초기화
mov     rdi, rax
xor     eax, eax
mov     ecx, 100h
rep stosb
lea     rcx, aInput     ; "Input : " ;Input : 출력
call    sub_140001190
lea     rdx, [rsp+138h+var_118] ;입력받음
lea     rcx, a256s      ; "%256s"
call    sub_1400011F0
lea     rcx, [rsp+138h+var_118] ;확인함
call    sub_140001000
test    eax, eax
jz      short loc_140001166

맞으면 Correct 틀리면 wrong을 출력하나 보다

call    sub_140001000

이 부분을 주목하자
뭔가 비교하는 함수를 호출하는 것 같다
함수를 확인해보자


lea     rdx, Str2       ; "([DH]에 의해 제거됨)"

hmmm...


.rdata:0000000140002220 Str2            db '([DH]에 의해 제거됨)',0

hmm...



0개의 댓글