- [URL]
- Protocol=EOS
- ProtocolDescription=EOS Protocol
- Name=Player
- Map=Index.unr
- LocalMap=Entry.unr
- LobbyMap=Lobby.unr/Lobby_rogue.unr/Lobby_guardian.unr/Lobby_sorceress.unr/Lobby_warrior.unr/Lobby_archer.unr/Lobby_Warlock.unr
- NetBrowseMap=Entry.unr
- Portal=
- MapExt=unr
- EXEName=EOS.exe
- SaveExt=usa
- Class=SBGame.SBRogue
- Character=SBRogue
- HostLogin=192.168.0.103
- PortLogin=12567
- Host=192.168.0.103
- Port=12557
- ;Host=112.216.119.206
- ;Port=12557
- ;Host=192.168.0.202
- HostAlpha=119.205.253.232
- PortAlpha=11476
- [SB]
- NetLogin=true
- NetLoginWorldList=true
- BGMOn=true
- MultiLangAvailables=EN|DE|FR
- MultiLangCode=EN
- [PubNHN.PubNHNService]
- UseSurvey=false
- SurveyWindowWidth=400
- SurveyWindowHeight=500
- CouponWindowX=100
- CouponWindowY=100
- CouponWindowWidth=600
- CouponWindowHeight=479
- HomepageURL=http://eos.hangame.com/
- SecurityPageURL=http://eos.hangame.com/cs/security.nhn
- BannerURL=http://eos.dn.toastoven.net/Banner/
- MobileDownloadURL=http://eos.hangame.com/sendSms/popupSendSms.nhn
- [PubCHN.PubCHNService]
- UseSecondPassword=false
- UseDamageMeter=false
- UseServerNameCheck=true
- HomepageURL=http://eos.changyou.com
- MembershipPageURL=http://member.changyou.com/registerNoSuffix/index.jsp?gametype=eos
- PasswordPageURL=http://member.changyou.com/common/codeAdmin.do
- CertificationPageURL=http://account.changyou.com/fangchenmi/submitlogin.jsp
- RealNamePageURL=http://account.changyou.com/quickRegister/QuickRegDetail.jsp
- CustomerPageURL=http://gm.changyou.com/indexPage.do
- SoulMoneyPointPageURL=http://event.changyou.com/eos/201411/pay/index.shtml
- GameAgreePageURL=http://member.changyou.com/inc/useragreement.html
- BannerURL=http://update.changyou.com/eoscashshop/RecommendItem/
- BannerPageURL=http://update.changyou.com/eoscashshop/ActivePage/
- MobileDownloadURL=http://event.changyou.com/eos/201409/app/index.shtml
- TargetNameScaleMin=0.35
- TargetNameScaleStep=0.01
- [PubTHA.PubTHAService]
- SkipXignCode=false
- HomepageURL=http://www.eos.in.th
- PasswordPageURL=https://auth.gg.in.th/authenticate_v2/ForgotPassword.aspx
- MembershipPageURL=https://auth.gg.in.th/authenticate_v2/GGPlatForm_Register.aspx?appid=41
- BannerURL=http://eos.gg.in.th/ingame/CashShop/
- MobileDownloadURL=http://eos.gg.in.th/gameguide/mobile.aspx
- [PubJPN.PubJPNService]
- SkipXignCode=false
- [PubEUUS.PubEUUSService]
- RechargePMoneyURL=https://billing.aeriagames.com
- BannerURL=http://echoofsoul.patch.aeriagames.com/Notice/
- SecurityPageURL=http://www.aeriagames.com/contact
- [FirstRun]
- FirstRun=3369
- [Engine.Engine]
- ;Publish=PubNHN.PubNHNService
- ;Publish=PubTHA.PubTHAService
- ;Publish=PubCHN.PubCHNService
- ;Publish=PubJPN.PubJPNService
- Publish=PubEUUS.PubEUUSService
- ;Publish=Engine.PubNullService
- RenderDevice=D3DDrv.D3DRenderDevice
- AudioDevice=ALAudio.ALAudioSubsystem
- Console=Engine.Console
- ;GUIController=SBInterface.SBGUIController
- GUIController=GFx4UI.GFx4Controller
- Language=int
- Product=EOS
- GameEngine=Engine.SBGameEngine
- EditorEngine=Editor.EditorEngine
- ViewportManager=WinDrv.WindowsClient
- [Core.System]
- PurgeCacheDays=30
- SavePath=..\Save
- CachePath=../Cache
- CacheExt=.uxx
- CacheRecordPath=../System/*.ucl
- MusicPath=../Data/Sounds
- MusicPath=../Data/Voices
- GUIPath=../Data/UI
- Paths=../Data/Textures/*.utx
- Paths=../Data/Sounds/*.uax
- Paths=../Data/Animations/*.ukx
- Paths=../Data/StaticMeshes/*.usx
- Paths=../Data/Voices/*.uax
- Paths=../Data/Maps/*.unr
- Paths=../Data/UI/*.ugx
- Paths=../System/*.u
- Paths=../Data/Textures/FX/*.utx
- Paths=../Data/Textures/Monster/*.utx
- Paths=../Data/Animations/Monster/*.ukx
- Paths=../Data/Textures/PC/Guardian/*.utx
- Paths=../Data/Animations/PC/Guardian/*.ukx
- Paths=../Data/Textures/PC/Rogue/*.utx
- Paths=../Data/Animations/PC/Rogue/*.ukx
- Paths=../Data/Textures/PC/Sorceress/*.utx
- Paths=../Data/Animations/PC/Sorceress/*.ukx
- Paths=../Data/Textures/PC/Warrior/*.utx
- Paths=../Data/Animations/PC/Warrior/*.ukx
- Paths=../Data/Textures/PC/Warlock/*.utx
- Paths=../Data/Animations/PC/Warlock/*.ukx
- Paths=../Data/Textures/PC/Archer/*.utx
- Paths=../Data/Animations/PC/Archer/*.ukx
- Paths=../Data/Textures/NPC/*.utx
- Paths=../Data/Animations/NPC/*.ukx
- Paths=../Data/Textures/Etc/*.utx
- Paths=../Data/Animations/Etc/*.ukx
- Paths=../Data/Textures/Pet/*.utx
- Paths=../Data/Animations/Pet/*.ukx
- Paths=../Data/Textures/BG/*.utx
- Paths=../Data/Animations/BG/*.ukx
- Paths=../Data/Animations/Cut/*.ukx
- Paths=../Data/Textures/WorldMap/*.utx
- Paths=../Data/Textures/L10N/*.utx
- Paths=../Data/Textures/UI/*.utx
- Paths=../../System/*.u
- Paths=../../Data/Maps/*.unr
- Paths=../../Data/Textures/*.utx
- Paths=../../Data/Textures/FX/*.utx
- Paths=../../Data/Sounds/*.uax
- Paths=../../Data/Voices/*.uax
- Paths=../../Data/StaticMeshes/*.usx
- Paths=../../Data/Animations/*.ukx
- Paths=../../Data/UI/*.ugx
- Paths=../DataNext/Textures/*.utx
- Paths=../DataNext/Sounds/*.uax
- Paths=../DataNext/Animations/*.ukx
- Paths=../DataNext/StaticMeshes/*.usx
- Paths=../DataNext/Voices/*.uax
- Paths=../DataNext/Maps/*.unr
- Paths=../DataNext/UI/*.ugx
- Paths=../DataNext/Textures/FX/*.utx
- Paths=../DataNext/Textures/Monster/*.utx
- Paths=../DataNext/Animations/Monster/*.ukx
- Paths=../DataNext/Textures/PC/Guardian/*.utx
- Paths=../DataNext/Animations/PC/Guardian/*.ukx
- Paths=../DataNext/Textures/PC/Rogue/*.utx
- Paths=../DataNext/Animations/PC/Rogue/*.ukx
- Paths=../DataNext/Textures/PC/Sorceress/*.utx
- Paths=../DataNext/Animations/PC/Sorceress/*.ukx
- Paths=../DataNext/Textures/PC/Warrior/*.utx
- Paths=../DataNext/Animations/PC/Warrior/*.ukx
- Paths=../DataNext/Textures/PC/Archer/*.utx
- Paths=../DataNext/Animations/PC/Archer/*.ukx
- Paths=../DataNext/Textures/PC/Warlock/*.utx
- Paths=../DataNext/Animations/PC/Warlock/*.ukx
- Paths=../DataNext/Textures/NPC/*.utx
- Paths=../DataNext/Animations/NPC/*.ukx
- Paths=../DataNext/Textures/Etc/*.utx
- Paths=../DataNext/Animations/Etc/*.ukx
- Paths=../DataNext/Textures/Pet/*.utx
- Paths=../DataNext/Animations/Pet/*.ukx
- Paths=../DataNext/Textures/BG/*.utx
- Paths=../DataNext/Animations/BG/*.ukx
- Paths=../DataNext/Animations/Cut/*.ukx
- Paths=../DataNext/Textures/WorldMap/*.utx
- Paths=../DataNext/Textures/L10N/*.utx
- Paths=../DataNext/Textures/UI/*.utx
- Paths=../../System/*.u
- Paths=../../Data/Maps/*.unr
- Paths=../../Data/Textures/*.utx
- Paths=../../Data/Textures/FX/*.utx
- Paths=../../Data/Sounds/*.uax
- Paths=../../Data/Voices/*.uax
- Paths=../../Data/StaticMeshes/*.usx
- Paths=../../Data/Animations/*.ukx
- Paths=../../Data/Saves/*.uvx
- Paths=../../Data/UI/*.ugx
- Suppress=DevLoad
- Suppress=DevSave
- Suppress=DevNetTraffic
- Suppress=DevGarbage
- Suppress=DevKill
- Suppress=DevReplace
- Suppress=DevCompile
- Suppress=DevBind
- Suppress=DevBsp
- Suppress=DevNet
- Suppress=RecordCache
- Suppress=MapVoteDebug
- suppress=MapVote
- Suppress=Timer
- MusicPath=../Data/Voices/EN
- Paths=../Data/Voices/EN/*.uax
- Paths=../../Data/Voices/EN/*.uax
- [Engine.GameEngine]
- CacheSizeMegs=32
- UseSound=True
- UseStaticMeshBatching=false
- MainMenuClass=SBInterface.MainMenu
- SinglePlayerMenuClass=SBInterface.MainMenu
- ConnectingMenuClass=SBInterface.SBLevelLoading
- DisconnectMenuClass=
- LoadingClass=SBInterface.SBLevelLoading
- [WinDrv.WindowsClient]
- Brightness=0.500000
- Contrast=0.500000
- Gamma=1.000000
- UseJoystick=False
- CaptureMouse=False
- NoLighting=False
- MinDesiredFrameRate=35.000000
- AnimMeshDynamicLOD=0.000000
- Decals=True
- Coronas=True
- DecoLayers=True
- Projectors=True
- NoDynamicLights=False
- ReportDynamicUploads=False
- TextureDetailInterface=UltraHigh
- TextureDetailTerrain=UltraHigh
- TextureDetailWeaponSkin=UltraHigh
- TextureDetailPlayerSkin=UltraHigh
- TextureDetailWorld=UltraHigh
- TextureDetailRenderMap=UltraHigh
- TextureDetailLightmap=UltraHigh
- NoFractalAnim=False
- MouseXMultiplier=1.000
- MouseYMultiplier=1.000
- UseSpeechRecognition=True
- WeatherEffects=True
- DrawDistanceLOD=1.0
- [ALAudio.ALAudioSubsystem]
- UseEAX=True
- Use3DSound=True
- UseDefaultDriver=True
- MaxEAXVersion=255
- UsePrecache=True
- ReverseStereo=False
- Channels=128
- PlaybackLimit=7
- MusicVolume=1.00000
- AmbientVolume=1.000000
- SoundVolume=1.00000
- VolumeScaleRec=0.100000
- DopplerFactor=1.0
- Rolloff=0.5
- TimeBetweenHWUpdates=15
- DisablePitch=False
- LowQualitySound=False
- LocalZOffset=0.0
- [D3DDrv.D3DRenderDevice]
- DetailTextures=True
- HighDetailActors=True
- SuperHighDetailActors=True
- UsePrecaching=True
- UseTrilinear=True
- AdapterNumber=-1
- ReduceMouseLag=False
- UseTripleBuffering=False
- UseHardwareTL=True
- UseHardwareVS=True
- UseCubemaps=True
- DesiredRefreshRate=60
- UseCompressedLightmaps=True
- UseStencil=False
- Use16bit=False
- Use16bitTextures=False
- MaxPixelShaderVersion=255
- LevelOfAnisotropy=1
- TesselationFactor=1.0
- CheckForOverflow=False
- AvoidHitches=False
- OverrideDesktopRefreshRate=False
- ReportUnusedTextures=False
- [Editor.EditorEngine]
- UseSound=True
- CacheSizeMegs=32
- GridEnabled=True
- SnapVertices=False
- SnapDistance=1.000000
- GridSize=(X=4.000000,Y=4.000000,Z=4.000000)
- RotGridEnabled=True
- RotGridSize=(Pitch=1024,Yaw=1024,Roll=1024)
- GameCommandLine=-log
- FovAngleDegrees=90.000000
- GodMode=True
- AutoSave=True
- AutoSaveTimeMinutes=5
- AutoSaveIndex=6
- UseAxisIndicator=True
- MatineeCurveDetail=0.1
- ShowIntWarnings=False
- UseSizingBox=True
- RenderDevice=D3D9Drv.D3D9RenderDevice
- AudioDevice=ALAudio.ALAudioSubsystem
- Console=Engine.Console
- Language=ute
- AlwaysShowTerrain=False
- UseActorRotationGizmo=False
- LoadEntirePackageWhenSaving=0
- EditPackages=Core
- EditPackages=Engine
- EditPackages=Fire
- EditPackages=Editor
- EditPackages=UnrealEd
- EditPackages=GamePlay
- EditPackages=GUI
- ;EditPackages=SBScene
- ;EditPackages=SBEffect
- ;EditPackages=SBGame
- ;EditPackages=SBSkillEffect
- ;EditPackages=SBInterface
- CutdownPackages=Core
- CutdownPackages=Editor
- CutdownPackages=Engine
- CutdownPackages=Fire
- CutdownPackages=UnrealEd
- CutdownPackages=GamePlay
- CutdownPackages=GUI
- CutdownPackages=SBEffect
- CutdownPackages=SBGame
- CutdownPackages=SBSkillEffect
- [Engine.AmbientSound]
- AmbientVolume=0.25
- [Engine.LevelInfo]
- PhysicsDetailLevel=PDL_Medium
- MeshLODDetailLevel=MDL_Medium
- bLowSoundDetail=False
- [UnrealEd.UnrealEdEngine]
- UseStaticMeshBatching=False
- [LevelLoadingData]
- Entry=37
- Sp_Cube_Forest001Map=404
To start, the main game executable (and several other files) are protected with Themida. I'm not going to cover how to unpack that since there are plenty of tutorials on the net for that. It's nothing special and easily removed with some automated scripts/tools.
Once unpacked, I dug around for the routines that handle the ini files. After some digging, I discovered that EoS is using a custom bit of xor'ing and using Microsoft's Enhanced Cryptographic provider.
First, I found the creation of the provider. This setups up the needed hash/key and provider objects needed to do the decryption and encryption of the data. The setup they do is as follow:
- if ( !CryptAcquireContextW(
- (HCRYPTPROV *)(a1 + 4208),
- L"SBENCRYPTIONKEYCONTAINER10",
- L"Microsoft Enhanced Cryptographic Provider v1.0",
- 1u,
- 0)
- && GetLastError() == 0x80090016 )
- CryptAcquireContextW((HCRYPTPROV *)(a1 + 4208), L"SBENCRYPTIONKEYCONTAINER10", 0, 1u, 8u);
- if ( !*(_DWORD *)(a1 + 4208) )
- {
- v4 = GetLastError();
- sub_E4B130(L"CryptAcquireContext failed. %08x", v4);
- }
- v5 = (HCRYPTHASH *)(a1 + 4216);
- if ( CryptCreateHash(*(_DWORD *)(a1 + 4208), 0x8003u, 0, 0, (HCRYPTHASH *)(a1 + 4216))
- && CryptHashData(*v5, &pbData, 8u, 0)
- && CryptDeriveKey(*(_DWORD *)(a1 + 4208), 0x6801u, *v5, (DWORD)&loc_800000, (HCRYPTKEY *)(a1 + 4212)) )
- v9 = 0;
- else
- LOBYTE(v9) = 0;
- return a1;
- v2 = (const CHAR *)sub_E2DF80(lpFileName);
- v3 = CreateFileA(v2, 0x80000000, 1u, 0, 3u, 0x80u, 0);
- if ( v3 == (HANDLE)-1
- || (NumberOfBytesRead = 0,
- v9 = 0xD0B7A0CC,
- ReadFile(v3, Buffer, 4u, &NumberOfBytesRead, 0),
- CloseHandle(v3),
- NumberOfBytesRead != 4) )
- {
- LABEL_8:
- result = 0;
- }
- else
- {
- for ( i = 0; ; ++i )
- {
- v7 = i;
- if ( i >= 4 )
- break;
- if ( Buffer[i] != *((_BYTE *)&v9 + i) )
- goto LABEL_8;
- }
- result = 1;
- }
- return result;
Afterward, the file is then decrypted using:
- NumberOfBytesRead = 0;
- ReadFile(*(HANDLE *)(v4 + 88), (LPVOID)(v4 + 116), 0x400u, &NumberOfBytesRead, 0);
- if ( (signed int)NumberOfBytesRead >= 8 )
- {
- v23 = NumberOfBytesRead >> 3;
- do
- {
- sub_409810(*(_DWORD *)(v4 + 1144), v13);
- v13 += 8;
- --v23;
- }
- while ( v23 );
- }
- int __usercall sub_409810@<eax>(HCRYPTKEY hKey@<ecx>, int a2@<esi>)
- {
- signed int v2; // ecx@1
- int v3; // eax@2
- int result; // eax@3
- int v5; // [sp+0h] [bp-4h]@1
- v5 = 8;
- CryptDecrypt(hKey, 0, 1, 0, (BYTE *)a2, (DWORD *)&v5);
- v2 = 0;
- do
- {
- LOBYTE(v3) = *(_BYTE *)(v2 + a2);
- if ( (_BYTE)v3 == 127 )
- {
- result = 0;
- }
- else if ( (_BYTE)v3 == -128 )
- {
- result = 255;
- }
- else
- {
- v3 = (unsigned __int8)v3;
- if ( (unsigned __int8)v3 >= 0x80u )
- result = v3 - 1;
- else
- result = v3 + 1;
- }
- *(_BYTE *)(v2++ + a2) = result;
- }
- while ( v2 < 8 );
- *(_DWORD *)a2 ^= 0xA4A7FF88;
- *(_DWORD *)(a2 + 4) ^= 0xA0447823;
- return result;
- }
- Create the crypto provider for decryption.
- Read the first 4 bytes of the file and look for the key: 0xD0B7A0CC
- Loop the file data and decrypt it.
- Xor the decrypted data with the keys: 0xA4A7FF88 and 0xA0447823
And then at that point we now have the decrypted file. For example the EoS.ini file is encrypted, running it through this will give us the full file which looks like: