Skip to content

Instantly share code, notes, and snippets.

@isopen
Created September 21, 2025 11:17
Show Gist options
  • Save isopen/41481eda87db2e6426af75be9d1f3748 to your computer and use it in GitHub Desktop.
Save isopen/41481eda87db2e6426af75be9d1f3748 to your computer and use it in GitHub Desktop.
nasm_tdjson_example
; 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment