; -----------------------------------------------------------------------------
; 파일명: realip_finder.asm
; 빌드 방법:
; nasm -f elf64 realip_finder.asm -o realip_finder.o
; gcc realip_finder.o -o realip_finder -no-pie
; -----------------------------------------------------------------------------
extern printf
extern sprintf
extern snprintf
extern popen
extern pclose
extern fgets
extern getaddrinfo
extern freeaddrinfo
extern inet_pton
extern inet_ntop
extern strchr
extern strcspn
extern strncpy
extern atoi
extern memset
extern exit
extern perror
section .data
; 색상 코드
color_red db 0x1b, "[31m", 0
color_green db 0x1b, "[32m", 0
color_reset db 0x1b, "[0m", 0
; 메시지
msg_usage db "사용법: %s <target-domain>", 10, 0
msg_start db 0x1b, "[32m=== Auto Real-IP Detector Started ===", 0x1b, "[0m", 10, 0
msg_target db "Target: %s", 10, 0
msg_scan db "Scanning subdomains using 'subfinder'...", 10, 10, 0
msg_err_cmd db "Subfinder 실행 실패", 0
msg_done db 10, 0x1b, "[32m=== Scan Completed ===", 0x1b, "[0m", 10, 0
fmt_cf db "[CF] %s -> %s", 10, 0
fmt_real db 0x1b, "[31m[REAL] %s -> %s (Target Found!)", 0x1b, "[0m", 10, 0
cmd_fmt db "subfinder -d %s -silent", 0
mode_r db "r", 0
newline db 10, 0
; Cloudflare IP Ranges
cf_r1 db "173.245.48.0/20", 0
cf_r2 db "103.21.244.0/22", 0
cf_r3 db "103.22.200.0/22", 0
cf_r4 db "103.31.4.0/22", 0
cf_r5 db "141.101.64.0/18", 0
cf_r6 db "108.162.192.0/18", 0
cf_r7 db "190.93.240.0/20", 0
cf_r8 db "188.114.96.0/20", 0
cf_r9 db "197.234.240.0/22", 0
cf_r10 db "198.41.128.0/17", 0
cf_r11 db "162.158.0.0/15", 0
cf_r12 db "104.16.0.0/13", 0
cf_r13 db "104.24.0.0/14", 0
cf_r14 db "172.64.0.0/13", 0
cf_r15 db "131.0.72.0/22", 0
cf_ranges dq cf_r1, cf_r2, cf_r3, cf_r4, cf_r5, cf_r6, cf_r7, cf_r8
dq cf_r9, cf_r10, cf_r11, cf_r12, cf_r13, cf_r14, cf_r15, 0
section .bss
cmd_buf resb 512
line_buf resb 256
section .text
global main
; -----------------------------------------------------------------------------
; 함수: is_ip_in_cidr
; 설명: CIDR 계산 및 비교
; -----------------------------------------------------------------------------
is_ip_in_cidr:
push rbp
mov rbp, rsp
; 스택 정렬: push rbx(8) + push r12(8) + push r13(8) + sub 72 = 96 (16의 배수)
push rbx
push r12
push r13
sub rsp, 72 ; 로컬 변수 공간
mov r12, rdi ; ip_str 보존
mov r13, rsi ; cidr_str 보존
; 1. CIDR 복사
lea rdi, [rbp-48] ; cidr_copy (32 bytes)
mov rsi, r13
mov rdx, 31
call strncpy
mov byte [rbp-48+31], 0
; 2. 슬래시 찾기
lea rdi, [rbp-48]
mov esi, '/'
call strchr
test rax, rax
jz .ret_false
mov byte [rax], 0 ; '/' -> NULL
inc rax
mov rdi, rax
call atoi
mov [rbp-52], eax ; prefix_len
; 3. IP 변환 (inet_pton)
mov edi, 2 ; AF_INET
mov rsi, r12 ; ip_str
lea rdx, [rbp-56] ; &ip_addr
call inet_pton
cmp eax, 1
jne .ret_false
mov edi, 2 ; AF_INET
lea rsi, [rbp-48] ; cidr_copy
lea rdx, [rbp-60] ; &net_addr
call inet_pton
cmp eax, 1
jne .ret_false
; 4. 비트 비교
mov eax, [rbp-56] ; ip
bswap eax
mov ebx, eax ; ebx = ip (host)
mov eax, [rbp-60] ; net
bswap eax
mov r12d, eax ; r12d = net (host)
mov ecx, [rbp-52] ; prefix
cmp ecx, 0
je .mask_zero
mov edx, 32
sub edx, ecx
mov ecx, edx
mov eax, -1
shl eax, cl
jmp .do_compare
.mask_zero:
xor eax, eax
.do_compare:
and ebx, eax
and r12d, eax
cmp ebx, r12d
je .ret_true
.ret_false:
xor eax, eax
jmp .cleanup
.ret_true:
mov eax, 1
.cleanup:
add rsp, 72
pop r13
pop r12
pop rbx
leave
ret
; -----------------------------------------------------------------------------
; 함수: check_if_cloudflare
; -----------------------------------------------------------------------------
check_if_cloudflare:
push rbp
mov rbp, rsp
; 스택 정렬: push rbx(8) + push r12(8) = 16 (정렬됨)
push rbx
push r12
mov r12, rdi ; ip_str
xor ebx, ebx ; index
.cf_loop:
lea rax, [cf_ranges]
mov rsi, [rax + rbx*8]
test rsi, rsi
jz .cf_not_found
mov rdi, r12
call is_ip_in_cidr
test eax, eax
jnz .cf_found
inc rbx
jmp .cf_loop
.cf_found:
mov eax, 1
jmp .cf_end
.cf_not_found:
xor eax, eax
.cf_end:
pop r12
pop rbx
leave
ret
; -----------------------------------------------------------------------------
; 함수: analyze_domain (여기가 가장 중요: 스택 정렬 수정됨)
; -----------------------------------------------------------------------------
analyze_domain:
push rbp
mov rbp, rsp
; [중요] 스택 정렬 계산
; Call 진입 시 RSP 끝자리: 8 (Return Address)
; push rbp: 0 (16바이트 정렬됨)
; push rbx: 8 (정렬 깨짐)
; sub rsp, 72: 80 (16 * 5 = 80 -> 정렬됨!)
; 총 공간: 72바이트 (로컬변수용)
push rbx
sub rsp, 72
; [rbp-48]: struct addrinfo hints (48 bytes max)
; [rbp-56]: struct addrinfo *res (8 bytes)
; [rbp-72]: char ip_str[16] (16 bytes)
; Total needed: ~72 bytes.
mov rbx, rdi ; domain string
; 1. 개행 제거
mov rdi, rbx
lea rsi, [newline]
call strcspn
mov byte [rbx + rax], 0
; 2. memset hints
lea rdi, [rbp-48]
xor esi, esi
mov edx, 48 ; sizeof(hints)
call memset
; 3. hints 설정
mov dword [rbp-48+4], 2 ; ai_family = AF_INET
mov dword [rbp-48+8], 1 ; ai_socktype = SOCK_STREAM
; 4. getaddrinfo
mov rdi, rbx ; node
xor esi, esi ; service
lea rdx, [rbp-48] ; hints
lea rcx, [rbp-56] ; res
call getaddrinfo
test eax, eax
jnz .ad_cleanup ; 실패 시 리턴
; 5. IP 추출
mov rax, [rbp-56] ; res
mov rax, [rax + 24] ; res->ai_addr -> struct sockaddr_in *
lea rsi, [rax + 4] ; &sin_addr (offset 4)
mov edi, 2 ; AF_INET
lea rdx, [rbp-72] ; dst (ip_str buffer)
mov ecx, 16 ; size
call inet_ntop
; 6. CF 확인
lea rdi, [rbp-72]
call check_if_cloudflare
test eax, eax
jnz .print_cf
; REAL IP 발견
lea rdi, [fmt_real]
mov rsi, rbx
lea rdx, [rbp-72]
xor eax, eax
call printf
jmp .free_res
.print_cf:
lea rdi, [fmt_cf]
mov rsi, rbx
lea rdx, [rbp-72]
xor eax, eax
call printf
.free_res:
mov rdi, [rbp-56]
call freeaddrinfo
.ad_cleanup:
add rsp, 72
pop rbx
leave
ret
; -----------------------------------------------------------------------------
; Main
; -----------------------------------------------------------------------------
main:
push rbp
mov rbp, rsp
sub rsp, 16 ; RSP 정렬됨 (push rbp 후 0 -> sub 16 -> 0)
cmp edi, 2
je .run
lea rdi, [msg_usage]
mov rsi, [rsi]
xor eax, eax
call printf
mov eax, 1
leave
ret
.run:
mov rbx, [rsi + 8] ; argv[1]
lea rdi, [msg_start]
xor eax, eax
call printf
lea rdi, [msg_target]
mov rsi, rbx
xor eax, eax
call printf
lea rdi, [msg_scan]
xor eax, eax
call printf
; 명령어 생성
lea rdi, [cmd_buf]
mov rsi, 512
lea rdx, [cmd_fmt]
mov rcx, rbx
xor eax, eax
call snprintf
; popen
lea rdi, [cmd_buf]
lea rsi, [mode_r]
call popen
test rax, rax
jz .fail
mov [rbp-8], rax ; FILE *fp
.read:
lea rdi, [line_buf]
mov esi, 256
mov rdx, [rbp-8]
call fgets
test rax, rax
jz .close
lea rdi, [line_buf]
call analyze_domain
jmp .read
.close:
mov rdi, [rbp-8]
call pclose
lea rdi, [msg_done]
xor eax, eax
call printf
xor eax, eax
leave
ret
.fail:
lea rdi, [msg_err_cmd]
call perror
mov eax, 1
leave
ret |