Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added dump-win tool #11

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@ They are used to develop [librespot](https://github.com/plietar/librespot), an o
The `spotify-dump` tool intercepts packets by the Spotify desktop client before they are encrypted or after they are decrypted.
It works by patching the `shn_encrypt` and `shn_decrypt` routines of the client at run time.

This currently only works on 64 bit OS X/Linux.
##### MacOS/Linux 64 bit

To use, quit the Spotify application, and execute the `dump.sh` script with the path the spotify binary.

```
~/spotify-analyze/dump> ./dump.sh /Applications/Spotify.app/Contents/MacOS/Spotify
```

###### Windows 64 bit

Build the solution and make sure `injector.exe` and `core.dll` are located in the same folder as `Spotify.exe`.

To use, quit the Spotify application, execute the `injector.exe` and then Spotify app.


This will produce a `dump.pcap` in the current directory, which can be analyzed by the `spotify-dissect` tool.

## spotify-dump-http
Expand Down
164 changes: 164 additions & 0 deletions dump-win/core/core.vcxproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?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>{1fb90cce-1dd3-452b-88fa-e29f616b6a24}</ProjectGuid>
<RootNamespace>core</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</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" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;CORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;CORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;CORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;CORE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pcap.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="shn.h" />
<ClInclude Include="utils.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pcap.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="shn.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
51 changes: 51 additions & 0 deletions dump-win/core/core.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="shn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pcap.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="shn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pcap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
4 changes: 4 additions & 0 deletions dump-win/core/core.vcxproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
133 changes: 133 additions & 0 deletions dump-win/core/dllmain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "pch.h"

#include "pcap.h"
#include "shn.h"
#include "utils.h"

// 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83
// EC 20 8B ?? CC 00 00 00
static const char *pattern =
"\x48\x89\x5c\x24\x08\x48\x89\x6c\x24\x10\x48\x89\x74\x24\x18\x57\x41\x54"
"\x41\x55\x41\x56\x41\x57\x48\x83\xec\x20\x8b\x00\xcc\x00\x00\x00";

static const char *mask = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx?xxxx";

#define DIRECTION_SEND 0
#define DIRECTION_RECV 1

static HANDLE dump_fd;

typedef void(__cdecl *shn_decrypt_t)(shn_ctx *, UCHAR *, int);
shn_decrypt_t shn_decrypt_stub = nullptr;

typedef void(__cdecl *shn_encrypt_t)(shn_ctx *, UCHAR *, int);
shn_encrypt_t shn_encrypt_stub = nullptr;

int gettimeofday(struct timeval *tp, struct timezone *tzp) {
// note: some broken versions only have 8 trailing zero's, the correct epoch
// has 9 trailing zero's this magic number is the number of 100 nanosecond
// intervals since january 1, 1601 (utc) until 00:00:00 january 1, 1970
static const uint64_t epoch = ((uint64_t)116444736000000000ull);

SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;

GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;

tp->tv_sec = (long)((time - epoch) / 10000000l);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}

void __cdecl shn_decrypt_proxy(shn_ctx *c, UCHAR *buf, int nBytes) {
shn_decrypt(c, buf, nBytes);

#pragma pack(push, 1)
static struct {
uint8_t cmd;
uint16_t length;
} header = {0, 0};
#pragma pack(pop)

if (header.cmd == 0) {
if (nBytes == 3)
memcpy(&header, buf, 3);
} else {
if (nBytes == ntohs(header.length)) {
struct timeval tv;
gettimeofday(&tv, NULL);
pcap_write_packet_header(dump_fd, &tv, 4 + nBytes);

uint8_t direction = DIRECTION_RECV;
WriteFile(dump_fd, &direction, 1, NULL, NULL);
WriteFile(dump_fd, &header, 3, NULL, NULL);
WriteFile(dump_fd, buf, nBytes, NULL, NULL);
}

header.cmd = 0;
}
}

void __cdecl shn_encrypt_proxy(shn_ctx *c, UCHAR *buf, int nBytes) {
struct timeval tv;
gettimeofday(&tv, NULL);
pcap_write_packet_header(dump_fd, &tv, 1 + nBytes);

uint8_t direction = DIRECTION_SEND;
WriteFile(dump_fd, &direction, 1, NULL, NULL);
WriteFile(dump_fd, buf, nBytes, NULL, NULL);

shn_encrypt(c, buf, nBytes);
}

DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {
MODULEINFO mInfo = utils::GetModuleInfo(NULL);

auto shn_decrypt = utils::FindPattern(
pattern, mask, (char *)mInfo.lpBaseOfDll, mInfo.SizeOfImage);

if (shn_decrypt == nullptr) {
MessageBoxA(NULL, "shn_decrypt is nullptr", "error", MB_ICONERROR);
return 1;
}

char *newPos = (char *)(shn_decrypt + strlen(mask));

uintptr_t newSize = mInfo.SizeOfImage -
((uintptr_t)shn_decrypt - (uintptr_t)mInfo.lpBaseOfDll) -
strlen(mask);

auto shn_encrypt = utils::FindPattern(pattern, mask, newPos, newSize);

if (shn_decrypt == nullptr) {
MessageBoxA(NULL, "shn_encrypt is nullptr", "error", MB_ICONERROR);
return 1;
}

dump_fd = CreateFileA("dump.pcap", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);

pcap_write_header(dump_fd, PCAP_DLT_USER0);

shn_encrypt_stub = (shn_encrypt_t)utils::InstallHook(
(void *)shn_encrypt, (void *)shn_encrypt_proxy);

shn_decrypt_stub = (shn_decrypt_t)utils::InstallHook(
(void *)shn_decrypt, (void *)shn_decrypt_proxy);

return 0;
};

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
LPVOID lpReserved) {

if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
CreateThread(NULL, 0, &ThreadProc, NULL, 0, NULL);
}

return TRUE;
}
5 changes: 5 additions & 0 deletions dump-win/core/framework.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
Loading