Saturday, December 29, 2018

Windows 악성코드 제작 및 분석_1

2018-12-03

Windows 

악성코드 제작(PoC)


윈도우용 백도어 1 - Direct Connection


  • 백도어가 작동할 타겟 시스템의 환경
    • Backdoor 설치된 운영체제는 Windows XP
    • 일반 사용자가  서핑  문서 작업용으로 사용 
      • 일반 가정집이나 소규모 사무실
      • 전문적인 침해 대응팀이 운영되는 환경이 아님
    • 호스트 기반 방화벽(Windows 내장 방화벽) 작동 
    • 네트워크 방화벽 없음
    • 공유기
      • 공유기가 없는 환경(PC 공인 직접 IP사용)
      • DMZ 또는 Port-Forwarding 설정된 환경(Dst NAT)
    • 백신
      • Avast 또는 알약 설치(pc 하나씩 작동)
      • 실시간 감시 기능 작동 
      • 최신 업데이트 적용
  • 통신 형태
    • TCP 기반 Server / Client 방식
      • 서버 --> Victim
      • 클라이언트 --> Hacker
    • 접속 방향
      • 해커에서 백도어로 먼저 접속(Direct Connection)
    • 포트 번호
      • 백도어가 포트를 열고 대기해야 하므로 소켓 정보 출력  발각될 가능성이 높다(netstat -ano)
      • 쉽게 의심되지 않을 만한 서비스의 포트번호와 동일한 번호
      • 유사한 포트 번호 사용, 실제 서비스와 충돌 가능성 주의
  • 보조 기능
    • 방화벽 우회
      • 소프트웨어 방화벽(Windows Firewall) 예외로 설정 or 방화벽 끄기
        • Outbound allow all / Inbound deny all
    • 자동 실행
      • 시작 프로그램으로 등록: 레지스트리 시작 프로그램 항목
      • 서비스로 등록
    • 안티 리버싱 / 안티 디버깅
    • 설치/실행/접속 기록(Log) 제거
    • 백신 무력화
  • 명령 체계
    • 명령어 변환없이 있는 그대로 /수신
      • 암호화 안함
    • 사용법(help 메뉴)
    • 연결하기: connect
    • 접속 끊기 : close
    • 파일 조작
      • [파일 목록 출력] : dir c:\
        • 소스코드: Backdoor Server / Client 시나리오 1-1
      • [파일 다운로드] : get [파일명]
        • 소스코드: Backdoor Server / Client 시나리오 1-2
      • [파일 업로드] : put [파일명]
        • 소스코드: 스스로 만들어보기 실습
      • [파일 삭제] : del [파일명]
        • 소스코드: 스스로 만들어보기 실습
통신S/W 함께 만들수 있도록(어플리케이션을 만드는데 연결역할)=>Winsock API(Application Programming Interface) : MS 제공하는 함수와 구조체를 제공

    • 시스템 종료/재시작
      • API 활용하는 방법
LookupPrivilegeValue / AdjustTokenPrivileges / ExitWindowsEx
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
// Get a token for this process.
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
// Get the LUID for the shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get the shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
// Shut down the system and force all applications to close.
ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0);
    • 명령어를 사용하는 방법
      • [종료] : shutdown
        • WinExec("shutdown -h -f -t 0", SW_HIDE);
      • [재시작] : reboot
        • WinExec("shutdown -r -f -t 0", SW_HIDE);
    • OS 명령 실행 : cmd [명령]
      • 명령창(cmd.exe)에서 명령어 실행
      • cmd.exe 명령어가 내장되어 있다.
      • cmd.exe /c [명령어]
      • cmd.exe /k [명령어]
    • 프로세스 다루기
      • [프로세스 목록 출력] : plist
        • 소스코드: Backdoor Server / Client 시나리오 1-3
      • [프로세스 생성(파일 실행)] : run [실행파일명]
        • 소스코드: 스스로 만들어보기 실습 
      •  [프로세스 종료] : pkill [pid]
        • 소스코드: Backdoor Server / Client 시나리오 1-4
    • 흔적제거
      • [HDD 파괴] : clearhdd
        • HDD Destroy 소스코드
    • 웹캠 보기/녹화
    • 소리 듣기/녹음
    • 화면 보기/캡쳐

실습

  • SERVER

// tcp_server_WinMain.cpp / 7계층(application) 위한 악성코드를 만듬(하위계층에게 시키는 SW)#include<winsock2.h> // windows.h 포함(선언필수)#pragma comment(lib,"ws2_32.lib")int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nShowCmd ){ int retval; WSADATA wsa; //변수
 if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) // ws2_32.dll 초기화 //함수return -1; SOCKET tcp_sock = socket(AF_INET, SOCK_STREAM, 0);  //함수//netstat -an 진행하기 위한 소켓프로그래밍 /SOCK_STREAM: TCP 소켓/SOCK_DGRAM: UDP 소켓 SOCKADDR_IN serveraddr;
 ZeroMemory(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; // 대체적으로  값을 기입 serveraddr.sin_port = htons(9000); // 포트번호 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); //ip주소/ INADDR_ANY=0.0.0.0 retval = bind(tcp_sock, (SOCKADDR *)&serveraddr, sizeof(serveraddr)); retval = listen(tcp_sock, SOMAXCONN); //  부분을 실행해야지 netstat 응답/ 소켓이 완전히 열린 상태
 SOCKET client_sock; SOCKADDR_IN clientaddr; int addrlen; char buf[10]; //

 while(1){  addrlen = sizeof(clientaddr); //주소의 길이만  client_sock = accept(tcp_sock, (SOCKADDR *)&clientaddr, &addrlen);//소켓을 계속 복제  retval = recv(client_sock, buf, sizeof(buf), 0); //받은  변수크기만큼 buf 담기  buf[retval]='\0';  retval = send(client_sock, buf, strlen(buf), 0); //buf 있는 바이트수를 계산해서  } return 0;}

[ 소스코드 빌드 ]



[ 디스어셈블리어 ]
3argc socket start
PUSH-PUSH-PUSH-CALL


**msdn(MS Development Network)
[ 중단점을 걸어 디버깅 ]
함수가 진행되어지는 과정을 자세히 보기위하여
새로운 함수가 시작하기 전에 중단점을 걸어서 확인



[ Server의 소켓확인 ]
설정한 포트가 열렸는지 확인하기 위해


[ client의 소켓확인 ]
9000포트 열림


[ 9000번포트가 연결됨 ]
Established


ESTABLISHED 
Client 와 Server가 9000번 포트로 연결됨



  • Client

// tcp_client_main.cpp

#include<winsock2.h> // 선언필수(windows.h 포함)
#include<stdlib.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")
int main(void) { int retval; char buf1[10], buf2[10]; WSADATA wsa;
 if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) return -1; //WSA:=winsocket 시작하는 함수
(참고) UNIX : Socket API--->Linux 고대로 따라함--->Windows 약간 변형: Winsock API
 SOCKET tcp_sock = socket(AF_INET, SOCK_STREAM, 0); //함수
 SOCKADDR_IN servaddr;
 ZeroMemory(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_port = htons(9000); //접속하고싶은 portnumber
 servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");// 접속하고싶은 ip
 retval = connect(tcp_sock, (SOCKADDR *)&servaddr, sizeof(servaddr));
 printf("Input data(below 10 char) : ");
 scanf("%s",buf1);
 retval = send(tcp_sock, buf1, strlen(buf1), 0);
 retval = recv(tcp_sock, buf2, sizeof(buf2), 0);
 buf2[retval]='\0';
 printf("Send data: %s,  Recv data: %s \n", buf1, buf2);
 Sleep(210000);
 return 0;
}

쓰레기 값이 붙어 있음



디버깅하여 값이 입력되는 부분을 살펴보자




중단점을 걸어놓고 디버깅
buf1 값에 입력한 값이 들어감



더 내려옴


"    " 의미없는 값이 있음


해결

초기화필요
->data+00 나오도록 만들어줘야 함 
-> 6byte이므로 6번째 byte부터 \0(NULL)값을 준다




깨끗하게 들어옴



[ Wireshark ]
9000번 포트로 통신이 진행되고 있음

확인


No comments:

Post a Comment

List

MobSF

MobSF는 오픈소스 모바일 앱 자동 보안 진단 프레임워크로 자동 분석 시스템 구축할 때 사용한다. 정정 및 동적 분석이 가능하며, Android, iOS, Windows에 대해 침투 테스트, 멀웨어 분석 및 보안 평가를 할 수 있다. 참고자료 필...