macOS Firmware 패스워드 삭제 스크립트

애플스크립트를 이용한 EFI 패스워드 삭제 스크립트

지난번, 실수로 잘못 걸은 EFI 패스워드는 여전히 삭제하지 못하고 있는 상황이다.
이런 상황이긴 하지만.
과정에서 만든 스크립트 하나를 공개하기로 한다.

단순한 비밀번호나, 알 수 없는 오타를 쳐서 돌이킬 수 없는 상황에 빠졌을 때.
시간을 들여 EFI패스워드를 삭제할 수 있게 해 주는 스크립트다.
(약간 어렵게 느껴질 것이다, 모르면 커뮤니티에 들고가서 물어봐라)

이 스크립트는 인텔칩을 사용하며,
애플T2칩을 사용하지 않는 모든 맥킨토시에서 사용할 수 있다.

아래 스크립트의 사용순서는 다음과 같다.

  1. 스팟라잇 혹은 Applications > 유틸리티에서 터미널 (Terminal)을 켠다.
  2. 터미널에서 sudo su 라는 명령어를 친다.
  3. macOS 비밀번호를 입력한다.(맥 켜자마자 ID와 같이 입력하는 그 PW말이다.)
  4. 터미널 시작이 Sh-3.2#으로 바뀌었다면 성공이다.
  5. 스팟라잇 혹은 Applications > 유틸리티에서 스크립트 편집기 (Script Editor)을 켠다.
  6. 아래 박스 안의 코드를 복사해 붙여넣고 저장하라.
  7. 스크립트 편집기 위의 삼각형 버튼(플레이버튼 같은 거)을 눌러서 시작하라.
  8. 1회 49667번 반복한다. 한 차례 반복후, 아래 스크린샷을 참고하여 상태를 확인해라. (아래 다시 설명)
  9. 암호해제에 실패했다면 아래 스크립트에 써 있는대로 다음 순번을 설정후 저장하고 스크립트 편집기 (Script Editor)를 닫아라.
  10. 터미널도 종료하고 맥을 재부팅해라.
  11. 맥을 다시 켰다면 1번부터 다시 반복한다.
  12. 성공할때까지 한다.

아마도, 보통 아래 문자 이외에 사용하지 않을 것이다.

abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
`1234567890-=[]\;',./
~!@#$%^&*()_+{}|:"<>?

-- 문자 Set 이른바 배열이다. (수학이나 컴퓨터공학의 배열 말이다.)

-- a_list라는 set 다음에 to 있고, 거기서부터 {}(중괄호) 하나의 꾸러미를 만들고 있다.

-- 꾸러미 안에 따옴표 안에 글자부터, 문장까지 작성하고, 따옴표 사이에 (,) 콤마로 다음 글자를 나간다.

-- , \ (역슬래시) " ( 따옴표) 프로그래밍 세계에서 특수문자로 취급해줘야 하는 글자들이다.

-- 따라서, 역슬래시를 하나 붙여 특수문자임을 표시한다. 역슬래시는 = \\ 따옴표 = \" 이렇게 말이다.

-- 스크립트는 최대 13가지 패턴으로 나눌 있을 것을 상정하여 만든 것이다.


-- 스크립트를 사용할 유저는 리스트(list) 꾸러미를 반드시 수정하라.


-- a부터 d 리스트는 글자 1개의 경우로 소문자, 대문자, 숫자, shift 누른 상태에서의 숫자와 특수문자다.

set a_list to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ""}

set b_list to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", ""}

set c_list to {"`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", ""}

set d_list to {"~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "{", "}", "|", ":", "\"", "<", ">", "?", ""}


-- e 리스트는 a부터 d 모두 한줄에 담은 리스트이다.

-- 실제로 이렇게 일은 없을 것이며, 없어야 한다. (왜냐하면 시간이 많이 걸린다)

-- 그냥 이렇게 있다는 보여주는 예제이다.

set e_list to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "{", "}", "|", ":", "\"", "<", ">", "?", " ", ""}


-- f부터 m리스트는 2 이상의 글자를 담은 예제이다.

-- 예를 들어 비번이 q1w2e3r4이라고 가정하자.

-- qwer 확실하거나 혹은 기억하는데. 숫자인지 특수문자인지 모를 경우가 있다.

-- 그렇다면 가지 방법이 있다.

-- a, c, e, g 리스트에 각각 "q" "w" "e" "r" 넣는 거다.

-- 그리고 b리스트에 "1","!".

-- d 리스트에 "2","@" 넣고.

