Skip to content

Instantly share code, notes, and snippets.

@shuax
Created March 13, 2022 02:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shuax/39019a41ef499843f54ab70a18dcb4a0 to your computer and use it in GitHub Desktop.
Save shuax/39019a41ef499843f54ab70a18dcb4a0 to your computer and use it in GitHub Desktop.
#include <windows.h>
#include <psapi.h>
#include <stdio.h>
#include <string>
#include <vector>
std::string store_password;
std::wstring QuoteSpaceIfNeeded(const std::wstring &str)
{
if (str.find(L' ') == std::wstring::npos)
return std::move(str);
std::wstring escaped(L"\"");
for (auto c : str)
{
if (c == L'"')
escaped += L'"';
escaped += c;
}
escaped += L'"';
return std::move(escaped);
}
std::wstring JoinArgsString(std::vector<std::wstring> lines, const std::wstring &delimiter)
{
std::wstring text;
bool first = true;
for (auto &line : lines)
{
if (!first)
text += delimiter;
else
first = false;
text += QuoteSpaceIfNeeded(line);
}
return text;
}
std::string utf16to8(const std::wstring &src)
{
std::vector<char> buffer;
buffer.resize(WideCharToMultiByte(CP_UTF8, 0, src.data(), -1, NULL, 0, NULL, NULL));
WideCharToMultiByte(CP_UTF8, 0, src.data(), -1, &buffer[0], (int)buffer.size(), NULL, NULL);
return std::string(&buffer[0]);
}
std::wstring StartSshWithPassword()
{
std::vector <std::wstring> args;
args.push_back(L"C:\\Windows\\System32\\OpenSSH\\ssh.exe");
int state = 0;
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
for (int i = 1; i < argc; i++)
{
switch(state)
{
case 0:
if (wcscmp(argv[i], L"--p") == 0)
{
state = 1;
}
else
{
args.push_back(argv[i]);
}
break;
case 1:
{
store_password = utf16to8(argv[i]);
state = 2;
}
break;
case 2:
args.push_back(argv[i]);
break;
}
}
LocalFree(argv);
return JoinArgsString(args, L" ");
}
const uint8_t *SundaySearch(const uint8_t *s, int n, const uint8_t *p, int m)
{
int i;
size_t skip[256];
for (i = 0; i < 256; i++)
{
*(skip + i) = m + 1;
}
for (i = 0; i < m; i++)
{
*(skip + * (p + i)) = m - i;
}
while (s < s + (n - m + 1))
{
for (i = 0; * (s + i) == *(p + i) ;)
{
i++;
if (i >= m)
{
return s;
}
}
s += *(skip + * (s + m));
}
return NULL;
}
void Patch_readpassphrase(HANDLE hprocess, HANDLE hThread)
{
MEMORY_BASIC_INFORMATION mbi;
unsigned char* addr = 0;
while (VirtualQueryEx(hprocess, addr, &mbi, sizeof(mbi)))
{
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS && mbi.Protect != PAGE_GUARD && mbi.Type==MEM_IMAGE)
{
if(mbi.BaseAddress != mbi.AllocationBase)
{
wchar_t path[MAX_PATH] = {0};
::GetMappedFileNameW(hprocess, mbi.BaseAddress, path, MAX_PATH);
// printf("BaseAddress %p %p %llx %S\n", mbi.BaseAddress, mbi.AllocationBase, mbi.RegionSize, path);
std::vector<uint8_t> buffer;
buffer.resize(mbi.RegionSize);
DWORD_PTR count;
ReadProcessMemory(hprocess, mbi.BaseAddress, &buffer[0], mbi.RegionSize, &count);
const uint8_t opcode[] = {0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x4C, 0x89, 0x44, 0x24, 0x18};
auto addr = SundaySearch(&buffer[0], count, &opcode[0], sizeof(opcode));
if(addr)
{
intptr_t offset = addr - &buffer[0];
uint8_t mov_rax_rdx[] = {0x48, 0x8B, 0xC2};
::WriteProcessMemory(hprocess, LPVOID((uintptr_t)mbi.BaseAddress + offset), mov_rax_rdx, sizeof(mov_rax_rdx), NULL);
offset += sizeof(mov_rax_rdx);
uint8_t patch[] = {0xC6, 0x40, 0x00, 0x00};
for(int i=0;i<=store_password.size();i++)
{
patch[2] = i;
patch[3] = store_password[i];
// printf("patch %d %p\n", patch[3], LPVOID((uintptr_t)mbi.BaseAddress + offset));
::WriteProcessMemory(hprocess, LPVOID((uintptr_t)mbi.BaseAddress + offset), patch, sizeof(patch), NULL);
offset += sizeof(patch);
}
uint8_t ret[] = {0xC3};
::WriteProcessMemory(hprocess, LPVOID((uintptr_t)mbi.BaseAddress + offset), ret, sizeof(ret), NULL);
offset += sizeof(ret);
// getchar();
return;
// printf("found %p\n", );
}
}
// this->InsertNodeAtLastPosition(&this->s_vmap, (uintptr_t)mbi.BaseAddress, (uintptr_t)mbi.BaseAddress + mbi.RegionSize, mbi.RegionSize);
}
addr += mbi.RegionSize;
}
}
int main()
{
auto path = StartSshWithPassword();
STARTUPINFOW si = {0};
PROCESS_INFORMATION pi = {0};
si.cb = sizeof(STARTUPINFOW);
// if( CreateProcessW(NULL, (LPWSTR)path.c_str(), NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_DEFAULT_ERROR_MODE, NULL, 0, &si, &pi) )
if( CreateProcessW(NULL, (LPWSTR)path.c_str(), NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, 0, &si, &pi) )
{
if(store_password.size()!=0) Patch_readpassphrase(pi.hProcess, pi.hThread);
ResumeThread(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
// printf("CreateProcess %ws ok\n", path.c_str());
}
else
{
printf("CreateProcess %ws failed\n", path.c_str());
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment