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