-- f 리스트에 "3","#" 넣고.

-- h 리스트에 "4","$" 넣는거다.

-- 그리고 i, j, k, l, m 모두 큰따옴표 2개만 넣어 "" <- 이렇게 빈칸으로 만들어 두고 돌리는 방법이다.

-- 또다른 방법은 이런 있다.

-- a리스트에 "q1w2e3r4","q!w@e#r$" 이렇게 2개의 문장만 넣고 b부터 m까지 모든 리스트를 빈칸으로 만드는 것이다.

-- 자신의 비밀번호 패턴을 기억해 내어 조합을 만들어 써라.

set f_list to {"aa", "bb", "cc", "dd", "ee", "ff", "  ", ""}

set g_list to {"a1", "b2", "c3", "d4", "e5", "f6", "g7", ""}

set h_list to {"A!", "B@", "C#", "D$", "E\\", "F\"", ""}

set i_list to {"a-b c", "c\\d\"-e", "fat-32", ""}

set j_list to {"QhdldQhdld", "EhdldEhdld", "BlaBla", "MolooMoloo", ""}

set k_list to {"{a!", "]b%", "\\c(", "\"d_", ""}

set l_list to {" ", ""}

set m_list to {"zfs", "ntfs", "apfs", "ufs", "fat", "ex-fat", ""}


-- Set 문자리스트에 몇개의 문자 혹은 단어의 묶음(큰따옴표로 묶은 것들) 있는지는 자동으로 계산한다.

-- 계산된 값은 문자리스트의 count 축약하여 의미하는 cnt안에 자동으로 담긴다.

-- 예를들면 아래 set a_cnt에는 a_list 들어있는 큰따옴표 모음의 전체 갯수가 자동으로 담긴다.

-- 부분은 절대로 건들지 마라.

set a_cnt to length of a_list

set b_cnt to length of b_list

set c_cnt to length of c_list

set d_cnt to length of d_list

set e_cnt to length of e_list

set f_cnt to length of f_list

set g_cnt to length of g_list

set h_cnt to length of h_list

set i_cnt to length of i_list

set j_cnt to length of j_list

set k_cnt to length of k_list

set l_cnt to length of l_list

set m_cnt to length of m_list


-- 이것들은 출력할 문자의 중복을 검토하기 위한 것이다.

-- 부분은 절대로 건들지 마라.

set a_count to 0

set b_count to 0

set c_count to 0

set d_count to 0

set e_count to 0

set f_count to 0

set g_count to 0

set h_count to 0

set i_count to 0

set j_count to 0

set k_count to 0

set l_count to 0


-- 스크립트는 list 큰따옴표안의 글자 혹은 문장을, a부터 m 순서로 1세트씩 불러서 비밀번호를 조합한다.

-- 따라서 한번에 같은 글자가 2개만 나오도록 설정하고 있다. (아래에서 수정할 있다)

-- 스크립트가 시동하자마자 같은 글자 혹은 문장이 2 이상 나올 가능성이 있다면, 아래 설정으로 회피할 있다.

-- m_id 1 쓴다.

-- l_id까지 1 쓴다.

-- k_id 2 쓴다.

-- 이렇게 아래에서 2개의 리스트마다 +1 하는 것이다.

-- 처음부터 겹칠 일이 없다면 모두 1 써도 된다.


-- 스크립트를 사용할 유저는 리스트(list) 꾸러미 패턴에 맞춰 수정하라.

-- (물론 하고 그냥 모두 1 두고 시작해도 된다. 단지 엄청나게 시간이 걸릴 뿐이다)

-- 바로 아래 다시 설명하지만, 스크립트는 49667회만 반복한다.

-- 49667회중에 성공하면 좋겠지만, 실패하면 이어서 작업해야 것이다.

-- 이때, 여기 숫자를 재설정해주면 이어서 49667 다시 반복작업을 준다.

-- 가장 마지막 줄의 결과를 여기에 반영하여 작업을 이어나간다.

set a_id to 6

set b_id to 6

set c_id to 5

set d_id to 5

set e_id to 4

set f_id to 4

set g_id to 3

set h_id to 3

set i_id to 2

set j_id to 2

set k_id to 1

set l_id to 1

set m_id to 1


-- 애플스크립트는 불행히도 사용할수록 RAM 데이터가 쌓인다.

-- 따라서 루프(반복)문으로 만들어 작업을 나눠서 하는 것이다.

-- 초기값은 당연히 0이고, 49667 반복하고 종료된다.

