nasm_tdjson_example

September 21, 2025 ยท View on GitHub

; TDLib Minimal Linux Client in x86-64 Assembly (NASM) ; ; nasm -f elf64 -o nasm_tdjson_example.o nasm_tdjson_example.asm ; gcc -o nasm_tdjson_example nasm_tdjson_example.o -ldl -no-pie ; ./nasm_tdjson_example

section .data ; Error messages lib_error db "Error: libtdjson.so not found", 10, 0 client_error db "Error: Failed to create client", 10, 0 input_error db "Error reading input", 10, 0 receive_error db "Error in receive function", 10, 0

; Function names
create_name db "td_json_client_create", 0
send_name db "td_json_client_send", 0
receive_name db "td_json_client_receive", 0
destroy_name db "td_json_client_destroy", 0
execute_name db "td_json_client_execute", 0

; Library name
lib_name db "libtdjson.so", 0

; Prompts
phone_prompt db "Enter phone number (international format): ", 0
code_prompt db "Enter authentication code: ", 0
password_prompt db "Enter password: ", 0
auth_success db "Authorization successful!", 10, 0
auth_wait db "Waiting for authorization...", 10, 0

; JSON messages
params_msg db '{"@type":"setTdlibParameters","database_directory":"td_data","use_message_database":true,"api_id":94575,"api_hash":"a3406de8d171bb422bb6ddf3bbd800e2","system_language_code":"en","device_model":"AsmClient","application_version":"1.0"}', 0
verbosity_msg db '{"@type":"setLogVerbosityLevel","new_verbosity_level":2}', 0
close_msg db '{"@type":"close"}', 0
newline db 10, 0

; Authorization states
auth_wait_phone db "authorizationStateWaitPhoneNumber", 0
auth_wait_code db "authorizationStateWaitCode", 0
auth_wait_password db "authorizationStateWaitPassword", 0
auth_ready db "authorizationStateReady", 0

; Format strings
fmt_phone db '{"@type":"setAuthenticationPhoneNumber","phone_number":"%s"}', 0
fmt_code db '{"@type":"checkAuthenticationCode","code":"%s"}', 0
fmt_password db '{"@type":"checkAuthenticationPassword","password":"%s"}', 0

section .bss ; Handle pointers lib_handle resq 1 client_handle resq 1

; Function pointers
create_func resq 1
send_func resq 1
receive_func resq 1
destroy_func resq 1
execute_func resq 1

; Buffers
input_buffer resb 256
phone_buffer resb 32
code_buffer resb 16
password_buffer resb 64
json_buffer resb 1024
auth_state resq 1

section .text global main extern dlopen, dlsym, printf, sleep, exit, fgets, stdin, strstr, sprintf, strlen, putchar, usleep, fflush

main: push rbp mov rbp, rsp sub rsp, 32

; Load TDLib library
mov rdi, lib_name
mov rsi, 1
call dlopen
test rax, rax
jz .dl_error
mov [lib_handle], rax

; Get function addresses
mov rdi, [lib_handle]
mov rsi, create_name
call dlsym
mov [create_func], rax

mov rdi, [lib_handle]
mov rsi, send_name
call dlsym
mov [send_func], rax

mov rdi, [lib_handle]
mov rsi, receive_name
call dlsym
mov [receive_func], rax

mov rdi, [lib_handle]
mov rsi, destroy_name
call dlsym
mov [destroy_func], rax

mov rdi, [lib_handle]
mov rsi, execute_name
call dlsym
mov [execute_func], rax

; Create TDLib client
call [create_func]
test rax, rax
jz .client_error
mov [client_handle], rax

; Set log verbosity
mov rdi, [client_handle]
mov rsi, verbosity_msg
call [execute_func]

; Set TDLib parameters
mov rdi, [client_handle]
mov rsi, params_msg
call [send_func]

; Authorization loop
xor r12, r12
mov qword [auth_state], 0

mov edi, 50000
call usleep

.auth_loop: mov rdi, [client_handle] xor rsi, rsi call [receive_func] test rax, rax jz .no_message

; Process message
mov rdi, rax
call process_message
cmp r12, 1
je .auth_complete

