Study Record

[리버싱] 자주 사용되는 C언어 코드 분석 + 함수 본문

리버싱/기본

[리버싱] 자주 사용되는 C언어 코드 분석 + 함수

초코초코초코 2021. 11. 12. 14:27
728x90

자주 사용되는 함수

※ 참고 사이트 :  http://forum.falinux.com/zbxe/index.php?document_srl=408400

int setreuid(uid_t ruid, uid_t euid) -> RUID / EUID 변경

int execl(const char* path, const char* arg); -> 현재 쉘에서 사용된다.

int execv(const char* path, const char* arg[])

 

☞ 공유 메모리(shmget , shmat, shmdt)

https://laustudy.tistory.com/67

 

☞ exit()

#include <stdlib.h>
void exit(int status); 

/* 
커널에서 종료작업을 실행한다.
status : 상태 코드
*/

☞ printf()

#include <stdio.h>

int printf(const char * restrict format, ...);
/*
C언어 표준 출력 함수로 출력할 데이터를 어떤 서식에 맞춰 출력할지 서식 지정자(format specifier)를 통해 직접 지정 가능하다.
리턴값 : 출력된 문자의 개수 (개행문자 표함)
*/

printf("printf() 함수는 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있어요!\n");
printf("변수에 저장된 숫자는 %d입니다.", 10);

☞ sprintf()

#include <stdio.h>
int sprintf(char *buffer, const char *format-string, argument-list);
/*
buffer에 format-string 의 내용을 저장한다.

리턴값 : 널문자를 제외한 문자열의 길이를 반환한다.
buffer : 출력값을 저장할 문자열
format-string : 서식 문자열
*/

sprintf(msg, "%d world!", 10);

☞ scanf()

#include <stdio.h>
int scanf(const char* format, ...);
/* 표준입력(stdin) 으로 부터 데이터를 읽어와 형식(format) 문자열에 따라
나머지 인자들이 가리키는 장소에 값을 대입한다. */
scanf("%d", &num);

☞ setuid() , setgid()

#include <sys/types.h>
#include <unistd.h>

int setuid(uid_t uid);
int setgid(gid_t gid);

/*
setuid() 함수를 실행한 프로세스가 루트 권한을 갖고 있다면 Read User ID, Effective User ID, 
Saved User ID 모두를 uid 로 바꾼다.
루트 권한은 갖고 있지 않으나 uid가 Real User ID 혹은 Saved User ID와 같다면
Effective User ID 만을 uid 로 바꿉니다.
setgid() 함수는 그룹 아이디를 제어한다는 점만 다르고 setuid() 와 동일하다.

반환값 : 성공시 0 , 실패시 -1

각각의 프로세스는 RUID , EUID , Saved UID 를 가지고 있고 실제 프로그램이 수행될 때는 RUID가 아닌 EUID를 사용하여
허가권을 계산한다. 따라서 Setuid 비트가 설정되어 있는 프로그램을 실행할 때 일시적으로 상승된 권한을 복귀하기 위해 Saved UID에
기존의 UID를 저장한 후 Effective UID를 일시적으로 파일의 소유자의 UID로 변경하여 사용된다.
/*

 

☞ create()

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int create(const char *file, mode_t mode)
/*
파일을 생성하고 파일 스크립트값을 반환한다.
반환값 : 실패시 0이하의 값, 성공시 파일 스크립트 반환
file : 파일 이름
mode : 접근 권한
*/

☞ write()

#include <unistd.h>
ssize_t wirte(int fd, const void *buf, size_t n);
/*
열려있는 파일에 쓰기를 한다.
반환값 : 쓰기 성공시 쓰기한 바이트 개수, 실패시 -1
fd : 파일 스크립터
void *buf : 파일에 쓰기를 할 내용을 담은 버퍼
size_t : 쓰기할 바이트 개수
*/

☞ close()

#include <unistd.h>
int close(int fd);
/*
파일 사용을 중지한다.
반환값 : 정상적으로 종료(0) , 실패(1)
fd : 파일 스크립트
/*

☞ remove()

#include <stdio.h>
int remove( const char *path );
/*
파일을 삭제한다.
path : 파일 경로
반환값 : 정상 일 때 0, 에러 시 -1
*/

 

☞ system()

#include <stdlib.h>
int system(const char *str);
/*
인수로 받은 명령어를 실행한다.
리턴값 : 에러 -1, str(명령어)의 return 값
str : 명령어
*/
system("/bin/bash");

☞ signal()

#include <signal.h>
sighandler_t signal(int signum, sighandler_t handler);
/*
인터럽트 신호를 처리할 수 있는 함수이다.
리턴값 : 성공시 handler 함수 주소, 실패시 EINVAL
signum  : 시그널 번호/이름
handler : SIG_DFL 또는 SIG_IGN 중 하나여야 하며, <signal.h> 포함 파일이나 함수 주소에 정의된다.
*/

signal(SIGINT, SIG_DFL);    # SIG_DFL : 시그널 실행
signal(SIGQUIT, SIG_IGN);   # SIG_IGN : 시그널 무시
signal(SIGINT, handler);    # handler 라는 별도의 정의된 함수 실행

☞ strlen()

☞ strcpy()

☞ strncmp()

#include <string.h>
int strncmp(const char *string1, const char *string2, size_t count);

/*
string1 과 string2 문자를 count 만큼 비교한다. 
리턴값 : 동일하면 0, 동일하지 않으면 0이아닌 값
*/

strncmp(string1, string2, 4);  // 앞 4개의 문자가 동일한지 비교한다.

☞ strcat()

☞ fgets()

#include <stdio.h>
char *fgets (char *string, int n, FILE *stream);

/*
현재 stream 위치에서 어느 것이 먼저 오건 첫 번째 줄 바꾸기 문자(\n)까지, 
스트림의 끝까지 또는 읽은 문자 수가 n-1과 같을 때까지 문자를 읽는다. 줄 바꾸기 문자까지 포함하여 읽는다.
fgets() 함수는 결과를 string에 저장하고 스트링 끝에 널(null) 문자(\0)를 추가한다.

리턴값 : 성공시 string 버퍼를 가르키는 포인터 리턴, 실패 혹은 파일의 끝일 경우 NUL
string : 파일에서 부터 가지고 온 문자열을 넣는 변수
n : 한번에 가지고올 문자열의 길이
stream : 파일의 파일 포인터 (stdin : 키보드 입력)
*/

fgets(s, 4, stdin);

☞ malloc()

#include <stdlib.h> 
void* malloc(size_t size);

/*
메모리를 size만큼 동적으로 할당해준다.
리턴값 : 성공시 첫번째 주소 리턴, 실패시 NULL
size : 메모리를 할당할 크기
*/
int *ptr = (int *)malloc(sizeof(int) * 4);

☞ getenv() - http://forum.falinux.com/zbxe/index.php?document_srl=408391

#include <stdlib.h>
char *getenv(const char *name);
/*
환경 변수 목록 중에 원하는 변수 값을 구한다.

리턴값 : 환경 변수의 값
name : 구하려는 환경 변수의 이름
*/

getenv("TERM");
getenv("SHELL");

☞ putenv() - http://forum.falinux.com/zbxe/index.php?document_srl=408394

#include <stdlib.h>
int putenv(char *string);
/*
환경 변수 목록 중에 변수 값을 수정하거나 추가합니다.
실행 중인 프로그램에서만 유효하며 외부적으로는 변경되지 않는다.

리턴값 : 성공시 0, 실패시 -1
string : 변경 또는 추가하려는 변수 이름과 변수 값
*/

putenv( "QTDIR=/form/falinux/com");
putenv( "NEWVALLUE=form.falinux.com");

☞ setenv() - http://forum.falinux.com/zbxe/index.php?document_srl=408397&mid=C_LIB