-- 부분은 절대로 건들지 마라.

set loop_cnt to 0

set loop_limit to 49667


-- 비밀번호를 담기 위한 공간인데...

-- 사실 쓸모없다.

-- (사실, 스크립트에서는 심플하게 코드를 짜도 된다.)

-- (그러나, 스크립트는 계속 개량하여 쓰던 코드라 남아있게 되었다)

-- (따라서) 부분은 절대로 건들지 마라.

set efi_pw to ""


-- 부분은 절대로 건들지 마라.

repeat with m_lp from m_id to m_cnt

repeat with l_lp from l_id to l_cnt

repeat with k_lp from k_id to k_cnt

repeat with j_lp from j_id to j_cnt

repeat with i_lp from i_id to i_cnt

repeat with h_lp from h_id to h_cnt

repeat with g_lp from g_id to g_cnt

repeat with f_lp from f_id to f_cnt

repeat with e_lp from e_id to e_cnt

repeat with d_lp from d_id to d_cnt

repeat with c_lp from c_id to c_cnt

repeat with b_lp from b_id to b_cnt

repeat with a_lp from a_id to a_cnt

-- a 중복 검토.

-- 여기 a에서부터 m까지 절대로 건들지 마라.

if ((item a_lp of a_list) = (item b_lp of b_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item c_lp of c_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item d_lp of d_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item e_lp of e_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item f_lp of f_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item g_lp of g_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item h_lp of h_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item i_lp of i_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item j_lp of j_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item k_lp of k_list)) then

set a_count to a_count + 1

end if

if ((item a_lp of a_list) = (item l_lp of l_list)) then

set a_count to a_count + 1

end if

-- b

if ((item b_lp of b_list) = (item a_lp of a_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item c_lp of c_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item d_lp of d_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item e_lp of e_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item f_lp of f_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item g_lp of g_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item h_lp of h_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item i_lp of i_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item j_lp of j_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item k_lp of k_list)) then

set b_count to b_count + 1

end if

if ((item b_lp of b_list) = (item l_lp of l_list)) then

set b_count to b_count + 1

end if

-- c

if ((item c_lp of c_list) = (item b_lp of b_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item a_lp of a_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item d_lp of d_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item e_lp of e_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item f_lp of f_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item g_lp of g_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item h_lp of h_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item i_lp of i_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item j_lp of j_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item k_lp of k_list)) then

set c_count to c_count + 1

end if

if ((item c_lp of c_list) = (item l_lp of l_list)) then

set c_count to c_count + 1

end if

-- d

if ((item d_lp of d_list) = (item b_lp of b_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item c_lp of c_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item a_lp of a_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item e_lp of e_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item f_lp of f_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item g_lp of g_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item h_lp of h_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item i_lp of i_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item j_lp of j_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item k_lp of k_list)) then

set d_count to d_count + 1

end if

if ((item d_lp of d_list) = (item l_lp of l_list)) then

set d_count to d_count + 1

end if

-- e

if ((item e_lp of e_list) = (item b_lp of b_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item c_lp of c_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item d_lp of d_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item a_lp of a_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item f_lp of f_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item g_lp of g_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item h_lp of h_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item i_lp of i_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item j_lp of j_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item k_lp of k_list)) then

set e_count to e_count + 1

end if

if ((item e_lp of e_list) = (item l_lp of l_list)) then

set e_count to e_count + 1

end if

-- f

if ((item f_lp of f_list) = (item b_lp of b_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item c_lp of c_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item d_lp of d_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item e_lp of e_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item a_lp of a_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item g_lp of g_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item h_lp of h_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item i_lp of i_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item j_lp of j_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item k_lp of k_list)) then

set f_count to f_count + 1

end if

if ((item f_lp of f_list) = (item l_lp of l_list)) then

set f_count to f_count + 1

end if

-- g

if ((item g_lp of g_list) = (item b_lp of b_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item c_lp of c_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item d_lp of d_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item e_lp of e_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item f_lp of f_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item a_lp of a_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item h_lp of h_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item i_lp of i_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item j_lp of j_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item k_lp of k_list)) then

set g_count to g_count + 1

end if

if ((item g_lp of g_list) = (item l_lp of l_list)) then

set g_count to g_count + 1

end if

-- h

if ((item h_lp of h_list) = (item b_lp of b_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item c_lp of c_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item d_lp of d_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item e_lp of e_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item f_lp of f_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item g_lp of g_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item a_lp of a_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item i_lp of i_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item j_lp of j_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item k_lp of k_list)) then

