-
Notifications
You must be signed in to change notification settings - Fork 0
Reversing
Yeong-won Seo edited this page May 28, 2024
·
4 revisions
yay -S ida-freediscord에 올라온 샘플을 분석해보자
int a;
while (true)
{
int b;
}
int c;이 세 변수는 메모리에 어떻게 저장될까?
선형적으로 4바이트씩 할당되어도 좋겠지만, 그랬다가는 가운데의 int b가 무한정 할당될것만 같아 두렵다.
이를 해결하기위해 메모리 스코프와 스택의 개념을 도입하자.
구조적 프로그래밍을 도입하며, 변수를 효과적으로 관리하기 위한 수단으로 메모리 스코프가 등장했다.
C언어 이전 옛 언어들의 문법에는 다음과 같은 구조가 드러난다:
BEGIN
{ do stuff... }
END위의 BEGIN과 END로 구성된 쌍은 절 내부의 것들이 절 외부에서 참조되지 못하도록 역할하는데, 같은 역할을 구현하기위해 C언어에는 중괄호가 도입되었다.
int a;
{
int c;
}
int b;중괄호 절 외부에서 중괄호 내부에 접근하지 못하기 때문에, int c는 중괄호 절을 벗어났을때, 할당이 해제되는 것이 효율적일 것이다.
또한 중괄호를 사용함으로서 스코프가 열리고 닫히는 구조가 스택의 형태를 띄기 때문에, 이러한 할당을 스택을 통해 관리하면 좋을 것이다.
따라서, C언어에서 (또한 수많은 현대 언어들에서) 변수에 대한 메모리 할당은 다음과 같이 일어난다:
- 최외각 스코프의
int a, b가 처음 스택에 push된다. -
int c가 포함된 스코프에 진입했을때, 스택에int c를 push한다. - 스코프를 벗어나면, 스택에서 pop한다.
int a = 0xDEADBEEF;
{
int c = 0xDEADCAFE;
}
int b = 0xDEADC0DE;따라서, 위의 코드에 따르면 스택은 다음과 같이 변화한다.
- 1
0 | DEADBEEF
4 | DEADC0DE
- 2
0 | DEADBEEF
4 | DEADC0DE
8 | DEADCAFE
- 3
0 | DEADBEEF
4 | DEADC0DE
메모리 스코프의 구현, 스택 계산기등을 생각해보면 스택 방식의 언어를 설계한것은 매우 타당해보인다.
그렇다면, 함수의 호출 또한 스택 방식으로 설명해볼 수 있을까?
https://en.wikipedia.org/wiki/Calling_convention
- 이 프로그램이 어떤 일을 수행하는지 분석하고 문서화하기
- 메모리 할당과 해제를 분석하고 문서화하기
- 컴파일된 바이너리를 분석하고 2번의 결과와 비교하여 문서화
- 컴파일러 안쓰고 직접 어셈블리로 바꿔보기
할 수 있는 한 높은 단계에 도전해보자!
#include <stdio.h>
int main(void)
{
while (1)
{
int x = 0;
int y = 1;
do
{
printf("%d\n", x);
int z = x + y;
x = y;
y = z;
} while (x < 255);
}
}$ yay -S nasm section .data
hello: db 'Hello, World!', 10
section .text
global _start
_start: mov eax, 4 ; 'write' syscall
mov ebx, 1
mov ecx, hello
mov edx, 14
int 80h
mov eax, 1 ; 'exit' syscall
mov ebx, 0
int 80h$ nasm -f elf64 hello.asm -o hello.o
$ ld hello.o -o hello
$ ./hello
Hello, World! section .data
hello: db 'Hello, World!', 10
section .text
global _start
_start: mov eax, 4 ; 'write' syscall
mov ebx, 1
mov ecx, hello
mov edx, 14
int 80h
jmp _start$ nasm -f elf64 hello.asm -o hello.o
$ ld hello.o -o hello
$ ./hello
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
... section .data
hello: db 'Hello, World!', 10
section .text
global _start
mov esi, 0
_start: cmp esi, 3
ja exit
mov eax, 4 ; 'write' syscall
mov ebx, 1
mov ecx, hello
mov edx, 14
int 80h
inc esi
jmp _start
exit: mov eax, 1 ; 'exit' syscall
mov ebx, 0
int 80h$ nasm -f elf64 hello.asm -o hello.o
$ ld hello.o -o hello
$ ./hello
Hello, World!
Hello, World!
Hello, World!
Hello, World! section .data
hello: db 'Hello, World!', 10
section .text
global _start
_start: call phello
call phello
call phello
mov eax, 1 ; 'exit' syscall
mov ebx, 0
int 80h
phello: mov eax, 4 ; 'write' syscall
mov ebx, 1
mov ecx, hello
mov edx, 14
int 80h
ret$ nasm -f elf64 hello.asm -o hello.o
$ ld hello.o -o hello
$ ./hello
Hello, World!
Hello, World!
Hello, World!- https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86-32_bit
- https://asmtutor.com/
- 별찍기 (피라미드)
- 입력이 주어졌을때, 해당 정수를 높이로 가지는 피라미드 출력해보기!