1. Home
  2. 보안 강좌/CrackMe
  3. [Solution] Abex' CrackMe #2 풀이 (IDA, OllyDbg 사용)

[Solution] Abex' CrackMe #2 풀이 (IDA, OllyDbg 사용)

안녕하세요 파일입니다. 저번 CrackMe #1번 풀이에 이어서 이번엔 CrackMe #2번 풀이입니다.

또 오늘은 IDA와 올리디버거를 동시에 사용하면서 풀이합니다. (기본적으로 IDA로 정적분석하고, 올리디버거로 동적 분석할 것임.)

abex' crackme2.exe
0.02MB

 

다운로드는 여기서 하실 수 있습니다.

 

실행

먼저 실행하면 VB6.0 스러운 프로그램이 하나 나옵니다.

 

이름과 시리얼에 대한 힌트가 없으니 임의의 내용을 입력하고 Check를 눌러봅시다.

 

시리얼이 틀렸다네요. 보통 프로그램이던 대부분의 제품에서 자주 사용하는 방식인 시리얼 키(==일련번호, 제품키) 를 몰라도 크래킹해서 뚫어내는 문제인 듯 싶습니다.

 

추가적으로 이름은 4글자 이상이여야 하는 검사도 들어가 있습니다.

 

About을 누르니 코딩된 날짜가 무려 1999년 이라고 나오네요 -.-;; 이런 역사적인 산물이 2022년에도 열려서 크랙되고 있다니.. 가슴이 웅장해집니다 ㄹㅇ.. 이거 만드신 abex라는 분은 뭐하고 살까요..?

 

분석

 

PEID나 Detect It Easy를 사용하면 프로그램이 암호화(패킹 또는 난독화) 되지 않았다는 가정에 이 프로그램이 어떤 프로그래밍 언어로 만들어졌는지 알 수 있습니다. 생긴거만 대충 봐도 비주얼 베이직스러웠는데 프로그램으로 확인해보니깐 VB6.0으로 만들어진게 맞네요.

 

??? : 생긴걸로 어떻게 프로그램 언어를 파악하나요

 

라고 물어보실 수 있는데요.. 이건 제가 예전에 프로그래밍 입문을 오토핫키랑 VB6.0으로 해서 그렇습니다. VB6.0에서 프로그래밍 경험이 꽤 많거든요. 실제로 비주얼베이직 에서 만든 프로그램의 특유의(?) 디자인이 있습니다. 비슷하게 C# Winform으로 만든 프로그램도 디자인이 윈폼이라는 티가 많이나서 이 프로그램이 C#으로 만들었구나 대충 감이 오긴합니다.

 

물론 당연히 정확히 확인하려면 프로그램을 사용해야 하기에 자세히 확인해봤습니다. 이제 맨날하던대로 이 실행파일(*.exe), 기계어 덩어리를 디스어셈블러로 열어서 어셈블리어로 복구해봅시다.

IDA는 아직 익숙하지 않지만.. 이 문제는 CrackMe 1번에 비해 코드들이 많아서 IDA를 사용하면 도움을 꽤 받을 수 있습니다. IDA로 프로그램을 열어봅니다.

 

IDA는 64비트 버전이 아닌 32비트 버전으로 실행합니다.

 

프로그램을 키면 이렇게 메뉴창이 나옵니다. 4K TV랑 듀얼 모니터를 쓰다보니깐 이렇게 DPI가 마구 깨져서 글자 크기가 엄청 커졌네요. 글 읽는 분들 입장에선 보기 편할거 같아서 그냥 이 상태로 글을 쓰겠습니다 -.- 

일단 새로 파일을 열어야 되니 New 버튼을 눌러서 디스어셈블할 파일을 열어줍니다.

 

그럼 파일 여는 창이 뜨는데 abex' crackme2.exe 를 열어줍니다. 이렇게 파일 찾는게 싫으면 파일 여는 창을 끄고 저기 드래그 하란곳에 exe파일을 드래그해서 열어도 됩니다. 올리디버거에선 드래그 드롭 안됐는데 오오

 

밑에 idb파일은 제가 이전에 ida로 crackme를 이미 열어서 생긴 IDA가 만든 데이터 베이스 파일입니다. 무시해주세요

그러면 이렇게 exe 파일에 대한 정보를 선택하는 창이 나옵니다. 이 exe 파일이 어떤 CPU 명령어로 쓰였는지 (32비트나, 64비트, ARM 등등) 설정하는 창이라고 보시면 됩니다. 보시면 MS-DOS 도 있고 그냥 Binary File도 있는데요. 기본적으로 IDA가 파일을 열면 알아서 이 파일에 대한 정보를 알아서 찾아서 설정해주기 때문에 그냥 설정 안하고 대부분 OK 누르면 됩니다.

 

가끔 IDA가 실행 파일에 대한 정보를 제대로 못읽어올 때가 있는데 그때는 수동으로 설정해주셔야 합니다.

일단은 IDA가 잘 찾아줬을거라고 믿고 잘모르겠으니깐 OK를 눌러서 열어줍니다.

 

(그나저나 글씨가 진짜 더럽게 커졌네요)

 

열면 이제 디스어셈블된 상태의 명령어들이 보입니다. public start 부분이 프로그램의 시작점(Entry Point) 으로 보이는군요.

 

프로그램의 시작점을 영어로 Entry Point 라고 합니다. 프로그램은 시작시 해당 부분부터 실행이 됩니다. 프로그래밍 언어에서는 C언어의 main() 함수, Java의 main() 함수가 바로 프로그램의 시작점(Entry Point)이 됩니다.

 

IDA는 익숙치 않아서.. 올리디버거로 교차 검증을 해보니깐 저 부분이 Entry Point가 맞네요.

CALL에서 분석한 함수 이름이 다르긴 한데 IDA가 기본적으로 올리디버거보다 분석 능력이 좋기 때문에 조금더 구체적인 함수 이름을 붙여준 것입니다.

 

만약 IDA에서 코드를 보다가 길을 잃어서 프로그램 시작점(Entry Point)으로 다시 이동하고 싶다면 Ctrl + E를 누르고 start 라벨로 이동하면 됩니다. (OK 클릭)

 

어쨌던 간에 초반에 실행하는 코드는 단 두줄입니다. 401E14 라는 주소값을 PUSH를 통해 스택 메모리에 삽입하고 있으며, 바로 ThunRTMain(올리디버거에선 MSVBVM60 이라고 표시됨) 라는 함수를 호출하고 있습니다.

 

디버깅을 해보면 아는데 F8 - Step Over로 (함수 Return 될때까지 실행) 저 ThunRTMain 를 실행하는 순간에 프로그램 창이 열리게 됩니다. 보통 VB나 C#에서 열리는 창들을 "폼 또는 윈도우 폼" 이라고 부르는데요. 저게 메인 폼을 여는 일종의 메인 함수 역할을 하는듯합니다.

 

실제로도 저것은 MSVBVM60.ThunRTmain 를 호출 하는 것인데, ThunRTmain은 The Thunder Runtime Engine 의 약자로 비주얼 베이직에서 사용하는 전용 엔진을 의미합니다. 그래서 파일을 열었을때 ThunRTmain 이 보이면 꼭 정적 분석을 하지 않아도 이게 대충 비베로 만들었겠구나~ 눈치밥으로 알게됩니다.

 

VB(Visual Basic) 파일은 기본적으로  MSVBVM60.dll(Microsoft Visual Basic Virtual Machine 6.0) 라는 전용 엔진을 사용하며 VB 파일은 컴파일 옵션에 따라서 N code와 P code로 컴파일이 가능합니다. N code는 일반적인 디버거에서 해석 가능한 인텔 32비트 명령어(x86) 을 사용하는 반면에 P code는 인터프리터(Interpreter) 언어 개념으로서 VB 엔진으로 가상 머신을 구현하여 자체적으로 해석 가능한 명령어(바이트코드)를 사용합니다. 따라서 VB의 P code를 정확히 해석하기 위해선 VB 엔진을 분석하여 에뮬레이터를 구현해야 합니다.

 

이미지 출처 : https://hyeonslove.tistory.com/1
이미지 출처 : https://art-life.tistory.com/116

또 VB나 C#에서 코딩을 해보신 분들은 알겠지만 기본적으로 이벤트 핸들러(리스너)의 개념을 이용해서 코딩을 하게 됩니다. 사실 정확히 알필요는 없는데 기본적으로 VB6.0에서 프로그래밍을 하게 되면 프로그램의 폼(창)을 드래그 & 드롭으로 간편하게 디자인 할 수 있구요, 이제 저기서 버튼을 클릭하면 기능이 동작하게 만들어야 하는데, 이때 이벤트의 개념을 활용하게 됩니다.

 

예를 들어서 Command1 이 클릭되는 이벤트(상황) 이 발생하면 Click() 이라는 함수를 호출해 실행하게끔 하는것이죠.

 

click(){
//버튼 클릭 메세지 출력
}

우리는 VB6.0에서 코딩할때 저 Command1 버튼을 더블클릭하면 VB6.0에서 자동으로 클릭 이벤트에 맞춰서 실행할 수 있는 Click() 함수가 생성되고 클릭을 할때마다 Click() 함수가 호출되어 실행이 되는겁니다.

 

우리는 이벤트에 맞춰서 실행될 수 있는 자동으로 등록된 click() 함수에 버튼을 클릭했을때 실행할 명령어 내용(VB6.0 코드) 만 작성하면 될 것 입니다.

 

그래서 결론적으로 VB프로그램 시작에선 VB 엔진의 메인 함수 호출 후에 돌아올 리턴 주소를 스택에 Push한 다음, VB의 메인 함수를 호출해 메인 엔진을 실행하게 되는 것 입니다. RUN ThunRTmain()

어떻게 보면 C언어에서 main() 을 실행하는것과 크게 다르지 않습니다. GUI창이 뜰 뿐이죠.

 

그래서 디버거를 통해 ThunRTmain() 을 Call 하면 VB6.0의 메인창이 뙇! 뜨는 거구요.

추정컨데 이 프로그램 제작자인 abex님이 Check나 About, Quit버튼을 Click 하는 이벤트가 발생하면 어떤 함수가 호출되도록 해놨을 것입니다. 그러니깐 우리가 Check 버튼을 클릭하기 전까진 프로그램은 그냥 실행상태로 있다가, 마우스로 Check 버튼을 누른 순간 이벤트가 발동해서 Check 버튼에 대한 코드(함수)를 실행한다.. 라고 이해할 수 있습니다.

 

* 제가 VB6.0으로 프로그래밍을 한 지 몇년이 넘어가서 부정확한 설명이 있을 수 있습니다. 

 

그래서 디버깅하면 창이 띄워져서 멀뚱 멀뚱 있다가, 제가 Check 를 눌렀을때 실행되는 코드 쪽에 적당히 BP(Break Point) 를 걸어준 다음 Check를 눌러주면 그 위치에서 코드가 적당히 멈출 것 입니다.

 

그러니깐 우선 Check를 눌렀을때 실행될 코드를 IDA로 잘 찾아봐야 겠군요.

 

우리가 시리얼을 틀렸을 때 나오는 Nope, this serial is wrong! 이라는 문자열이 일종의 힌트입니다. 이 문자열이 어디서 참조 되고 있는지 찾으면 대충 Check 를 눌렀을때 실행하는 코드를 찾을 수 있을겁니다. (Check 를 누르면 실행하는 코드에서 저 메세지 창의 내용을 문자열을 활용해서 띄울거니깐요.)

IDA로 돌아와서 Ctrl + 1을 누르면 Quick View(빠른 보기) 가 나옵니다.

여기서 Strings를 눌러서 프로그램에서 참조(사용) 되는 모든 문자열을 찾아봅니다.

Strings 탭에서 프로그램에서 보이는 모든 문자열을 한번에 볼 수 있습니다.

Strings 탭에서 문자열을 확인해보니 Congratulations! 나 우리가 방금 찾아놓은 Nope, this serial is wrong! 이라는 문자열이 보이네요. 이거랑 연관이 있어보입니다.

 

IDA에서 문자열이 잘 찾아지지 않으면

올리디버거에선 문자열이 잘 찾아지는데 IDA에서는 문자열이 잘 안찾아지는 경우가 있습니다. IDA 기본 설정에서 모든 인코딩에 대해 문자열을 찾도록 설정해줘야 하는데요. Strings 탭에서 빈 곳이나 아무 곳에 오른쪽 클릭 - Setup 을 클릭합니다.

 

 

여기서 허용되는 문자열 타입(Allowed string types) 에 모두 체크합니다. 이렇게 해야 VB6.0 에서 나오는 문자열도 찾을 수 있습니다. 보니깐 인코딩으로 UTF-16LE를 이용해 데이터를 저장하는 거 같더라구요.

또 Minimal string length는 최소 몇글자 이상 보여줄지인데, 저는 1글자 이상이면 다 보여주도록 설정하였습니다.

 


 

일단은 원래 계획한 대로 Nope, this serial is wrong! 이 참조되는 코드 위치를 찾아보겠습니다.

저 Nope.. 부분을 더블 클릭 합니다.

 