set h_count to h_count + 1

end if

if ((item h_lp of h_list) = (item l_lp of l_list)) then

set h_count to h_count + 1

end if

-- i

if ((item i_lp of i_list) = (item b_lp of b_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item c_lp of c_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item d_lp of d_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item e_lp of e_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item f_lp of f_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item g_lp of g_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item h_lp of h_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item a_lp of a_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item j_lp of j_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item k_lp of k_list)) then

set i_count to i_count + 1

end if

if ((item i_lp of i_list) = (item l_lp of l_list)) then

set i_count to i_count + 1

end if

-- j

if ((item j_lp of j_list) = (item b_lp of b_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item c_lp of c_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item d_lp of d_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item e_lp of e_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item f_lp of f_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item g_lp of g_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item h_lp of h_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item i_lp of i_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item a_lp of a_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item k_lp of k_list)) then

set j_count to j_count + 1

end if

if ((item j_lp of j_list) = (item l_lp of l_list)) then

set j_count to j_count + 1

end if

-- k

if ((item k_lp of k_list) = (item b_lp of b_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item c_lp of c_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item d_lp of d_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item e_lp of e_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item f_lp of f_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item g_lp of g_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item h_lp of h_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item i_lp of i_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item j_lp of j_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item a_lp of a_list)) then

set k_count to k_count + 1

end if

if ((item k_lp of k_list) = (item l_lp of l_list)) then

set k_count to k_count + 1

end if

-- l

if ((item l_lp of l_list) = (item a_lp of a_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item b_lp of b_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item c_lp of c_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item d_lp of d_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item e_lp of e_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item f_lp of f_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item g_lp of g_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item h_lp of h_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item i_lp of i_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item j_lp of j_list)) then

set l_count to l_count + 1

end if

if ((item l_lp of l_list) = (item k_lp of k_list)) then

set l_count to l_count + 1

end if

-- 여기 if()라고 있는 부분은 엑셀의 if문과 같은 기능을 한다.

-- 스크립트에서는 위에서 처럼 모든 문자 혹은 문장을 1개씩 2 중복하여 출력하는 허락하고 있다.

-- 위에서 쓴것처럼 자신의 비밀번호 패턴에 따라서 어떤 문자 혹은 문장이 2 이상 반복해야 한다면?

-- ≤ 1 부분을 ≤ 2 혹은 ≤ 3 같이 바꿔줘라.

-- 자신의 비밀번호 위의 문자 리스트 패턴에 맞춰 부분을 반드시 수정하라.

if ((a_count ≤ 1) and (b_count ≤ 1) and (c_count ≤ 1) and (d_count ≤ 1) and (e_count ≤ 1) and (f_count ≤ 1) and (g_count ≤ 1) and (h_count ≤ 1) and (i_count ≤ 1) and (j_count ≤ 1) and (k_count ≤ 1) and (l_count ≤ 1)) then

-- tell 어쩌구 부분은 터미널에 비밀번호를 대입하는 기능을 담당한다.

-- 절대로 건들지 마라.

tell application "Terminal"

set W to (the first window whose tty of tab 1 contains "ttys000")

delay (random number from 0.27 to 0.43)

do script "firmwarepasswd -delete" in W

delay (random number from 0.01 to 0.1)

set efi_pw to ((item a_lp of a_list) & (item b_lp of b_list) & (item c_lp of c_list) & (item d_lp of d_list) & (item e_lp of e_list) & (item f_lp of f_list) & (item g_lp of g_list) & (item h_lp of h_list) & (item i_lp of i_list) & (item j_lp of j_list) & (item k_lp of k_list) & (item l_lp of l_list) & (item m_lp of m_list) & "\n")

do script efi_pw in W

end tell

set efi_pw to ""

set loop_cnt to loop_cnt + 1

end if

-- if문이 종료되는 구간이다.

-- if문이 끝나면 반드시 1. 현재까지의 반복횟수가 49667 이하인지 체크한다.

-- 만약 49667회라면 스크립트는 루프(반복) 중단한다.

if (loop_cntloop_limit) then exit repeat

-- 만약 루프(반복) 계속된다면 중복체크를 0으로 리셋해준다.

-- 부분은 절대로 건들지 마라.

set a_count to 0

set b_count to 0

set c_count to 0

set d_count to 0

set e_count to 0

set f_count to 0

set g_count to 0

set h_count to 0

set i_count to 0

set j_count to 0

set k_count to 0

set l_count to 0

-- 여기부터 마지막 end repeat까지 절대로 건들지 마라.

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat

if (loop_cntloop_limit) then exit repeat

end repeat


-- 49667 루프(반복) 돌면, 종료 시점의 리스트의 현재 글자를 남겨준다.

-- 다음 루프(반복) 글자에 해당하는 위치를 세어서 위의 a_id부터 m_id 숫자를 갱신해라.

-- 코드는 절대로 건들지 마라.

set theDialogText to return & "a:" & (item a_lp of a_list) & ", b:" & (item b_lp of b_list) & ", c:" & (item c_lp of c_list) & ", d:" & (item d_lp of d_list) & ", e:" & (item e_lp of e_list) & ", f:" & (item f_lp of f_list) & ", g:" & (item g_lp of g_list) & ", h:" & (item h_lp of h_list) & ", i:" & (item i_lp of i_list) & ", j:" & (item j_lp of j_list) & ", k:" & (item k_lp of k_list) & ", l:" & (item l_lp of l_list) & ", m:" & (item m_lp of m_list) & "\n" & "loop count:" & loop_cnt & "."

이 스크립트는 보면 알 수 있듯이 초심자에게는 매우 어렵고 복잡해 보이며.
프로그램 유경험자에게도 애플스크립트가 익숙하지 않다면,
대충 뭔지는 알겠지만. 역시 어려울 수 있다.

그러나, 이 방식은 터미널을 이용해 EFI패스워드를 해제하는
소프트웨어 적으로 가장 안전하고 안정적인 방법이다.
(라는 게 내가 얻은 결론이다. 물론 시간도 많이 필요하다!)

스크립트를 더 세련되게 만들어, 터미널에서 나오는 문자를 파악해 성공-실패를 확인하고.
루프(반복)을 중단하게 할 수도 있겠지만.
애플스크립트를 이용한 방법은 현재 중단한 상태다.
딱히 수정할 이유도 없기도 한데. 그 이유는 아래 스크린샷을 통해 설명한다.

패스워드 삭제에 성공한 상황

패스워드가 삭제되면, "Password Removed."가 뜨고,
그 이후로 루프(반복) 삭제 명령이 주입돼도,
가장 먼저 "No firmware password set"가 뜨면서 비밀번호를 먹지 않게 된다.

다음으로 패스워드가 삭제되거나,
삭제되지 않았어도 루프(반복)이 종료되면 보이는 변화를 살펴보자.

패스워드 삭제 확인

먼저 터미널을 통해 확인할 수 있는 명령어가 있다.

firmwarepasswd -check

그 아래 "Password Enabled: No" 가 반환된 모습이 보인다.
EFI에 설정된 패스워드가 없다는 뜻이다.

이어서 뒤에 있는 스크립트 에디터를 보자.
스크린샷 하단에 보면 Result라고 된 부분 아래에,
a부터 m까지 각 문자 리스트에서 추출되어 입력된 마지막 패스워드가 보인다.

이 스크린샷은 애초에 패스워드를 알고 있어서 5000회만에 비밀번호가 나왔지만.
실제 비밀번호를 잃어버린 경우 결코 단시간에 결과가 나오지 않는다.

이 비밀번호 체크가 CPU와 RAM과 SSD 사이에서 이뤄지는 게 아니라
통신이라는 방식으로 이뤄지다 보니. 터미널에 걸리는 부하도 무시할 수가 없다.
이것이 루프 카운트를 49667회로 한정한 이유다.
(49667회는 가장 안전하고 안정된 통신횟수라 정한 것이다)

터미널을 꺼도, 이 부하는 커널이라고 부르는
macOS의 핵심부에 남아있기 때문에
다음회 루프 (반복)은 반드시 재부팅후 진행하라는 것이다.
(잊어버릴 수 있으니 루프 종료 직후에 스크립트의 문자열 번호를 수정해 두라는 거다)

이 방법은 나중에 다듬어 Github에 재공개할지 그냥 이대로 둘지 하겠지만.
아무튼, EFI비번을 알 수 없어 고통받고 있는 사람들에게
비번의 전체 길이와 대략적인 문자열만 알고 있다면.
혼자서도 비번을 풀 수 있는 좋은 수단이 되어 줄 것이다.

그런 입장에 있는 사람은 극히 소수겠지만,
그런 이들에게 부디 유용하게 쓰이길 바라며 여기 우선 공개한다.

Next Post Previous Post
No Comment
Add Comment
comment url