Поскольку я пытаюсь улучшить свои навыки сборки x86, я разрабатываю реализацию NASM Tiny Encryption Algorithm (TEA) .
Алгоритм шифрования определяется следующим образом:
void encrypt (uint32_t v[2], uint32_t k[4]) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9E3779B9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
К сожалению, моя версия NASM где-то не работает, и до сих пор я не смог найти ошибки.
Реализация NASM была разработана под * nix x86 и должен быть связан со следующей командой, поскольку я непосредственно пишу в секции .text во время выполнения: ld -m elf_i386 -N -o tea tea.nasm
Здесь мой код до сих пор:
global _start
; EAX = store arithmetic results
; ECX = COUNTER
; EBX = current chunk (v0,v1)
; EDX = sum
; ESI = *encrypted_shellcode
; EDI = *key
section .text
_start:
jmp short key_section ; goto key_section
key_section:
; key0: 0x6c645a37
; key1: 0x6e775667
; key2: 0x57433641
; key3: 0x4e6c7151
call key_loader ; goto key_loader, putting key on the stack
; | 0 | 1 | 2 | 3 |
; | EDI | EDI+4 | EDI+8 | EDI+12 |
key: db 0x6c, 0x64, 0x5a, 0x37, 0x6e, 0x77, 0x56, 0x67, 0x57, 0x43, 0x36, 0x41, 0x4e, 0x6c, 0x71, 0x51
key_loader:
pop edi ; load address of our key into EDI (JMP CALL POP trick)
jmp short shellcode_section ; goto shellcode_section
encoder: ; encoder
pop esi ; load address of our shellcode into ESI (JMP CALL POP trick)
mov ecx, 3 ; load the number of our shellcode chunks, used to loop. (shellcode length is 24. 24/4(DWORD)=6 blocks/2(chunks taken 2by 2)=3)
;cld ; clear direction flag, setting it to 0.
encrypt_loop:
push ecx ; save counter status before entering 32 iteration loop
mov ecx, 32 ; store loop counter, we nedd to cycle x32 times
xor edx, edx ; clean EDX (sum), EDX = 0
loop_32:
mov ebx, dword [esi+4] ; v1 load encrypted_shellcode's chunk DWORD pointed by ESI in EBX | EBX=B
; sum = sum+delta
add edx, 0x9E3779B9 ; sum = sum+delta
; v0 = v0 + ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
mov eax, ebx ; v1 is now in EAX
shl eax, 4 ; v1<<4
add eax, dword [edi] ; +k0
push eax ; store EAX (result) on stack
mov eax, ebx ; v1 is now in EAX
add eax, edx ; v1 + sum
push eax ; store EAX (result) on stack
mov eax, ebx ; v1 is now in EAX
shr eax, 5 ; v1>>5
add eax, dword [edi+4] ; +k1
; EAX = ((v1>>5) + k1)
pop ebx ; restore EBX = (v1 + sum)
xor eax, ebx ; EAX = (v1 + sum) ^ ((v1>>5) + k1)
pop ebx ; restore EBX = (v1<<4) + k0)
xor eax, ebx ; EAX = ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1)
add eax, dword [esi] ; v0 = v0 + ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1)
mov dword [esi], eax ; store encrypted v0 back to shellcode "buffer"
;--------------------------------------------------------------------------------------
mov ebx, dword [esi] ; v0 load shellcode's chunk DWORD pointed by ESI in EBX | EBX=A
; v1 = v1 + ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
mov eax, ebx ; v0 is now in EAX
shl eax, 4 ; v0<<4
add eax, dword [edi+8] ; +k2
push eax ; store EAX (result) on stack
mov eax, ebx ; v0 is now in EAX
add eax, edx ; v0 + sum
push eax ; store EAX (result) on stack
mov eax, ebx ; v0 is now in EAX
shr eax, 5 ; v0>>5
add eax, dword [edi+12] ; +k3
; EAX = ((v0>>5) + k3)
pop ebx ; restore EBX = (v0 + sum)
xor eax, ebx ; EAX = (v0 + sum) ^ ((v0>>5) + k3)
pop ebx ; restore EBX = (v0<<4) + k2)
xor eax, ebx ; EAX = ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3)
add eax, dword [esi+4] ; v1 = v1 + ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3)
mov dword [esi+4], eax ; store encrypted v1 back to shellcode "buffer"
loop loop_32 ; ECX is 0? No, we go back at loop_32 and execute the cicle again
pop ecx ; restore ECX counter status
add esi, 8 ; select next chunk "couple"
loop encrypt_loop ; ECX is 0? No, we go back at decrypt_loop and execute the cicle again
exec:
int3 ; ECX is 0! We've encrypted our shellcode. GDB: x/24cb encrypted_shellcode
shellcode_section:
call encoder ; goto decoder, putting shellcode on the stack
; | A | B | C | D | E | F |
; | ESI | ESI+4 | ESI+8 | ESI+12 | ESI+16 | ESI+20 |
encrypted_shellcode: db 0x31, 0xc0, 0x50, 0x68, 0x2f, 0x2f, 0x73, 0x68, 0x68, 0x2f, 0x62, 0x69, 0x6e, 0x87, 0xe3, 0xb0, 0x0b, 0xcd, 0x80, 0x90, 0x90, 0x90, 0x90, 0x90
; |<-chunk read direction|
C реализация работает правильно (может шифровать / дешифровать) и возвращает следующее:
- Оригинал v0 0x31c05068
- Оригинал v1 0x2f2f7368
- k0 = 0x6c645a37, k1 = 0x6e775667 , k2 = 0x57433641, k3 = 0x4e6c7151
C:
- Crypted v0: 0x17c59b4a
- Crypted v1: 0xf8c4497
ASM:
- Crypted v0: 0x56efe51
- Crypted v1: 0xba4731 e3
Почему моя реализация не работает? Чего мне не хватает?
Спасибо всем заранее и, пожалуйста, будьте добры, я не эксперт