그럼 .text 영역에서 이 문자열을 보여주는데.. 이 문자열이 참조된 위치를 오른쪽 위에 보여줍니다

저기 주소 위치에 이 문자열이 사용됐다는 의미로 보이는데요. 저기 빨간색으로 표시된 주소 부분을 또 더블클릭 해줍니다.

그러면 저 문자열이 사용된 코드 주소 위치로 점프할 수 있습니다.

우와. 우리가 시리얼을 틀리면 나오는 부분의 코드가 이제 찾아졌습니다. 비주얼 베이직으로 만들어서 그런가 코드가 상당히 복잡합니다. IDA를 사용하면 그래프 모드로 보여주기에 코드의 흐름을 한눈에 파악할 수 있습니다. (만약에 그래프 모드로 안보이면 스페이스바를 눌러서 전환할 수 있습니다.)

 

코드를 위로 좀 올려서 보니깐 우리가 목표해야할 코드가 보입니다. 보니깐 _vbaVarTstEq 라는 함수를 호출해서 무언가 비교하고 그 비교값이 EAX 에 리턴될 건데, EAX를 통째로 쓰는게 아닌 ax 레지스터만 test ax, ax 로 비교한 다음,  jz(jump equal, je랑 똑같은 명령어) 로 점프를 뛰고 있습니다. jz가 참이면 저 초록색 부분으로 점프 뛰는거고, 거짓이면 저 빨간 부분으로 점프뛰게 됩니다.

 

test 명령어

test 명령어를 분명 배운적이 있는데 잘 기억이 나지 않아서 찾아보았습니다.

우선 test 명령어는 인자(피연산자)가 2개인 명령어로 두 인자에 대한 AND 연산을 수행합니다.

예를 들어서 test arg1 arg2 를 실행하면 arg1과 arg2에 대한 AND 연산을 수행하게 되는것이죠.

 

보통은 test eax, eax 와 같이 같은 레지스터에 대해 연산을 수행하게 되는데요. 도대체 똑같은 레지스터 2개를 AND 연산하는게 무슨 의미가 있을까요? 어짜피 같은 레지스터라 AND 연산을 하면 자기 자신이 나올건데 말이죠.

 

기본적으로 test 명령어는 연산의 결과를 따로 저장하진 않고, 두 인자값을 비교 연산해서 결과값이 0인 경우에만 ZF(zero flag) 를 1로 세팅시킵니다. 이 ZF값을 기준으로 나중에 JMP 명령어를 수행할 수 있는것이구요.

 

test eax, eax 를 수행시키면 결과값이 0이 되는 경우는 eax가 0일때만 입니다. 왜냐면 0은 32비트 eax 레지스터에 00000000.. 으로 저장될것이고  00000.. 와 00000 을 AND 연산하면 0이 되니깐요. 0 AND 0 == 0

 

만약에 eax값이 1이면 00001 이고 00001 을 AND 연산하기 때문에 결과값이 1이 됩니다. 즉 test의 AND 연산 결과값이 0이 될 수 있는 경우는 레지스터 자신의 값이 0이 되는 경우밖에 없습니다.

 

test reg1, reg1 와 같은 명령어는 reg1이 0이 아닌지 맞는지 확인하기 위해 수행하는 명령어라고 보시면 됩니다. 이를 통해서 reg1이 0인지 체크한다음에, 0이면 ZF가 1로 설정되고, 이에 맞춰서 JZ(Jump Zero)가 수행될 수 있다고 보시면 됩니다.

 

대부분 test를 사용할 때 이런식으로 동일 레지스터에 대해 AND 연산을 해서 이 값이 0이 아닌지 체크하기 위해 많이 사용합니다. 그리고 당연하지만 test는 단일로 사용하지 않고 cmp 처럼 jump 계열 명령어와 함께 사용합니다.

 

결론 : test eax eax == eax가 0인지 체크하는 것

동일하게 위에서 사용한 test ax, ax 도 ax가 0인지 체크하는 것임.

 

그러니깐 위의 코드를 간단하게 이해해보면 우선 edx, eax 값을 스택 메모리에 Push 하고, 그 다음 vbaVarTstEq 라는 비교 함수로 추정되는 것을 Call 한다음에, 반환값이 0 또는 0이 아닌 값이 나올건데, 그것이 EAX에 저장될 것입니다.

어짜피 0을 32비트 eax 레지스터에 표현한다고 해도 모든 비트가 0일것이기 때문에 eax중에 절반, 즉 ax인 부분이 0인지만 체크해도 될 것입니다.

 

