오늘은 오랜만에 옛날 GWBASIC 추억 얘기를 또 늘어놓아 보겠다. 예전에 했을 법도 해 보이는데 여러 키워드로 검색을 해 보니 안 한 것 같다. 베이직 얘기를 전문적으로 하는 건 한 2년 만의 일이다.
GWBASIC은 초딩이었던 본인을 프로그래밍의 세계로 이끈 추억의 장난감이다.
본인은 어릴 때부터 컴퓨터가 다른 전자 기기와는 뭔가 차원이 다른 대단한 물건이라는 걸 실감했다.
텔레비전은 오로지 일방적으로 전달만 하는 물건인 반면, 컴퓨터는 내가 직접 명령을 내려서 모니터에 찍히는 글자의 색깔을 바꿀 수 있고, 내가 원하는 화면을 구성할 수 있고, 그림도 그릴 수 있고 소리도 내고 파일로부터 정보를 읽고 쓰면서 뭔가 '나만의 능동적인 세계'를 표현할 수 있기 때문이다.
본인은 딱히 머리가 빨리빨리 잘 돌아간다거나 수학 덕후 최적화 덕후 기질이 있지는 않았다. 단지, 새로운 세계를 표현하는 것 자체에 집착했다. 그래서 정보 올림피아드도 경시에서는 영 재미를 못 보고 그 대신 공모 부문에서 다 입상했다.
GWBASIC은 결과를 즉시 확인할 수 있는 대화식 구조라는 게 굉장히 인상적이다. 행번호에 GOTO문 남발은 굉장히 기괴하고 거추장스러운 개념이긴 하지만, 행번호가 없는 명령은 곧장 실행되고, 행번호가 붙은 명령은 메모리에 등록되어서 나중에 행번호 순으로 한꺼번에 실행된다는 그런 발상은... 참 아무나 할 수 있는 게 아닌 듯하다. RUN, MERGE, DELETE, CHAIN처럼 기억된 프로그램 자체를 확장하거나 바꾸는 명령이 있다는 것도 기괴하고 말이다.
GWBASIC에는 프로그램을 불러오거나 저장하는 명령으로 LOAD, SAVE가 있다. 그런데 GWBASIC은 좀 특이한 게, 여느 프로그래밍 툴처럼 소스 코드를 plain text로 저장하는 게 아니라 내부 바이너리 바이트코드로 저장하는 게 기본 옵션이다. 바이트코드는 같은 소스를 저장했을 때 plain text보다 크기가 작고, 로딩/저장 속도도 더 빠르다는 이점이 있다.
세월이 워낙 많이 흘렀기 때문에 지금은 그 바이트코드의 포맷이 다 알려져서 인터넷에 굴러다닌다. 포맷이 정식으로 공개된 건지 아니면 해커들이 리버스 엔지니어링을 해서 알아낸 건지는 잘 모르겠다.
다른 프로그램에서도 소스 코드를 볼 수 있게 저장하려면 SAVE"파일이름", A라고 뒤에 A를 덧붙여야 한다.
그리고 한편으로 P라는 옵션이 있다. P 옵션은 A와는 반대로 소스 코드를 내부 바이너리 코드로 저장하되 그걸 XOR 기반의 간단한 암호화까지 해서 저장한다.
P 옵션으로 저장된 소스는 불러와서 실행은 가능하지만, LIST로 내용을 열람하거나 코드를 수정할 수 없다. 따라서 비록 GWBASIC에 소스 코드를 EXE로 컴파일하는 기능은 없지만, 다 만든 프로그램을 남에게 인계할 때는 P 옵션으로 저장된 프로그램 파일을 전해 주면 소스 코드 유출을 막을 수 있다. 이론적으로는 말이다.
그러나 그 시절의 GWBASIC에 무슨 전문적인 코드 암호화나 난독화 기능이 있었던 것도 아닌데, 겨우 그 정도의 허접한 보호 기능은 당연히 뚫리고도 남았다.
P 옵션의 암호화 방식도 다 알려져 있고, GWBASIC의 버그를 이용하여 보호 기능 자체를 뚫어 버리는 방법도 존재한다. 이것은 아주 오래 전부터 베이직 프로그래머들 사이에 나돌던 공공연한 비밀 테크닉이었다.
자, 0xFF 문자 2개로 구성된 2바이트짜리 파일(가칭 UN.BAS)을 만든다. 간단하지만 키보드로 바로 입력할 수 없는 문자이긴 한데.. 헥사 에디터를 쓰든지 아니면 GWBASIC 자체를 이용해서 이런 파일을 생성하는 프로그램을 짜서 돌려도 된다.
그 뒤, P 옵션이 붙은 임의의 소스를 LOAD한 뒤, 그 상태에서 UN.BAS를 뒤이어 LOAD하고 나면..
기존 소스의 프로텍션이 풀리고 LIST 열람이 가능해지는 걸 볼 수 있다. 마법과 같은 일이 벌어진다.
그 뿐만이 아니다.
NEW를 입력해서 기억되어 있던 소스를 다 지운 뒤에도 UN.BAS를 LOAD하면.. 방금 지워졌던 소스가 되살아난다.
이게 도대체 어째서 가능할까? (UN.BAS는 0xFF 0xFF일 뿐, 저 소스 코드 자체가 들어있는 거 절대 아님.. -_-)
사실, GWBASIC은 내부적으로 기억하고 있는 바이트코드를 디코딩해서 LIST로 출력하고 소스 코드를 고치는 것을 허용할지 여부를 간단한 boolean 변수 하나로만 판단하는 듯하다. 저장할 때 XOR 인코딩 여부 역시 그 변수로 판단하며, 불러올 때의 XOR 디코딩 여부는 파일 앞부분에 있는 헤더로 판단한다.
그러니, 그 메모리 주소의 값만 바꿔 버리면 프로텍션을 곧바로 풀 수 있다. GWBASIC의 보안 체계는 근본적으로 허술했던 것이다.
그리고 GWBASIC의 고유 파일 포맷에 따르면, 프로텍션이 걸리지 않은 파일은 0xFF로 시작하고, 걸린 파일은 0xFE로 시작한다.
그러므로 0xFF 0xFF 2바이트짜리 파일은 GWBASIC으로 하여금 프로텍션 플래그는 해제하지만 그 뒤에 거의 즉시 파일이 끝나 버리기 때문에 메모리 상의 다른 소스 코드는 건드리지 않는 역할을 하는 듯하다.
원래는 그렇게 파일이 갑작스럽게 끝났을 때의 처리를 GWBASIC이 깔끔하게 해야 하지만 그렇지 못하기 때문에 졸지에 프로텍션만 풀어 버리는 게 가능한 듯하다.
NEW를 한 것까지 어떻게 undo를 하는지까지는 잘 모르겠지만 말이다.
아무튼, 이런 게 오늘날의 소프트웨어 보안 용어로 치자면 일종의 버그이고 exploit이다.
만약 GWBASIC이 Windows, Office, Visual Studio처럼 오늘날까지 살아 있는 제품이고 GWBASIC이 세계 기업들의 돈줄을 좌지우지하는 솔루션이었다면 이건 뭐 당장 긴급 업데이트/패치감이 됐을 것이다. 회사의 자산인 소스 코드가 간단한 해킹으로 죄다 유출되게 생겼으니 말이다.
업데이트 명분으로 맨날 귀가 따갑도록 나오는 “악의적으로 조작된 파일을 열 경우 임의의 코드가 실행... 까지는 아니어도 뭐가 어찌될 수 있는 보안 취약점이 Microsoft 모 제품에서 발견되었습니다” 문구가 가리키는 게 바로 이런 거다.
자그맣게 조작된 파일이 GWBASIC의 저장 프로텍션을 풀어 버리니, 이 꼼수가 보안의 관점에서 오늘날 시사하는 바가 크다고 생각되어서 문득 글을 써 보았다.
옛날에, 286 XT/AT를 갖고 '교육용 컴퓨터' 이러던 시절에는 단색 그래픽 모드에서 동작하는 여러 '교육용 소프트웨어'들도 있었다. CAI라고 들어 보셨는가?
'약수와 배수', '컴퓨터 개론' 같은 타이틀이 있었는데, 개중에는 정말 놀랍게도 GWBASIC으로 개발된 것도 있었다.
물론 런타임인 GWBASIC.EXE와 소스 코드들은 다 파일 이름과 확장자를 교묘하게 바꿨고, 실행은 CAI.BAT라는 파일로 했다.
소스 코드를 열어 보니 당연히 프로텍션이 걸려 있었다. 그러나 본인은 저 테크닉을 이용하여 프로텍션을 풀고 코드를 열람해 보기도 했다. 분량이 상당히 방대했으며 지금 다시 봤으면 여러 재미있는 아이디어들을 발견했을 법도 해 보지만, 본인은 그 당시엔 프로그래밍 실력의 부족으로 인해 그다지 충분한 재미를 못 봤다.
그 느리고 허접한 GWBASIC으로 자체 한글 출력과 그것도 모자라서 입력까지 구현했는데 과연 어떻게 구현했을지가 궁금해지지 않는가?
GWBASIC의 후신인 QBasic이야 고릴라 내지 NIBBLES 같은 예제 게임 프로그램이 MS-DOS 5.0에 같이 곁들여 제공되기도 했다.
순수 GWBASIC으로 근성으로 만들어진 프로그램은? 먼 옛날에 무슨 허접한 자동차 경주 게임 같은 걸 본 게 마지막이다. 각 스테이지의 이름은 태양계의 행성 이름이었는데... 기억하는 분이 있으려나 모르겠다.
상용 제품인 QuickBasic도 GWBASIC의 전통을 이어받아 소스 코드를 자기 고유 포맷으로 저장하는 기능이 있었다. 물론 GWBASIC과 호환되는 포맷은 아니었다. 그리고 축소판인 QBasic은 그런 기능이 없다.
지금은 '큐베'라고 하면 음악 DAW 프로그램인 큐베이스(Cubase)가 먼저 떠오르는 세상이 됐으니 이것도 격세지감이다.
* 그리고 GWBASIC과 관련된 추가 여담.
IBM PC(=도스)용으로 이식된 GWBASIC이야 기본 프롬프트가 Ok이지만, 더 구닥다리 8비트 롬 베이직 같은 걸 보면 프롬프트가 READY인 경우가 있다. 빌 게이츠 아저씨가 GWBASIC을 최초로 만들 때 원래 의도했던 메시지는 ready였다고 한다.
그 사고방식은 오늘날 같은 Windows+GUI 시대에까지도 남아 있다. Excel이나 Visual Studio, 심지어 MFC 기본 어플이.. 내부적으로 더 처리할 메시지가 없이 사용자의 입력만 기다리는 idle 상태로 진입했을 때 아래의 상태 표시줄에 나타나는 메시지는 바로 Ready이며, 우리말로는 그냥 '준비'이다.
그랬는데 ready가 ok로 바뀐 이유는.. 메모리를 단 3 바이트라도 더 확보하기 위해서였다고 한다. 뿌우우... 묵념.
단, Ok도 다 대문자 OK도 아니고, 대문자 O에 소문자 k로 정해진 이유는 본인으로서는 지금도 알 길이 없다.
Posted by 사무엘