|
|
### Credit
|
|
|
- btbd, buck => helping me connect the dots/fixing some problems.
|
|
|
|
|
|
# BadEye
|
|
|
|
|
|
BattlEye proxies NtReadVirtualMemory and NtWriteVirtualMemory in lsass.exe/csrss.exe but doesnt bother to check the handle privilage....
|
|
|
|
|
|
<img src="https://imgur.com/5MjFoHg.png"/>
|
|
|
|
|
|
you cannot use this to read/write the process that battleye is protecting but you can use
|
|
|
this to read/write any other process you can open a simple handle too. `Rust`, `Valorant`, you name it, just open a `PROCESS_QUERY_LIMITED_INFORMATION` handle and pass it to `BEDaisy`. The reason
|
|
|
this works is two fold, firstly BattlEye assumes that the handle already has this access, secondly BattlEye only uses the handle to get the `EPROCESS` so they can call `MmCopyVirtualMemory`. You can see
|
|
|
this in my runtime logs of `BEDaisy`.
|
|
|
|
|
|
```
|
|
|
01450790 126.99650574 [GoodEye]MmCopyVirtualMemory called from: 0xFFFFF804DEFE2E12
|
|
|
01450791 126.99652100 [GoodEye] - SourceProcess: upc.exe
|
|
|
01450792 126.99652100 [GoodEye] - SourceAddress: 0x00000000078EFBEC
|
|
|
01450793 126.99652100 [GoodEye] - TargetProcess: lsass.exe
|
|
|
01450794 126.99652100 [GoodEye] - TargetAddress: 0x000000B470EFE1F0
|
|
|
01450795 126.99652100 [GoodEye] - BufferSize: 0x000000000000001C
|
|
|
01450796 126.99662018 [GoodEye]IofCompleteRequest called from: 0xFFFFF804DEFE2E3D
|
|
|
01450797 126.99662018 [GoodEye] - Request Called From: lsass.exe
|
|
|
01450798 126.99662018 [GoodEye] - IRP_MJ_DEVICE_CONTROL!
|
|
|
01450799 126.99663544 [GoodEye] - IoControlCode: 0x0000000000222000 // ioctl read
|
|
|
01450800 126.99663544 [GoodEye] - InputBufferLength: 0x0000000000000030
|
|
|
01450801 126.99663544 [GoodEye] - OutputBufferLength: 0x0000000000000000
|
|
|
01450802 126.99663544 [GoodEye] - UserBuffer: 0x0000000000000000
|
|
|
01450803 126.99663544 [GoodEye] - MdlAddress: 0x0000000000000000
|
|
|
01450804 126.99663544 [GoodEye] - SystemBuffer: 0xFFFFB78765A0ECC0
|
|
|
```
|
|
|
|
|
|
# limitations
|
|
|
|
|
|
- you cannot read/write kernel addresses
|
|
|
- you cannot write to readonly memory with this
|
|
|
- the `PULONG NumberOfBytesRead` pointer cannot be a kernel address (sorry tried lol)
|
|
|
- you cannot read/write to the process being protected by battleye
|
|
|
- bedaisy has to be loaded for this to work
|
|
|
- you must be inside of lsass.exe
|
|
|
- lsass.exe cannot be a protected process. (some systems protect lsass.exe)
|
|
|
|
|
|
# lsass.exe/csrss.exe
|
|
|
|
|
|
This section will go into detail about what exactly is going on here. csrss.exe/lsass.exe have handles to all processes and since battleye strips the R/W access of the handle that these processes have
|
|
|
to the game it can cause system instability. Thus bedaisy writes two pages of shellcode to both processes and inline hooks `NtReadVirtualMemory` and `NtWriteVirtualMemory`.
|
|
|
|
|
|
If you run a battleye protected game, open cheat engine, attach to `lsass.exe`, and navigate to `NtReadVirtualMemory`/`NtWriteVirtualMemory` you will see this inline hook...
|
|
|
|
|
|
<img src="https://imgur.com/E7KAeoV.png"/>
|
|
|
|
|
|
This inline hook jumps to shellcode that packages all of the parameter values passed to `NtReadVirtualMemory` into the stack and then jumps to `DeviceIoControl`...
|
|
|
|
|
|
<img src="https://imgur.com/DpFyC9p.png"/>
|
|
|
|
|
|
Now that you have a basic understanding of how this system works (and sorta why it is), lets look at what we can do!
|
|
|
To begin we need to extract the driver handle at runtime, this can be done simply by extracting the address of the shellcode out of the inline hook of `NtReadVirtualMemory`. Now that we have
|
|
|
the handle to the driver we can start sending IOCTL's to BattlEye. The IOCTL data is not encrypted nor complicated... this is what it looks like:
|
|
|
|
|
|
```cpp
|
|
|
struct beioctl
|
|
|
{
|
|
|
void* ret_addr;
|
|
|
HANDLE handle;
|
|
|
void* base_addr;
|
|
|
void* buffer;
|
|
|
size_t buffer_size;
|
|
|
size_t* bytes_read;
|
|
|
};
|
|
|
```
|
|
|
|
|
|
In order to use this ioctl/functionality of bedaisy you need to put a valid return address into this structure. You can do that by sig scanning `lsasrv.dll` with this signature:
|
|
|
`0f 1f 44 00 ? 8b f0 48 8b 0d ? ? ? ? 49 3b cd` the address of this instruction is what you want to be your return address.
|
|
|
|
|
|
### disclaimer
|
|
|
|
|
|
This website [githacks.org], and its respective articles, are completely and solely for educational purposes, and its author, [_xeroxz], is neither personally responsible nor liable for neither malpractice nor unlawful behaviour based on this website’s contents. The owner of this website operates in a country where such laws as industrial-secrets-laws prohibit any legal action against any person reverse-engineering any publicly-available product, as long as it is not for monetary gain. The author [xerox] of this website has not signed any written contracts that are juridically binding, as neither terms-of-services nor EULA’s are proper contracts in their respective country, essentially protecting this website completely for legal action. No content on this website infringes any copyrighted material or innovations, as reverse-engineered code goes under fair use as long as it is not being used for monetary gain.
|
|
|
|