Assembly
[어셈블리어] 시저암호 암호화 with Assembly
GuTTe
2018. 11. 3. 00:22
C로 시저암호(카이사르암호) 암호화와 복호화를 먼저 작성하고 이를 바탕으로 어셈블리어로 작성하려 한다.
먼저 복호화 구간은 조금 복잡해서 먼저 암호화 구간만 진행했는데 아마 내일 부터 다시 복호화 구간을 만들어내지 않을까 생각해본다... ㅎ
코드는 주석을 대충달았는데 알아서 잘 해석하길 바랍니다.
또한 %include "asm_io.inc"는 Pual Carter 교수가 만든 include파일인데 print_nl을 사용하기 위해서다 이 파일이 없다면 지우고 print_nl을 지우길 바람.
;일단 필요한 함수 strlen, strcpy구현
%include "asm_io.inc"
segment .bss
segment .data
format1 db "%s", 0
format2 db "%d", 0
print1 db "input your key(0~25) : ", 0
segment .txt
global asm_main
global strlen_s ;문자열의 길이를 체크할 함수 구현
global strcpy ;문자열을 복사할 함수 구현
global crypto ;평문을 암호화 시킬 함수
global encrypto ;암호문을 복호화 시킬 함수
extern printf
extern scanf
extern gets
extern strlen
asm_main:
push ebp
mov ebp, esp
sub esp, 80 ;buffer
sub esp, 8 ;문자열의 길이, key value
lea eax, [ebp-80] ;buffer의 공간 즉, 80바이트 만큼 평문을 처리할 것이다.
push eax
call gets ;gets함수를 통해 buffer의 시작주소를 인자로 준다.
add esp, 4
lea eax, [ebp-80]
push eax
push format1
call printf
add esp, 8
call print_nl ;개행문자를 출력
lea eax, [ebp-80] ;버퍼의 시작주소를 따온다.
push eax ;string push!
call strlen_s ;
;call strlen_s ;strlen 호출
add esp, 4
mov [ebp-84], eax ;plain의 문자열 길이 변수(평문의 길이 exclude NULL)
;input key
push print1
push format1
call printf
add esp, 8
lea eax, [ebp-88] ;key value (KEY값)
push eax
push format2
call scanf
add esp, 8
lea eax, [ebp-80] ;buffer ebp+16(평문이 있는 버퍼의 주소값)
push eax ;스택에 푸시
push dword [ebp-84] ;length ebp+12 평문의 길이 푸시
push dword [ebp-88] ;key ebp+8 키의 값 스택에 푸시
call crypto ;암호화 진행 함수
add esp, 12 ;인자정리
lea eax, [ebp-80]
push eax
push format1
call printf
add esp, 8
call print_nl
add esp, 88
leave
ret
strlen_s: ;문자열의 길이를 반환하는 함수 널문자는 배제 +8
push ebp
mov ebp, esp
mov esi, [ebp+8] ;버퍼의 주소를 땀
xor ecx, ecx
jmp strlen_start_len
strlen_start_len:
lodsb
cmp al, 0x0 ;널까지하고 앞에 개행을 널로 바꿔주자
je strlen_end
inc ecx
;add esi, 1
jmp strlen_start_len
strlen_end:
mov eax, ecx ;return string length
pop ebp
ret
strcmp: ;문자열을 카피해주는 함수 널문자 포함
push ebp
mov ebp, esp
pop ebp
ret
crypto:
push ebp
mov ebp, esp
xor ecx, ecx
mov esi, [ebp+16] ;버퍼의 주소를 esi로 줌
mov edi, [ebp+16] ;버퍼의 주소를 다시 edi로 줌 (edi에는 최종으로 값이 변경된 간접연산)
mov ecx, [ebp+12] ;
xor eax, eax
xor ebx, ebx
crypto_starting: ;[ebp+8]key [ebp+12]length [ebp+16]buffer
xor eax, eax
lodsb ;al = [esi], esi+=1
cmp eax, 0x20 ;문자가 space인지(공백) 비교한다.
je crypto_set_space
mov ebx, [ebp+8] ;key value
sub eax, 0x41 ; 'A'의 값을 빼서 offset을 구한다.
add eax, ebx
mov ebx, 26 ;나눌 수
CDQ ;32bit레지스터를 eax:edx로 확장한다. 여기서 eax에는 몫이, edx에는 나머지가 들어간다.
idiv ebx ;edx에는 나머지가 들어감
add edx, 0x41 ;다시 아스키코드 값 'A'의 값을 더해서 암호화된 값을 edx에 넣는다.
mov al, dl ;최종적으로 나온 값을 al에 넣고
stosb ;[edi] = al => add edi, 1한다. 즉, edi에 넣는다.
loop crypto_starting ;다시 루프
crypto_end:
leave
ret
crypto_set_space:
dec ecx
stosb ;공백일 경우 공백을 다시 넣는다.
jmp crypto_starting