.no_message: ; Check if we need to request input cmp qword [auth_state], 1 ; wait_phone je .request_phone cmp qword [auth_state], 2 ; wait_code je .request_code cmp qword [auth_state], 3 ; wait_password je .request_password

mov edi, 10000
call usleep
jmp .auth_loop

.request_phone: mov rdi, phone_prompt call printf xor rdi, rdi call fflush

; Read phone number
mov rdi, phone_buffer
mov rsi, 32
mov rdx, [stdin]
call fgets
test rax, rax
jz .input_error

; Remove newline
mov rdi, phone_buffer
call remove_newline

; Create JSON for phone number
mov rdi, json_buffer
mov rsi, fmt_phone
mov rdx, phone_buffer
call sprintf

; Send to TDLib
mov rdi, [client_handle]
mov rsi, json_buffer
call [send_func]

mov qword [auth_state], 0

mov edi, 10000
call usleep
jmp .auth_loop

.request_code: mov rdi, code_prompt call printf xor rdi, rdi call fflush

; Read code
mov rdi, code_buffer
mov rsi, 16
mov rdx, [stdin]
call fgets
test rax, rax
jz .input_error

; Remove newline
mov rdi, code_buffer
call remove_newline

; Create JSON for code
mov rdi, json_buffer
mov rsi, fmt_code
mov rdx, code_buffer
call sprintf

; Send to TDLib
mov rdi, [client_handle]
mov rsi, json_buffer
call [send_func]

mov qword [auth_state], 0

mov edi, 10000
call usleep
jmp .auth_loop

.request_password: mov rdi, password_prompt call printf xor rdi, rdi call fflush

; Read password
mov rdi, password_buffer
mov rsi, 64
mov rdx, [stdin]
call fgets
test rax, rax
jz .input_error

; Remove newline
mov rdi, password_buffer
call remove_newline

; Create JSON for password
mov rdi, json_buffer
mov rsi, fmt_password
mov rdx, password_buffer
call sprintf

; Send to TDLib
mov rdi, [client_handle]
mov rsi, json_buffer
call [send_func]

mov qword [auth_state], 0

mov edi, 10000
call usleep
jmp .auth_loop

.auth_complete: mov rdi, auth_success call printf

; Main loop
mov r13, 100

.main_loop: ; Receive messages mov rdi, [client_handle] xor rsi, rsi call [receive_func] test rax, rax jz .no_msg_main

; Print message
mov rdi, rax
call printf
mov rdi, newline
call printf

.no_msg_main: mov edi, 50000 call usleep dec r13 jnz .main_loop

.cleanup: ; Send close command mov rdi, [client_handle] mov rsi, close_msg call [send_func]

mov edi, 50000
call usleep

; Destroy client
mov rdi, [client_handle]
call [destroy_func]

; Exit
xor rdi, rdi
call exit

.dl_error: mov rdi, lib_error call printf mov rdi, 1 call exit

.client_error: mov rdi, client_error call printf jmp .cleanup

.input_error: mov rdi, input_error call printf jmp .cleanup

process_message: push rbp mov rbp, rsp push r12 push r13 mov r12, rdi

mov rdi, r12
mov rsi, auth_wait_phone
call strstr
test rax, rax
jnz .wait_phone

mov rdi, r12
mov rsi, auth_wait_code
call strstr
test rax, rax
jnz .wait_code

mov rdi, r12
mov rsi, auth_wait_password
call strstr
test rax, rax
jnz .wait_password

mov rdi, r12
mov rsi, auth_ready
call strstr
test rax, rax
jnz .auth_ready

jmp .done

.wait_phone: mov qword [auth_state], 1 jmp .done

.wait_code: mov qword [auth_state], 2 jmp .done

.wait_password: mov qword [auth_state], 3 jmp .done

.auth_ready: mov r12, 1 mov qword [auth_state], 0

.done: pop r13 pop r12 pop rbp ret

remove_newline: push rbp mov rbp, rsp

mov rcx, rdi

.find_end: cmp byte [rcx], 0 je .check_newline inc rcx jmp .find_end

.check_newline: dec rcx cmp byte [rcx], 10 jne .end mov byte [rcx], 0

.end: pop rbp ret