일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- intent
- Flutter
- DART
- 앱
- textfield
- data
- TEST
- CustomScrollView
- scroll
- appbar
- Navigation
- Dialog
- Kotlin
- 앱바
- tabbar
- Button
- drift
- 테스트
- livedata
- Compose
- android
- 계측
- ScrollView
- Coroutines
- binding
- activity
- 안드로이드
- LifeCycle
- viewmodel
- textview
- Today
- Total
Study Record
[리버싱] 자주 사용되는 C언어 코드 분석 + 함수 본문
자주 사용되는 함수
※ 참고 사이트 : 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=0; a < 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 |
'리버싱 > 기본' 카테고리의 다른 글
[리버싱] Hack Me 리버싱 의사코드 복원 (5,6단계) (0) | 2021.11.15 |
---|---|
[리버싱] netcat(nc) CMD (0) | 2021.11.15 |
[리버싱] 간단한 어셈블리 코드 분석 후 복원 (0) | 2021.11.12 |
[리버싱] 어셈블리어 문법 (0) | 2021.11.12 |
[리버싱] gdb 사용법 (0) | 2021.11.12 |