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

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

+ Recent posts