그렇게 해서 ax 레지스터 값이 0이면 (위에서 설명드린 test reg1, reg1 입니다.) jz를 통해 성공메세지가 아닌 쪽으로 분기하고, 만약에 ax 레지스터 값이 0이 아니라면 성공 메세지 쪽으로 분기하겠죠.

 

그러니깐 시리얼키가 맞아서 저 vbaVarTstEq 를 통해서 검사했을때 참값 (0이 아닌 값, 여기선 1로 가정) 이 나오면 성공 메세지가 뜨고, 아니면 실패메세지 쪽으로 분기하는게 아닌가 추정이 됩니다.

 

그리고 위에서 결과가 성공하던, 실패하던간에 또 다시 vbaVarTstNe 라는 함수를 호출한다음에 ax가 0인걸 체크해서 오류 메세지를 띄우거나 안띄우거나 하고 있습니다.

 

디버깅을 해보니깐 앞에서 실패하면 뒤의 결과에도 영향을 주어서 앞에서 실패 -> 뒤에서도 실패, 앞에서 성공 -> 뒤에서도 성공과 같은 흐름으로 진행이 되더라구요. 글로 풀어서 쓰려니깐 굉장히 복잡해지네요 -.-

 

뭐 정확히도 아니고 주저리 주저리 추측을 적어놓긴 했는데 확실한건 저기 vbaVarTstEq로 호출을 해서 비교를 수행하는 부분이 굉장히 중요해보인다는 겁니다. 이제 얼추 분석이 되었으니 프로그램 수정이 비교적 간편한 올리디버거로 수정을 해보겠습니다. 저기 call 부분을 클릭하면 왼쪽 아래 주소가 뜨는데 올리디버거를 열고 저 주소로 바로 이동해서 브레이크 포인트를 걸어줍시다. [찾을 주소 : 00403329]

 

=> 사실 IDA 에서도 바로 디버깅 하고 패치할 수도 있긴한데 우선은 이 문제는 올리디버거로 푸는게 정보 차원에서 더 도움을 많이 받을 수 있습니다. 스택 메모리에서 문자열 참조 주소가 아니라 문자열 내용을 그대로 보여주거든요... (물론 이건 제가 IDA 사용법을 잘 몰라서 그런것도 있지만 ㅠㅠ...)

 

올리디버거로 crackme 2번을 연다음 Ctrl + G 를 누르고 아까 찾아놨던 주소를 입력하면 바로 그 위치로 점프됩니다.

이제 저 CALL 위치에 브레이크 포인트를 걸어줍니다. [BP 거는법 단축키 = F2]

 

브레이크 포인트를 거셨으면 실행합니다.

 

이제 값을 입력하고 Check 를 누르는 순간 시리얼을 검사하는 부분에서 BP가 딱 걸리게 됩니다.

 

그렇죠? 지금 우리가 궁금한건 저 vbaVarTstEq 함수로 어떻게 비교를 수행하고 있는지 궁금합니다.

edx 와 eax 레지스터 값을 스택 메모리에 push해서 함수를 호출했는데요. F8로 저 부분을 실행하고 스택 메모리에 주목해봅니다.

 

F8로 비교 연산을 수행했고 이제 TEST AX, AX 를 다음에 실행할 차례인데요

 

스택 메모리에 뭔가 달라진건 없어보입니다만... 위에 올려서 값들을 잘 찾아보니깐 저희가 입력한 값과 어떤 문자열을 비교 하고 있습니다. 감이 오지만 아마 저 "AACDD0C9" 라는 문자열이 우리가 원하는 시리얼이 아닌가 싶네요.

 

디버깅을 중단하고 방금 찾아놓은 시리얼을 입력해봅니다.

 

정답을 찾은듯하네요 ㅋㅋ 그러나 사실 이문제는 시리얼키가 고정이 아니고 Name에 따라 여기서 작성해놓은 코드 알고리즘에 맞춰서 비밀번호를 동적으로 생성합니다.

 

그러니깐 Name이 달라질때마다 어떤 규칙에 의해 시리얼이 새로 생성된다는 것이죠.

이 자세한 부분의 내막은 나중에 시간이 나면 추가로 작성하도록 하겠습니다.

* 어셈블리 코드를 하나 하나씩 분석하면서 디버깅 해야 하므로 굉장히 귀찮습니다...

 

또한 추가적으로 스택 메모리를 따라가지 않고 하는 풀이는 crackme 1번에서도 했듯이 그냥 무조건 성공 지점 코드로 점프시키는 겁니다. 이 문제에서는 jz가 아니라 jmp 또는 jnz 로 성공위치로 점프시키고

 

또 밑에서 실패를 검사하는 부분에서도 실패 메세지가 아닌 부분으로 점프시키면 되겠습니다. 이러면 코드 생성 알고리즘이 뭐던간에 무조건 검사를 건너뛰어서 통과할 수 있습니다. 날먹 풀이

 

이 문제의 실제 규칙

생각을 좀 해본 결과 귀찮게 어셈블리어를 분석하지 않고도 이 문제가 비밀번호를 생성하는 규칙에 대해 알아낼 수 있었습니다.

 

위에서 이미 Name에 대한 결과값(Serial 값)을 보는 방법은 알았으니 각 Input에 대한 패턴을 살펴보니 다음과 같았습니다.

 

예를 들어서 aaaa에 대한 결과값은 C5C5C5C5 인데요. 이 값은 실제로 10진수를 기준으로 a에 대한 아스키 코드가 97인데 , 각 아스키코드 값을 구하고 거기에 100을 더한다음에 나오는 값 197 , 197 , 197 , 197 을 16진수로 변환해서 표현하는 것 이였습니다.

 

마찬가지로 File이라는 문자열도 각 Ascii 코드 값을 구한다음 10진수 100을 더해서 완성된 값을 16진수로 표현한 것이였구요..

 

실제로 위에서 이런 규칙대로 제품번호를 생성하는 코드가 IDA에서 분석된 위의 긴 코드에 포함이 되어 있을겁니다. 지금 술을 마시고 글을 쓰는거라.. 집중이 안되는군요. 여러분들은 열심히 찾으셔서 실력을 꼭 신장하시길 바랍니다. 죄송합니다 ㅎㅎ 

 

+ 2022-12-31 추가

정확히는 긴글자를 추가해도 앞의 4글자 (4바이트) 만 참고해서 시리얼 키를 생성합니다.

10글자 길이의 Name을 입력해도 앞의 4글자만 참고해서 Ascii 코드로 비밀번호를 만드네요.

 

그러니 Name으로 File을 입력하던, FileS를 입력하던 FileSS 를 입력하던 앞의 File만 참고하기 때문에 시리얼이 전부 같습니다. 4글자 이상 받는 이유가 이거였군요 -.-

 

CrackMe 2번 생성기

 

 

 

위는 제가 HTML + JS로 심심해서 작성한 웹에서 CrackMe 2번 정답을 만들어주는 폼입니다. Name 쪽에 이름을 입력하면 Result에서 자동으로 크랙미 2번에 필요한 시리얼 키를 생성해줍니다.

티스토리에 삽입하면 2번째 접속부터 스크립트가 날라가버리네요 ;; 여기선 작동을 제대로 안해서 아래쪽에 HTML 코드도 첨부합니다. 복사해서 HTML로 저장하고 열어볼 수 있습니다.

 

<!-- 입력 받고 버튼을 누르면 10을 출력하는 HTML 코드 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Insert title here</title>
  </head>
  <body>
    <script>
      function convert() {
        //문자열을 입력받는다
        const input = document.getElementById("name").value;
        const length = input.length > 4 ? 4 : input.length;
        //문자열을 4글자 보면서 아스키코드를 읽어서 배열에 저장한다
        let ascii = [];
        for (let i = 0; i < length; i++) {
          ascii.push(input.charCodeAt(i));
        }

        for (let i = 0; i < ascii.length; i++) {
          ascii[i] += 100;
        }

        //배열을 16진수 대문자 문자열로 변환한다.
        let result = "";
        for (let i = 0; i < ascii.length; i++) {
          result += ascii[i].toString(16).toUpperCase();
        }

        //결과를 출력한다.
        document.getElementById("result").value = result;
      }
    </script>

    <input type="text" placeholder="Name" id="name" onkeyup="convert()" />
    <br />
    <input
      type="text"
      placeholder="Result(Serial)"
      id="result"
      readonly="true"
    />
  </body>
</html>

 

출처(참고문헌)

https://yokang90.tistory.com/8

https://posix.tistory.com/78

https://itsaessak.tistory.com/302

https://tyeolrik.github.io/assembly/2017/02/25/Assembly-Command.html

SNS 공유하기
네이버밴드
카카오톡
페이스북
X(트위터)

최근글
인기글
이모티콘창 닫기
울음
안녕
감사
당황
피폐