Author Topic: Win64 Url Encode Byte Array NASM GCC GOLINK  (Read 14358 times)

Offline encryptor256

  • Full Member
  • **
  • Posts: 250
  • Country: lv
  • Win64 .
    • On Youtube: encryptor256
Win64 Url Encode Byte Array NASM GCC GOLINK
« on: November 26, 2013, 06:29:57 AM »
Hello!

; ------------------------------------------------------------ ;
; This is: Win64 Url Encode Byte Array NASM, GCC, GOLINK.
; Author: J.K. Encryptor256
; Date: November 26, 2013
;
; ------------------------------------------------------------ ;
; Description:
; Url encode byte array.
; Print result.
;
; ------------------------------------------------------------ ;
; Using:
;
; 1. NASM: (http://nasm.us/)
;
;     "The Netwide Assembler, NASM,"
;     "is an 80x86 and x86-64 assembler designed"
;     "for portability and modularity."
;
; 2. MINGW64-GCC: (http://mingw-w64.sourceforge.net/)
;
;     "Mingw-w64 delivers runtime, headers and libs for"
;     "developing both 64 bit (x64) and 32 bit (x86) windows"
;     "applications using GCC and other free software compilers."
;
; 3. GoLink: (http://www.godevtool.com/)
;
;     "Jeremy Gordon's Go Tools for Win32 and Win64:"
;     "assembler, resource compiler,"
;     "linker, debugger and information"
;
; ------------------------------------------------------------ ;
; Compile:
;
; 1. NASM.EXE:
;     "-f win64 main.asm -o main.obj"
;
;           Output size: 1.64 KB (1,688 bytes)
;
; Choose your linker:
;
; 2. GCC.EXE:
;     "main.obj -m64 -o main.exe"
;
;           Output size: 43.3 KB (44,395 bytes)
;
; 3. GoLink.EXE:
;     "/entry main /console main.obj MSVCRT.dll"
;
;           Output size:  2.00 KB (2,048 bytes)
;
; ------------------------------------------------------------ ;

Info:
This procedure "urlEncodeByteArray" became pretty interesting,
it uses internal procedure. First time it run's loop cycle,
it determines the size of result buffer. Second time, it calls,
internal procedure and now it updates result buffer, using
the same cycle again.

Procedure:
Code: [Select]
; -----------------------------------------------------------;
;
; Procedure: urlEncodeByteArray
;
; Encodes byte array (RFC1738)
;
; RCX - src buffer address
; RDX - src buffer len
; R8 - hex idicator
;
; Usage:
;
; Result of this example,
; should be: ,124Vx,9A,BC,DE,F1,23Eg,89,AB,CD,EF,124Vx,9A
; Be aware that, using HEX idicator '%' will produce
; visual glitch with "printf", because '%' is a special char.
;
;           ...
;           align 8
;           txt_test:db 0x12,0x34,0x56,0x78,0x9a,
;                    db 0xbc,0xde,0xf1,0x23,0x45,
;                    db 0x67,0x89,0xab,0xcd,0xef,
;                    db 0x12,0x34,0x56,0x78,0x9a
;           txt_test_len equ ($ - txt_test)
;           ...
;
;           mov rdx,txt_test_len
;           mov rcx,txt_test
;           mov r8,','
;           call urlEncodeByteArray
;           mov rbx,rax
;
;           mov rcx,rax
;           call printf
;
;           mov rcx,rbx
;           call free
;
;
; Returns a pointer to null terminated string buffer.
; Null terminator are excluded from buffer len.
; Returned buffer must be freed by "malloc".
;
; Returns a pointer to buffer into RAX.
; Returns a buffer len into RCX.
; Set's carry flag on error.
; Clear's carry flag on success.
;
; -----------------------------------------------------------;
align 8
urlEncodeByteArray:

      ; Check args
      xor rax,rax
      cmp rcx,rax
      je .earlyQuit
      cmp rdx,rax
      jne .proceed
.earlyQuit:
      ; Set error n quit
      stc
      ret
.proceed:

      ; Save args
      mov qword [rsp+8*1],rcx; src buffer address
      mov qword [rsp+8*2],rdx; src buffer len
      mov qword [rsp+8*3],r8; hex indicator
      ; r8 - hex indicator,
      ; example value ('%', or '.') => (%HH or .HH)

      ; Create stack
      push rbp
      mov rbp,rsp
      push rbx
      push r12
      push r13
      push r14
      push rsi
      push rdi
      lea rsp,[rsp-(8*4)]

      ; 1. Save src buffer address and len
      ; rcx is already set
      ; rdx is already set
      mov rsi,rcx ; address
      mov r12,rdx ; len
      mov r14,rcx

      ; 2. Determine dst buffer len (Loop)
      ; rsi - src buffer address
      ; rcx - src buffer len
      ; rdx - dst buffer len
      ; bx - temporary usage
      ; r13 - must be zero
      mov rcx,r12
      xor rdx,rdx
      xor r13,r13

      ; 3. Internal procedure
.lblProcedure:
      cld

      ; 4. Internal loop
.lblLoop:
      lodsb

      ; 4.1. Individual
      cmp al,byte ('.')
      je .lblStoreSingle
      cmp al,byte ('-')
      je .lblStoreSingle
      cmp al,byte ('_')
      je .lblStoreSingle
      cmp al,byte ('~')
      je .lblStoreSingle

      ; 4.2. 0-9
      cmp al,byte ('0')
      setge bl
      cmp al,byte ('9')
      setle bh
      and bl,bh
      jnz .lblStoreSingle

      ; 4.3. a-z
      cmp al,byte ('a')
      setge bl
      cmp al,byte ('z')
      setle bh
      and bl,bh
      jnz .lblStoreSingle

      ; 4.4. A-Z
      cmp al,byte ('A')
      setge bl
      cmp al,byte ('Z')
      setle bh
      and bl,bh
      jnz .lblStoreSingle

.incBy3:
      add rdx,byte (2)

      ; 3.1. Functionoid - store '%' 'H' 'H'
      cmp r13b, byte (1)
      jne .lblContinue

      ; 3.2. Store '%'
      mov ah,al; Save al
      ;mov al,byte ('%')
      mov al,r8b
      stosb

      ; 3.3. Build n Store hex part HH
      mov al,ah; Restore al
      and al,0xF0
      and ah,0x0F
      shr al,byte (0x04)
.lblAL:
      cmp al,byte (0x09)
      jle .lblAH
      add al,byte (0x07)
.lblAH:
      cmp ah,byte (0x09)
      jle .lblDone
      add ah,byte (0x07)
.lblDone:
      add ax,word (0x3030)
      stosw
      jmp .lblContinue

.lblStoreSingle:
      ; 3.4. Functionoid - store 'c'
      cmp r13b, byte (1)
      jne .lblContinue
      ; Store char
      stosb

.lblContinue:
      inc rdx
      loop .lblLoop

      ; 3.5. Functionoid - quit
      cmp r13b, byte (1)
      jne .fnQuit
      ; Set null terminator byte
      mov al,byte (0)
      stosb
      ret
.fnQuit:

      ; 5. Save hex idicator
      mov rbx,r8

      ; 6. Allocate buffer
      mov rcx,rdx
      inc rcx
      call malloc
      xor rdx,rdx
      cmp rax,rdx
      je .quitError

      ; 7. Restore hex idicator
      mov r8,rbx

      ; 8. Prepare procedure params
      mov rsi,r14
      mov rdi,rax
      mov rcx,r12
      xor rdx,rdx
      mov r13b,byte (1)
      mov r14,rax ; Save buffer address from malloc

      ; 9. Call internal procedure
      call .lblProcedure
      jmp .quitSuccess

.quitError:
     ; Set error
     stc
     jmp .quit

.quitSuccess:
      ; 10. Set return value
      mov rax,r14 ; address of buffer
      mov rcx,rdx ; buffer len
      ; 11. Set success
      clc

.quit:
      ; 12. Clear stack n quit
      lea rsp,[rsp+(8*4)]
      pop rdi
      pop rsi
      pop r14
      pop r13
      pop r12
      pop rbx
      pop rbp
      ret

Output:
Code: [Select]
[code begin]


urlEncodeByteArray: .124Vx.9A.BC.DE.F1.23Eg.89.AB.CD.EF.124Vx.9A


[code end]

Video:
Watch source code and run time demo on youtube: Win64 Url Encode Byte Array NASM GCC GOLINK

Attachment:
Added attachment named: win64_urlencodebytearray_nasm_gcc_golink.zip, which includes, main compile file of source code: "main.asm".

An that's it,
Bye,
Encryptor256!!!
Encryptor256's Investigation \ Research Department.