일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Softmax classification
- programmers
- 기능개발
- Python
- Linear_regression
- logistic regression
- 텐서플로
- pwnable.kr
- Algorithm
- AI
- 인공지능
- leg
- tensorflow
- Today
- Total
목록pwnable (28)
나혼자 공부장

소스 파일을 봤을 때, 알 수 있는 제약 사항은 두가지다. 1. strcpy 함수 주소로 리턴을 받아야 하고 2. strcpy 함수 이후 공간에는 AAAA 를 넣을 것이니 리턴받을 strcpy 함수를 이용해 뭔가 익스플로잇을 해야한다. 일단 스택은 이렇게 생겼을 것이다. 제약사항들을 고려해서 시나리오를 구상해보자. 1. buffer+sfp의 44바이트를 system("/bin/sh") 공간으로 채우고 2. strcpy로 리턴을 받은 후 3. strcpy의 인자로는 destination은 RET+4, source는 &buffer로 전달해준다면 4. strcpy가 실행되면서 AAAA의 공간을 buffer의 주소로 채워주기 때문에 5. strcpy 종료 후 buffer 주소로 RET 6. buffer 주소에 ..

위 코드를 봤을 때, 이전과 다르지 않아 보이지만 제약사항이 두 가지 추가되었다. 1. 환경변수를 초기화하는 과정이 추가되어 환경변수를 이용한 공격이 불가능해졌다. 2. buffer를 모두 0으로 만들어버리기 때문에 buffer에 쉘코드를 넣는 방식의 공격이 불가능해졌다. 즉, 환경변수를 이용하지 않고 return으로 buffer가 아니면서 bf로 시작하는 주소에 저장되어있는 쉘코드를 실행시키라는 소리이다. buffer를 0으로 만들더라도, 쉘코드는 어차피 버퍼 너머에서 동작할 것이기 때문에 영향을 받지 않는다. 공격 시 스택구조는 위와 같게 된다. .... 라고 표현한 부분은 리턴 주소가 bf 로 시작해야하기 때문에, 주소를 맞추기 위해 스택의 크기를 bf가 로 시작하는 주소에 닿을 때까지 늘려주는 것..

공격파일 코드이다. 위 코드만 봤을 때 알 수 있는 제약사항은 한 가지다. argv 인자의 47번째 값은 bf이되, 46번째 값은 ff이면 안 된다는 것이다. 이제는 딱히 gdb를 뜯어보지 않고도 스택을 그릴 수 있다. argv를 48byte 만큼 받으면, buffer로 strcpy 되었을 때 48번째 위치가 결과적으로 리턴 주소이기 때문에 argv의 44~47 번째 값이 곧 리턴 주소이다. 그 리턴 주소에 쉘코드가 있도록 구상할건데, 그 주소는 0xbffe.... 로 시작하도록 할 것이다. 더 주소를 높여서 조건문들을 우회하는 방법도 있으나 커널 영역을 침범할 가능성이 있기 때문에 주소를 낮춰서 우회하는 것이 낫다. 스택의 크기는 가변적이다. 0xbffe... 주소에 닿을 때까지 입력값을 극단적으로 늘..

hint 파일을 보면, gets 함수로 buf를 받을 때 인덱스 갯수를 제한하지 않고 있다. 이번에도 역시 BOF를 이용해서 푸는 문제겠다. 패스워드를 알아내기 위해 우리가 해결해야할 문제는 크게 두가지다. 1. 코드에 setreuid() 와 같은 권한 설정을 해주는 부분이 없다. 2. 쉘로 떨어지는 부분이 없다. 공격대상 파일은 setuid 설정이 되어있는 상태긴 하지만, rethat 7.0 이후부터 만큼은 쉘을 실행시킬 때 만큼은 drop privileges 정책에 의해 ruid 로 실행된다. 일반 setuid는 euid만 바꿔주는 것이고 ruid는 그대로기 때문에 setreuid() 함수로 따로 처리해주지 않으면 쉘을 실행해봤자 권한이 그대로인 상태로 실행된다. 따라서 아래와 같은 코드가 추가적으로..

/* input.c */ #include #include #include #include #include int main(int argc, char* argv[], char* envp[]){ printf("Welcome to pwnable.kr\n"); printf("Let's see if you know how to give input to program\n"); printf("Just give me correct inputs then you will get the flag :)\n"); // argv if(argc != 100) return 0; if(strcmp(argv['A'],"\x00")) return 0; if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0; p..

key 와 random 값을 서로 XOR 연산 했을 때 0xdeadbeef 가 되도록 key를 입력해주면 되는 문제이다. 여기서 rand()는 seed를 두고 있는 랜덤이 아니기 때문에 말이 랜덤이지 계속 같은 값을 가지게 된다. 그럼 랜덤 값이 뭔지 알아내기만 하면 끝나는 문제겠다. rand() 함수값이 할당이 된 이후에 break point 를 걸고 random 값이 무엇인지 찾아보았다. random address : 0x6b8b4567 key는 정수형으로 받고 있으니 10진수 타입으로 입력해주면 된다. 아래 접은 글은 flag문을 포함하고 있다. 더보기 flag : Mommy, I thought libc random is unpredictable...

passcode 실행파일의 코드이다. 찬찬히 읽어보며 취약점을 찾아보자. 일단 코드의 로직을 살펴봤을 때, passcode1의 값이 338150이거나 passcode2의 값이 13371337이면 flag를 보여준다. 그럼 저 stdin으로 조건문에 부합하도록 입력해주면 끝나는거 아닌가? 싶었지만, login() 함수 속 scanf() 구문을 잘 보면, 우리가 옳다고 여기는 형태와 조금 다르다. scanf("%d", passcode1); 무엇이 다른가 하면, &이 붙고 안 붙고의 차이가 있다. 한 마디로 passcode1의 주소값이냐 value냐인데, 우리가 아는 형태로는 주소값으로 받아야 우리가 원하는 변수에 입력값이 제대로 할당이 된다. 그렇다면 passcode.c 에서 제시된 입력 구문대로 하면 컴퓨..

일단 첫인상은 ARM 아키텍처를 사용하는 것으로 보여진다. 쓰여진 링크들을 모두 다운받아 내용을 확인해보자. 다운받은 파일 중 leg.c 라는 소스 파일을 열어보면, 위와 같은 코드가 보여진다. 코드로만 봤을 때는, key1() + key2() + key3() 의 값을 사용자가 계산하여 stdin을 통해 입력해주면 풀리는 문제라고 보여진다. asm 함수에 따로 리턴 타입이 있는지 조사해봤으나 그런 것 같지는 않았다. 다운받은 파일 중 leg.asm을 열어 더 자세하게 살펴보자. 여기까지 봤을 때 파악할 수 있는건, 각 함수의 값은 r0 에 담겨서 전달되고 있다는 것이다. 이는 우리가 이제 각 함수마다 r0 값이 최종적으로 무엇인지 파악해야 한다는 것을 의미한다. 1. key1 key1 부터 보면, r0에..

로그인 한 후 현재 디렉토리 정보를 확인하면 cobolt 실행파일의 코드로 보이는 것이 있다. 코드를 확인해봤을 때, 사용자가 입력한 값이 buffer 배열로 들어가므로 , 1. buffer 배열의 시작점부터 RET 직전까지의 byte 수를 구하고 2. 그 byte 수 만큼을 NOP로 채운 다음 3. return address로 쉘이 실행되게 하는 어떠한 주소를 넣어주면 해결되는 맥락이다. cobolt 파일을 gdb로 뜯어보자. 16 (buffer) + 4 (SFP) = 20 Byte 우리가 NOP로 채워야 할 바이트 수가 구해졌다. 이제 3번 사항에 쓰일 쉘이 실행되는 주소를 어떻게 구현해줄 것이냐? 두 가지 방법이 있다. 1. 환경변수를 이용 왜 굳이 환경변수를 이용해야 하느냐 하면, ASLR 이라는..