v3 = argc;
VirtualProtect(sub_140001000, 0x10ui64, 0x40u, &flOldProtect);
*sub_140001000 ^= v3;
VirtualProtect(sub_140001000, 0x10ui64, flOldProtect, &flOldProtect);
v4 = sub_140001000();
v5 = &unk_1400032B0; // yes
if ( v4 != 10 )
v5 = &unk_1400032B4; // no
sub_1400010B0(std::cout, v5);
return 0;
sub_140001000과 argc를 xor한 뒤 호출한다.
결과가 10이여야 한다.
cmp [rcx], bl // 38 19
retn // c3
sub_140001000의 바이트는 0x1938이다.
호출 결과가 10이 되려면 al을 10으로 설정해야 한다.
mov al,a // b0 0a
ret // c3
따라서 0x1938 ^ argc = 0xab0 이 돼야 한다.
std::cout << (0xab0 ^ 0x1938);
>> 5000
계산해보면 argc는 5000이여야 한다.
pwntools를 이용하여 argv를 설정할 수 있다.
from pwn import *
argv = []
for i in range(5000):
argv.append('1')
p = process(executable=".\\easy crackme.exe", argv=argv)
print(p.recv())
p.close()
출력
[x] Starting local process '.\\easy crackme.exe'
[+] Starting local process '.\\easy crackme.exe': pid 11900
[*] Process '.\\easy crackme.exe' stopped with exit code 0 (pid 11900)
b'yes'
sub_140001010(std::cin, Buffer, envp);
v3 = Buffer;
if ( v10 > 0xF )
v3 = Buffer[0];
sscanf(v3, "%d", &v7);
if ( v7 == 10 )
v4 = "!crackme!";
else
v4 = " ohh nooo...";
v5 = sub_140001270(std::cout, v4);
입력을 받고 숫자로 변환한 뒤 10인지 확인한다.
print('type password: ')
-- get input
local pw = io.read()
-- input to lua script
local f = load(pw)
local password
-- 1. check if input is can be lua script
if f then
-- pass anony function into input function, and call it.
local r = f(function() password = PASSWORD() end)
-- 2. check input function return
if r == 'load_pw' then
-- 3. check if password is set (it set on anony function)
if password then
print('password: ' .. password)
else
print('password is not set')
end
else
print('wrong input data')
end
else
print('wrong input type')
end
return 'load_pw'를 넣으면 넘어 갈 수 있다.
출력
type password:
password is not set
... 키워드를 이용해서 매개 변수에 접근할 수 있다.
type password:
local fn = ... print(fn)
function: 00000283DBC0CA90
wrong input data
매개 변수로 들어온 함수를 호출하면 비밀번호를 얻을 수 있다.
type password:
local fn = ... fn() return "load_pw"
password: //.A?%V}
또는 PASSWORD 함수를 직접 호출해도 비밀번호를 구할 수 있다.
type password:
print(PASSWORD())
//.A?%V}
wrong input data
v18 = 0i64;
v19 = v32;
for ( i = Block[0]; v18 < v31; ++v18 )
{
v21 = Block;
if ( v32 >= 0x10 )
v21 = Block[0];
v2 += *(v21 + v18);
}
username을 입력받은 뒤 sum을 구한다.
v6 = a2
v7 = strtoull(v6, EndPtr, 10);
입력한 password를 숫자로 변환하고
v8 = a1;
if ( v7 == a1 * (v8 * 1.093829989433289) )
비밀번호를 확인한다.
(a1 = sum)
local n = 0
local input = "crackmyapp"
for i=1, #input do
n = n + input:byte(i,i)
end
return n * (math.floor(n * 1.09382998943329))