Description
We all make mistakes, let's move on. (don't take this too seriously, no fancy hacking skill is required at all) This task is based on real event ssh [email protected] -p2222 (pw:guest)
Source Code
- mistake.c
#include <stdio.h>
#include <fcntl.h>
#define PW_LEN 10
#define XORKEY 1
void xor(char* s, int len){
int i;
for(i=0; i<len; i++){
s[i] ^= XORKEY;
}
}
int main(int argc, char* argv[]){
int fd;
if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){
printf("can't open password %d\n", fd);
return 0;
}
printf("do not bruteforce...\n");
sleep(time(0)%20);
char pw_buf[PW_LEN+1];
int len;
if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
printf("read error\n");
close(fd);
return 0;
}
char pw_buf2[PW_LEN+1];
printf("input password : ");
scanf("%10s", pw_buf2);
// xor your input
xor(pw_buf2, 10);
if(!strncmp(pw_buf, pw_buf2, PW_LEN)){
printf("Password OK\n");
setregid(getegid(), getegid());
system("/bin/cat flag\n");
}
else{
printf("Wrong Password\n");
}
close(fd);
return 0;
}
Analysis
strncmp에 브레이크포인트 설치하고, 각각 AAAAAAAAAA, BBBBBBBBBB를 입력했을때 gef에서 다음과 같은 결과를 볼 수 있다.
gef➤ r
Starting program: /home/ubuntu/pwnable.kr/mistake/mistake
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
do not bruteforce...
AAAAAAAAAA
BBBBBBBBBB
input password :
Breakpoint 1, __strncmp_sse2 () at ../sysdeps/x86_64/strcmp.S:108
108 ../sysdeps/x86_64/strcmp.S: No such file or directory.
[ Legend: Modified register | Code | Heap | Stack | String ]
─────────────────────────────────────────────────────────────────── registers ────
$rax : 0x00007fffffffe482 → "AAAAAAAAAA"
$rbx : 0x0
$rcx : 0x00007fffffffe48d → "CCCCCCCCCC"
$rdx : 0xa
$rsp : 0x00007fffffffe458 → 0x0000555555555486 → <main+0173> test eax, eax
$rbp : 0x00007fffffffe4b0 → 0x0000000000000001
$rsi : 0x00007fffffffe48d → "CCCCCCCCCC"
$rdi : 0x00007fffffffe482 → "AAAAAAAAAA"
$rip : 0x00007ffff7e3f020 → <__strncmp_sse2+0000> endbr64
$r8 : 0x0
$r9 : 0x00005555555596b0 → "BBBBBBBBBB\n"
$r10 : 0xffffffffffffff80
$r11 : 0x0
$r12 : 0x00007fffffffe5c8 → 0x00007fffffffe807 → "/home/ubuntu/pwnable.kr/mistake/mistake"
$r13 : 0x0000555555555313 → <main+0000> endbr64
$r14 : 0x0000555555557d60 → 0x0000555555555280 → <__do_global_dtors_aux+0000> endbr64
$r15 : 0x00007ffff7ffd040 → 0x00007ffff7ffe2e0 → 0x0000555555554000 → jg 0x555555554047
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x33 $ss: 0x2b $ds: 0x00 $es: 0x00 $fs: 0x00 $gs: 0x00
─────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe458│+0x0000: 0x0000555555555486 → <main+0173> test eax, eax ← $rsp
0x00007fffffffe460│+0x0008: 0x00007fffffffe5c8 → 0x00007fffffffe807 → "/home/ubuntu/pwnable.kr/mistake/mistake"
0x00007fffffffe468│+0x0010: 0x0000000100000000
0x00007fffffffe470│+0x0018: 0x0000000000000000
0x00007fffffffe478│+0x0020: 0x0000000100000000
0x00007fffffffe480│+0x0028: 0x4141414141410000
0x00007fffffffe488│+0x0030: 0x4343430041414141 ("AAAA"?)
0x00007fffffffe490│+0x0038: 0x0043434343434343 ("CCCCCCC"?)
───────────────────────────────────────────────────────────────── code:x86:64 ────
0x7ffff7e3f012 <__strcmp_sse2_unaligned+02a2> ret
0x7ffff7e3f013 cs nop WORD PTR [rax+rax*1+0x0]
0x7ffff7e3f01d nop DWORD PTR [rax]
→ 0x7ffff7e3f020 <__strncmp_sse2+0000> endbr64
0x7ffff7e3f024 <__strncmp_sse2+0004> test rdx, rdx
0x7ffff7e3f027 <__strncmp_sse2+0007> je 0x7ffff7e40864 <__strncmp_sse2+6212>
0x7ffff7e3f02d <__strncmp_sse2+000d> cmp rdx, 0x1
0x7ffff7e3f031 <__strncmp_sse2+0011> je 0x7ffff7e40870 <__strncmp_sse2+6224>
0x7ffff7e3f037 <__strncmp_sse2+0017> mov r11, rdx
───────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "mistake", stopped 0x7ffff7e3f020 in __strncmp_sse2 (), reason: BREAKPOINT
─────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x7ffff7e3f020 → __strncmp_sse2()
[#1] 0x555555555486 → main()
──────────────────────────────────────────────────────────────────────────────────
gef➤
첫번째 매개변수는 A 10개가 들어갔고, 2번째 매개변수에는 C 10개가 들어간 것을 보면, 2번째때 입력했던 B 10개가 1과 XOR되어 나온 것을 알 수 있다.
0x41을 1과 XOR한 @를 2번째때 입력해주면 된다.
>>> chr(ord('A') ^ 1)
'@'
Why?
if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){
open("/home/mistake/password",O_RDONLY,0400) 함수는 양수인 fd 값을 반환한다.
연산자 우선순위 때문에 크기 비교인 (<)를 먼저하고 fd와 0을 대소비교하면 false가 되므로, 최종적으로 fd는 0이된다.
따라서 password는 파일로부터 읽는게 아니라 표준 입력으로 우리가 임의로 지정줄 수 있다.
Result
mistake@ubuntu:~$ ./mistake do not bruteforce... AAAAAAAAAA input password : @@@@@@@@@@ Password OK Mommy_the_0perator_priority_confuses_me