#include <stdlib.h>
int setenv(const char *envname, const char *envval, int overwrite);
/*
환경 변수 목록 중에 변수 값을 수정하거나 추가한다.
실행 중인 프로그램에서만 유효하며 외부적으로는 변경되지 않는다.

리턴값 : 성공시 0, 실패시 -1
envname : 환경 변수의 이름
envval : 변수 값
overwrite : 이미 같은 이름의 변수가 있다면 변경할지의 여부 (0 : 변경 하지 않음, 1 : 변경)
*/

setenv( "QTDIR"    , "/form/falinux/com", 0);
setenv( "NEWVALLUE", "form.falinux.com" , 1);

☞ unsetenv() - http://forum.falinux.com/zbxe/index.php?document_srl=408400&mid=C_LIB

#include <stdlib.h>
int unsetenv(const char *name);
/*
환경 변수를 삭제한다.
실행 중인 프로그램에서만 유효하며 외부적으로는 변경되지 않는다.

리턴값 : 성공시 0, 실패시 -1
name : 환경 변수의 이름
*/

unsetenv("HOSTNAME");

☞ execve()

#include <unistd.h>
int execve (const char *filename, char *const argv [], char *const envp[]);
/*
다른 프로그램을 실행하고 자신은 종료한다.

리턴값 : 실패일 경우만 -1
filename : 전체 경로명
argv : arg 인수 목록
envp : 환경 설정 목록
*/

char *argv[] = {"/bin/bash", 0};
execve("/bin/bash", &argv, 0);

공격 프로그램 만들때 사용하는 주로 사용 되는 함수

1. sprintf()
2. strcpy()/strcat()

echo mate | /bin/level7    ===   (printf mate; cat) | /bin/level7
=> 일반적인 공격 구문: (echo mate; cat) | /bin/level7

 

자주  사용되는 C언어 코드 분석

1. 기본 구문

void main(void){

}
0x080482f4 <main+0>:    push   %ebp
0x080482f5 <main+1>:    mov    %esp,%ebp
0x080482f7 <main+3>:    sub    $0x8,%esp
0x080482fa <main+6>:    and    $0xfffffff0,%esp
0x080482fd <main+9>:    mov    $0x0,%eax
0x08048302 <main+14>:   sub    %eax,%esp
0x08048304 <main+16>:   leave
0x08048305 <main+17>:   ret
0x08048306 <main+18>:   nop
0x08048307 <main+19>:   nop
#include <stdio.h>

int main(void){
    return 0;
}
0x080482f4 <main+0>:    push   %ebp
0x080482f5 <main+1>:    mov    %esp,%ebp
0x080482f7 <main+3>:    sub    $0x8,%esp
0x080482fa <main+6>:    and    $0xfffffff0,%esp
0x080482fd <main+9>:    mov    $0x0,%eax
0x08048302 <main+14>:   sub    %eax,%esp
0x08048304 <main+16>:   mov    $0x0,%eax
0x08048309 <main+21>:   leave
0x0804830a <main+22>:   ret
0x0804830b <main+23>:   nop

 

2. 변수 선언

void main(void){
    int a = 10;
}
0x080482f4 <main+0>:    push   %ebp
0x080482f5 <main+1>:    mov    %esp,%ebp
0x080482f7 <main+3>:    sub    $0x8,%esp
0x080482fa <main+6>:    and    $0xfffffff0,%esp
0x080482fd <main+9>:    mov    $0x0,%eax
0x08048302 <main+14>:   sub    %eax,%esp
0x08048304 <main+16>:   movl   $0xa,0xfffffffc(%ebp)
0x0804830b <main+23>:   leave
0x0804830c <main+24>:   ret
0x0804830d <main+25>:   nop
0x0804830e <main+26>:   nop
0x0804830f <main+27>:   nop

 

3.  if 구문

#include <stdio.h>

int main(void){
    int a = 10;
    if(a < 5) {
        printf("a는 5보다 작습니다.");
    }else {
        printf("a는 5보다 큽니다.");
    }
    return 0;
}
0x08048328 <main+0>:    push   %ebp
0x08048329 <main+1>:    mov    %esp,%ebp
0x0804832b <main+3>:    sub    $0x8,%esp
0x0804832e <main+6>:    and    $0xfffffff0,%esp
0x08048331 <main+9>:    mov    $0x0,%eax
0x08048336 <main+14>:   sub    %eax,%esp
0x08048338 <main+16>:   movl   $0xa,0xfffffffc(%ebp)
0x0804833f <main+23>:   cmpl   $0x4,0xfffffffc(%ebp)
0x08048343 <main+27>:   jg     0x8048357 <main+47>
0x08048345 <main+29>:   sub    $0xc,%esp
0x08048348 <main+32>:   push   $0x804841c
0x0804834d <main+37>:   call   0x8048268 <printf>
0x08048352 <main+42>:   add    $0x10,%esp
0x08048355 <main+45>:   jmp    0x8048367 <main+63>  # if문 종료
0x08048357 <main+47>:   sub    $0xc,%esp
0x0804835a <main+50>:   push   $0x8048429
0x0804835f <main+55>:   call   0x8048268 <printf>
0x08048364 <main+60>:   add    $0x10,%esp
0x08048367 <main+63>:   mov    $0x0,%eax
0x0804836c <main+68>:   leave
0x0804836d <main+69>:   ret
0x0804836e <main+70>:   nop
0x0804836f <main+71>:   nop

 

4. 반복문 - for문과 while문의 결과가 동일하다.

#include <stdio.h>
void main(void){
    int a;
    for(a=0a < 5; a++){
        printf("%d", a);
    }
}
0x08048328 <main+0>:    push   %ebp
0x08048329 <main+1>:    mov    %esp,%ebp
0x0804832b <main+3>:    sub    $0x8,%esp
0x0804832e <main+6>:    and    $0xfffffff0,%esp
0x08048331 <main+9>:    mov    $0x0,%eax
0x08048336 <main+14>:   sub    %eax,%esp
0x08048338 <main+16>:   movl   $0x0,0xfffffffc(%ebp)
0x0804833f <main+23>:   cmpl   $0x4,0xfffffffc(%ebp)
0x08048343 <main+27>:   jle    0x8048347 <main+31>  # a<5일 경우
0x08048345 <main+29>:   jmp    0x8048361 <main+57>  # 반복문 탈출
0x08048347 <main+31>:   sub    $0x8,%esp
0x0804834a <main+34>:   pushl  0xfffffffc(%ebp)
0x0804834d <main+37>:   push   $0x8048410
0x08048352 <main+42>:   call   0x8048268 <printf>
0x08048357 <main+47>:   add    $0x10,%esp
0x0804835a <main+50>:   lea    0xfffffffc(%ebp),%eax
0x0804835d <main+53>:   incl   (%eax)
0x0804835f <main+55>:   jmp    0x804833f <main+23>
0x08048361 <main+57>:   leave
0x08048362 <main+58>:   ret
0x08048363 <main+59>:   nop
#include <stdio.h>
void main(void){
    int a = 0;
    while(a < 5){
        printf("%d", a);
        a++;   
    }
}
0x08048328 <main+0>:    push   %ebp
0x08048329 <main+1>:    mov    %esp,%ebp
0x0804832b <main+3>:    sub    $0x8,%esp
0x0804832e <main+6>:    and    $0xfffffff0,%esp
0x08048331 <main+9>:    mov    $0x0,%eax
0x08048336 <main+14>:   sub    %eax,%esp
0x08048338 <main+16>:   movl   $0x0,0xfffffffc(%ebp)
0x0804833f <main+23>:   cmpl   $0x4,0xfffffffc(%ebp)
0x08048343 <main+27>:   jle    0x8048347 <main+31>  # a<5 일 경우
0x08048345 <main+29>:   jmp    0x8048361 <main+57>  # 반복문 탈출
0x08048347 <main+31>:   sub    $0x8,%esp
0x0804834a <main+34>:   pushl  0xfffffffc(%ebp)
0x0804834d <main+37>:   push   $0x8048410
0x08048352 <main+42>:   call   0x8048268 <printf>
0x08048357 <main+47>:   add    $0x10,%esp
0x0804835a <main+50>:   lea    0xfffffffc(%ebp),%eax
0x0804835d <main+53>:   incl   (%eax)
0x0804835f <main+55>:   jmp    0x804833f <main+23>
0x08048361 <main+57>:   leave
0x08048362 <main+58>:   ret
0x08048363 <main+59>:   nop

5. switch 문

#include <stdio.h>
int main(void){
    int a = 2;
    switch(a){
    case (1):
        printf("a is 1\n");
        break;
    case (2):
        printf("a is 2\n");
        break;
    case (3):
        printf("a is 3\n");
        break;
    default:
        printf("a is not 1~3\n");
        break;
    }
    return 0;
}
0x08048328 <main+0>:    push   %ebp
0x08048329 <main+1>:    mov    %esp,%ebp
0x0804832b <main+3>:    sub    $0x8,%esp
0x0804832e <main+6>:    and    $0xfffffff0,%esp
0x08048331 <main+9>:    mov    $0x0,%eax
0x08048336 <main+14>:   sub    %eax,%esp
0x08048338 <main+16>:   movl   $0x2,0xfffffffc(%ebp)
0x0804833f <main+23>:   mov    0xfffffffc(%ebp),%eax
0x08048342 <main+26>:   mov    %eax,0xfffffff8(%ebp)
0x08048345 <main+29>:   cmpl   $0x2,0xfffffff8(%ebp)
0x08048349 <main+33>:   je     0x8048373 <main+75>
0x0804834b <main+35>:   cmpl   $0x2,0xfffffff8(%ebp)
0x0804834f <main+39>:   jg     0x8048359 <main+49>
0x08048351 <main+41>:   cmpl   $0x1,0xfffffff8(%ebp)
0x08048355 <main+45>:   je     0x8048361 <main+57>
0x08048357 <main+47>:   jmp    0x8048397 <main+111>
0x08048359 <main+49>:   cmpl   $0x3,0xfffffff8(%ebp)
0x0804835d <main+53>:   je     0x8048385 <main+93>
0x0804835f <main+55>:   jmp    0x8048397 <main+111>
0x08048361 <main+57>:   sub    $0xc,%esp         # case 1
0x08048364 <main+60>:   push   $0x804845c
0x08048369 <main+65>:   call   0x8048268 <printf>
0x0804836e <main+70>:   add    $0x10,%esp
0x08048371 <main+73>:   jmp    0x80483a7 <main+127>
0x08048373 <main+75>:   sub    $0xc,%esp         # case 2
0x08048376 <main+78>:   push   $0x8048464
0x0804837b <main+83>:   call   0x8048268 <printf>
0x08048380 <main+88>:   add    $0x10,%esp
0x08048383 <main+91>:   jmp    0x80483a7 <main+127>
0x08048385 <main+93>:   sub    $0xc,%esp         # case 3
0x08048388 <main+96>:   push   $0x804846c
0x0804838d <main+101>:  call   0x8048268 <printf>
0x08048392 <main+106>:  add    $0x10,%esp
0x08048395 <main+109>:  jmp    0x80483a7 <main+127>
0x08048397 <main+111>:  sub    $0xc,%esp         # default
0x0804839a <main+114>:  push   $0x8048474
0x0804839f <main+119>:  call   0x8048268 <printf>
0x080483a4 <main+124>:  add    $0x10,%esp
0x080483a7 <main+127>:  mov    $0x0,%eax
0x080483ac <main+132>:  leave
0x080483ad <main+133>:  ret
0x080483ae <main+134>:  nop
0x080483af <main+135>:  nop

 

 

728x90