콘텐츠로 건너뛰기

mistake

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
태그: