I'm making the pac-man with the winapi32, and using XAudio2 API for playing multiple sounds simultanueosly. I played my sound file pacman_beginning.wav, pacman_death.wav, pacman_chomp.wav, pacman_eatfruit.wav, pacman_eatghost.wav, pacman_intermission.wav, pacman_siren.wav, and all of them worked fine, but pacman_siren.wav (I download them from Pac-Man Sounds, and Pacman Sound Effects, and pacman_siren.wav is renamed from 8d82b5_Pacman_Siren_Sound_Effect.wav ).
the following is part of my code(for XAudio2, I referred to How to: Play a Sound with XAudio2
)
PacmanApp.hpp:
////////////////////
// PacmanApp //
////////////////////
# include<Windows.h>
# include<functional>
# include<xaudio2.h>
# include<vector>
# include"resource.h" // `IDB_BITMAP1` is defined.
class PacmanApp {
struct AudioData {
BYTE* pDataBuffer;
DWORD dwChunkSize;
IXAudio2SourceVoice* pSourceVoice;
WAVEFORMATEXTENSIBLE wfx;
};
using Delegate = std::function<void(HDC,HDC)>;
// the window procedure.
static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
// find chunk from `fFile`.
static HRESULT FindChunk(HANDLE hFile, DWORD fourcc, DWORD& dwChunkSize, DWORD dwChunkDataPosition);
// read chunk data from `fFile`.
static HRESULT ReadChunkData(HANDLE hFile, void* buffer, DWORD bufferSize, DWORD bufferoffset);
private:
// for message loop.
HINSTANCE hInstance = NULL;
HWND hwnd = NULL;
WNDCLASS wc = { 0 };
MSG msg = { 0 };
// for rendering.
HBITMAP hBM = NULL; // for pac-man sprite.
HBITMAP hBM2 = NULL; // for back-buffer.
RECT rect;
BITMAP bm;
// for application
Delegate callbackFn = nullptr; // callback function.
bool keyState[255] = { 0 }; // for key-down events.
bool isTimeout[256] = { 0 }; // for timer events.
// for sound.
IXAudio2* pXAudio2 = nullptr;
IXAudioMasteringVoice* pMasterVoice = nullptr;
XAUDIO2_BUFFER buffer = { 0 };
std::vector<AudioData> audioList;
private:
PacmanApp() = default;
PacmanApp(const PacmanApp&) = delete;
PacmanApp(PacmanApp&&) = delete;
~PacmanApp() {
if(hBM) DeleteObject(hBM);
if(hBM2) DeleteObject(hBM2);
for(auto& i : audioList) {
delete[] i.pDataBuffer;
}
}
public:
static PacmanApp inst; // for single-ton.
// initialize the pacman application.
bool Init(HINSTANCE hInstance, int nWidth, int nHeight);
// load the desired sound file.
bool LoadSound(const wchar_t strFileName[]);
// start the sound identified by `sndID`.
bool StartSound(UINT sndID, float playLength);
// run the pacman application.
template<typename Functor>
void Run(Functor&& callbackFn, int nCmdShow, UINT fps){
if(this->callbackFn = std::forward<Functor>(callbackFn) ) {
ShowWindow(hwnd, nCmdShow);
SetTimer(hwnd, 256, (1000 / fps), NULL);
while(GetMessage(&msg, 0, 0, 0) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
KillTimer(hwnd, 256);
}
}
/* omitted */
};
PacmanApp.cpp:
# include"PacmanApp.hpp"
#ifdef _XBOX //Big-Endian
# define fourccRIFF 'RIFF'
# define fourccDATA 'data'
# define fourccFMT 'fmt '
# define fourccWAVE 'WAVE'
# define fourccXWMA 'XWMA'
# define fourccDPDS 'dpds'
#endif
#ifndef _XBOX //Little-Endian
# define fourccRIFF 'FFIR'
# define fourccDATA 'atad'
# define fourccFMT ' tmf'
# define fourccWAVE 'EVAW'
# define fourccXWMA 'AMWX'
# define fourccDPDS 'sdpd'
#endif
// for single-ton.
PacmanApp PacmanApp::inst;
// initialize the pac-man application.
bool PacmanApp::Init(HINSTANCE hInstance, int nWidth, int nHeight) {
/* ommitted. RegisterClass, CreateWindowEx, etc is here. */
// init COM
if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)) ) {
return false;
}
// create XAudio engine.
if (FAILED(XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR) ) ) {
return false;
}
// create mastering voice.
if (FAILED(pXAudio2->CreateMasteringVoice(&pMasterVoice) ) ) {
return false;
}
return true;
}
// find chunk from `fFile`.
HRESULT PacmanApp::FindChunk(HANDLE hFile, DWORD fourcc, DWORD& dwChunkSize, DWORD& dwChunkDataPosition) {
HRESULT hr = S_OK;
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) {
return HRESULT_FROM_WIN32(GetLastError() );
}
DWORD dwChunkType;
DWORD dwChunkDataSize;
DWORD dwRIFFDataSize = 0;
DWORD dwFileType;
DWORD bytesRead = 0;
DWORD dwOffset = 0;
while (hr == S_OK) {
DWORD dwRead;
// read ChunkID.
if (0 == ReadFile(hFile, &dwChunkType, sizeof(DWORD), &dwRead, NULL)) {
hr = HRESULT_FROM_WIN32(GetLastError() );
}
// read ChunkDataSize.
if(0 == ReadFile(hFile, &dwChunkDataSize, sizeof(DWORD), &dwRead, NULL) ) {
hr = HRESULT_FROM_WIN32(GetLastError() );
}
if (dwChunkType == fourccRIFF) {
dwRIFFDataSize = dwChunkDataSize;
dwChunkDataSize = 4;
// read RIFFType.
if (0 == ReadFile(hFile, &dwFileType, sizeof(DWORD), &dwRead, NULL) ) {
hr = HRESULT_FROM_WIN32(GetLastError() );
}
}
else {
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, dwChunkDataSize, NULL, FILE_CURRENT) ) {
return HRESULT_FROM_WIN32(GetLastError() );
}
}
dwOffset += sizeof(DWORD) * 2;
if (dwChunkType == fourcc) {
dwChunkSize = dwChunkDataSize;
dwChunkDataPosition = dwOffset;
return S_OK;
}
dwOffset += dwChunkDataSize;
if (bytesRead >= dwRIFFDataSize) {
return S_FALSE;
}
}
return S_OK;
}
// read chunk data from `hFile`.
HRESULT PacmanApp::ReadChunkData(HANDLE hFile, void* buffer, DWORD buffersize, DWORD bufferoffset) {
HRESULT hr = S_OK;
DWORD dwRead;
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, bufferoffset, NULL, FILE_BEGIN) ) {
return HRESULT_FROM_WIN32(GetLastError() );
}
if (0 == ReadFile(hFile, buffer, buffersize, &dwRead, NULL) ) {
hr = HRESULT_FROM_WIN32(GetLastError() );
}
return hr;
}
// load the desired sound file.
bool PacmanApp::LoadSound(const wchar_t strFileName[]) {
HANDLE hFile = CreateFile(
strFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (INVALID_HANDLE_VALUE == hFile) {
return false;
}
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_BEGIN) ) {
CloseHandle(hFile);
return false;
}
DWORD dwChunkSize;
DWORD dwChunkPosition;
DWORD filetype;
WAVEFORMATEXTENSIBLE wfx = { 0 };
// check the file type, should be fourccWAVE or 'XWMA'
FindChunk(hFile, fourccRIFF, dwChunkSize, dwChunkPosition);
ReadChunkData(hFile, &filetype, sizeof(DWORD), dwChunkPosition);
if (filetype != fourccWAVE) {
CloseHandle(hFile);
return false;
}
FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition);
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);
// fill out the audio data buffer with the contents of the fourccDATA
FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition);
audioList.push_back({
new BYTE[dwChunkSize],
dwChunkSize,
nullptr,
wfx
});
ReadChunkData(hFile, audioList.back().pDataBuffer, dwChunkSize, dwChunkPosition);
CloseHandle(hFile);
return true;
}
// start the sound identified by `sndID`.
bool PacmanApp::StartSound(UINT sndID, float playLength) { // playLength is in [0, 1.0f]
if (sndID < audioList.size() ) {
auto& curAudio = audioList[sndID];
buffer.AudioBytes = curAudio.dwChunkSize; // size of the audio buffer in bytes.
buffer.pAudioData = curAudio.pDataBuffer; // buffer containing audio data.
buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after the buffer.
buffer.PlayBegin = 0;
buffer.PlayLength = curAudio.dwChunkSize * playLength;
HRESULT hr;
if (FAILED(hr = pXAudio2->CreateSourceVoice(&curAudio.pSourceVoice, (WAVEFORMATEX*)&curAudio.wfx)) ) {
return false;
}
if (FAILED(hr = curAudio.pSourceVoice->SubmitSourceBuffer(&buffer) ) ) {
return false;
}
if (FAILED(hr = curAudio.pSourceVoice->Start(0) ) ) {
return false;
}
}
return true;
}
main.cpp:
# include"PacmanApp.hpp"
# include"PacmanObject.hpp"
/////////////////////
// wWinMain //
/////////////////////
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR nCmdLine,
_In_ int nCmdShow)
{
if(!PacmanApp::inst.Init(hInstance, 1400, 650) {
return 0;
}
/* omitted */
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_beginning.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_death.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_chomp.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_eatfruit.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_eatghost.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_intermission.wav");
PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_siren.wav");
enum struct PacmanSound : UINT {
INTRO, DEATH, CHOMP, EAT_FRUIT, EAT_GHOST, INTERMISSION, SIREN
};
// main loop.
PacmanApp::inst.Run([&](HDC srcDC, HDC destDC) {
PacmanApp::inst.StartSound((UINT)PacmanSound::INTRO, 1.0f); // OK. rest of them is same ,but..
// PacmanApp::inst.StartSound((UINT)PacmanSound::SIREN, 1.0f); // only this statement returns false.
}, nCmdShow, 60);
}
In the beginning, I thought that LoadSound have some problem. but,
pacman_beginning.wav:
hex dump:
52 49 46 46 EA B5 00 00 57 41 56 45 66 6D 74 20 RIFF....WAVEfmt
10 00 00 00 01 00 01 00 11 2B 00 00 11 2B 00 00 .........+...+..
01 00 08 00 64 61 74 61 9A B5 00 00 80 7F 80 7F ....data........
WAV format reader output:
C:\Users\user>"C:\Users\user\Desktop\WAV format reader\x64\Debug\WAV format reader.exe" "C:\Users\user\Desktop\pacman_beginning.wav"
WAVE file C:\Users\user\Desktop\pacman_beginning.wav
riff 'WAVE', chunk 'fmt ', 16 bytes
format tag 0001 (PCM)
number of channels 1
samples per second 11025
avg bytes per second 11025
sample block size 1 bytes
bits per sample 8
when PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_beginning.wav"); is excuting:
FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x10, dwChunkPosition => 0x14
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);
// fill out the audio data buffer with the contents of the fourccDATA
FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x0x0000b59a, dwChunkPosition => 0x0000002c
audioList.push_back({
new BYTE[dwChunkSize],
dwChunkSize,
nullptr,
wfx
});
the LoadSound result:
auto& curAudio = audioList.back();
curAudio.dwChunkSize = 46490
curAudio.wfx.Format = {
.wFormatTag = 1,
.nChannels = 1,
.nSamplesPerSec = 11025,
.nAvgBytesPerSec = 11025,
.nBlockAlign = 1,
.wBitsPerSample = 8,
.cbSize = 0
}
pacman_death.wav:
hex dump:
52 49 46 46 68 42 00 00 57 41 56 45 4C 49 53 54 RIFFhB..WAVELIST
28 00 00 00 49 4E 46 4F 49 53 46 54 1C 00 00 00 (...INFOISFT....
57 48 41 4D 20 31 2E 33 31 20 62 79 20 41 6E 64 WHAM 1.31 by And
72 65 77 20 42 75 6C 68 61 6B 00 00 66 6D 74 20 rew Bulhak..fmt
10 00 00 00 01 00 01 00 11 2B 00 00 11 2B 00 00 .........+...+..
01 00 08 00 64 61 74 61 14 42 00 00 80 80 82 7F ....data.B......
WAV format reader output:
C:\Users\user>"C:\Users\user\Desktop\WAV format reader\x64\Debug\WAV format reader.exe" "C:\Users\user\Desktop\pacman_death.wav"
WAVE file C:\Users\user\Desktop\pacman_death.wav
riff 'WAVE', chunk 'fmt ', 16 bytes
format tag 0001 (PCM)
number of channels 1
samples per second 11025
avg bytes per second 11025
sample block size 1 bytes
bits per sample 8
when PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_death.wav"); is excuting:
FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x10, dwChunkPosition => 0x44
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);
// fill out the audio data buffer with the contents of the fourccDATA
FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x00004214, dwChunkPosition => 0x0000005c
audioList.push_back({
new BYTE[dwChunkSize],
dwChunkSize,
nullptr,
wfx
});
the LoadSound result:
auto& curAudio = audioList.back();
curAudio.dwChunkSize = 16916
curAudio.wfx.Format = {
.wFormatTag = 1,
.nChannels = 1,
.nSamplesPerSec = 11025,
.nAvgBytesPerSec = 11025,
.nBlockAlign = 1,
.wBitsPerSample = 8,
.cbSize = 0
}
pacman_siren.wav:
hex dump:
52 49 46 46 54 3B 01 00 57 41 56 45 66 6D 74 20 RIFFT;..WAVEfmt
10 00 00 00 01 00 01 00 22 56 00 00 44 AC 00 00 ........"V..D...
02 00 10 00 4C 49 53 54 28 00 00 00 49 4E 46 4F ....LIST(...INFO
49 47 4E 52 06 00 00 00 4F 74 68 65 72 00 49 53 IGNR....Other.IS
46 54 0E 00 00 00 4C 61 76 66 35 39 2E 32 37 2E FT....Lavf59.27.
31 30 30 00 64 61 74 61 00 3B 01 00 00 00 00 00 100.data.;......
WAV format reader output:
C:\Users\user>"C:\Users\user\Desktop\WAV format reader\x64\Debug\WAV format reader.exe" "C:\Users\user\Desktop\pacman_siren.wav"
WAVE file C:\Users\user\Desktop\pacman_siren.wav
riff 'WAVE', chunk 'fmt ', 16 bytes
format tag 0001 (PCM)
number of channels 1
samples per second 22050
avg bytes per second 44100
sample block size 2 bytes
bits per sample 16
when PacmanApp::inst.LoadSound(L"C:/Users/user/Desktop/pacman_siren.wav"); is excuting:
FindChunk(hFile, fourccFMT, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x10, dwChunkPosition => 0x14
ReadChunkData(hFile, &wfx, dwChunkSize, dwChunkPosition);
// fill out the audio data buffer with the contents of the fourccDATA
FindChunk(hFile, fourccDATA, dwChunkSize, dwChunkPosition); // result: dwChunkSize => 0x00013b00, dwChunkPosition => 0x0000005c
audioList.push_back({
new BYTE[dwChunkSize],
dwChunkSize,
nullptr,
wfx
});
the LoadSound result:
auto& curAudio = audioList.back();
curAudio.dwChunkSize = 80640
curAudio.wfx.Format = {
.wFormatTag = 1,
.nChannels = 1,
.nSamplesPerSec = 22050,
.nAvgBytesPerSec = 44100,
.nBlockAlign = 2,
.wBitsPerSample = 16,
.cbSize = 0
}
every calls to LoadSound work correctly. so, I think there is not any WAVEFORMATEX structure corruption, or incorrect uninitialized data.SubmitSourceBuffer is failed when onlysndID = PacmanSound::SIREN:
bool PacmanApp::StartSound(UINT sndID, float playLength) { // sndID = 6 (=PacmanSound::SIREN)
/* omitted */
HRESULT hr;
if (FAILED(hr = pXAudio2->CreateSourceVoice(&curAudio.pSourceVoice, (WAVEFORMATEX*)&curAudio.wfx)) ) {
return false;
}
if (FAILED(hr = curAudio.pSourceVoice->SubmitSourceBuffer(&buffer) ) ) {
return false; // hr is XAUDIO2_E_INVALID_CALL (=0x88960001)
}
if (FAILED(hr = curAudio.pSourceVoice->Start(0) ) ) {
return false;
}
/* omitted */
}
MSDN says
Returned by XAudio2 for certain API usage errors (invalid calls and so on) that are hard to avoid completely and should be handled by a title at runtime. (API usage errors that are completely avoidable, such as invalid parameters, cause an ASSERT in debug builds and undefined behavior in retail builds, so no error code is defined for them.)
But, I don't know what I'm missing.. Could anyone help me to solve this issue??.
23/01/29 EDIT:
add wavdump.cpp outputs, and LoadSound results.
I believe the problem you are having is that buffer.PlayLength is not valid. You are currently using:
buffer.PlayLength = curAudio.dwChunkSize * playLength;
This means you are setting it in terms of BYTES. Both PlayLength and LoopLength must be in terms of SAMPLES.
First, try using buffer.PlayLength = 0; to verify it works.
Computing sample counts is challenging in a general case, but I have code for it in the DirectX Tool Kit for Audio in SoundEffect.cpp for PCM, ADPCM, xWMA, and XMA2.
For PCM data, you use:
// You'll want to do this with 64-bit integer math to avoid overflow.
samples = (curAudio.dwChunkSize * 8) / (wfx.wBitsPerSample * wfx.nChannels)
I tried to export private key from certificate store by CNG API. It work fine when export RSA private key, but failed in EC private key.
The code failed in NCryptExportKey() with 0x80090029.
Is there any document from MS said: Export EC private key not support? or any sample code?
Here is my code:
NCRYPT_KEY_HANDLE hKey = NULL;
SECURITY_STATUS secStatus = ERROR_SUCCESS;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD dwKeySpec, cbData = 0, cbBlob = 0, KeyPolicy = 0;
PBYTE pbHash = NULL, pbBlob = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
unsigned char *MessagePrivKey;
Struct_Return ExportMessage = { NULL, 0 };
bool bStatus;
pSignerCert = GetCert(MY_CERT_NAME);
if (!CryptAcquireCertificatePrivateKey(
pSignerCert,
CRYPT_ACQUIRE_ONLY_NCRYPT_KEY_FLAG,
NULL,
&hKey,
&dwKeySpec,
NULL))
{
goto End;
}
if (FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL,
NULL,
0,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto End;
}
pbBlob = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlob);
if (NULL == pbBlob)
{
wprintf(L"**** memory allocation failed\n");
goto End;
}
if (FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
NCRYPT_PKCS8_PRIVATE_KEY_BLOB,
NULL,
pbBlob,
cbBlob,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto End;
}
I also tried to call NCryptSetProperty() before export, but it failed with 0x8009000b.
KeyPolicy = NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG | NCRYPT_ALLOW_EXPORT_FLAG;
if (FAILED(secStatus = NCryptSetProperty(
hKey,
NCRYPT_EXPORT_POLICY_PROPERTY,
(PBYTE)&KeyPolicy,
sizeof(KeyPolicy),
NCRYPT_PERSIST_FLAG)))
{
wprintf(L"**** Error 0x%x returned by NCryptSetProperty\n", secStatus);
goto End;
}
I have a key in the Registry wich contains 3 REG_BINARY values.
I can read the first one perfectly, but when I try to get the second and third values, I get an ERROR_MORE_DATA error, even if the data is only 10 BYTES. I don't obtain the value but I get the good datalength of it.
HKEY hKey;
long nError;
DWORD sizeData;
BYTE Data[256];
nError = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\MyProg\\Test01",
NULL,KEY_ALL_ACCESS, &hKey );
if(!nError)
{ nError = RegQueryValueEx(hKey, "1", NULL, NULL, (LPBYTE)&Data,
&sizeData); // This one does OK
nError = RegQueryValueEx(hKey, "2", NULL, NULL, (LPBYTE)&Data,
&sizeData); // Here I get the good value for sizeData but ERROR_MORE_DATA
nError = RegQueryValueEx(hKey, "3", NULL, NULL, (LPBYTE)Data,
&sizeData); // Same ERROR here too
}
RegCloseKey(hKey);
NOTE: In the Registry I have those keys:
1 REG_BINARY c5 31 56 f4 d3 22 17 88 64 e3
2 REG_BINARY 45 48 47 c5 d2 21 77
3 REG_BINARY dd ef 45 2e fc 10
What am I doing wrong?
I removed the test for nError to reduce the size of the code, but in my program I get nError = ERROR_MORE_DATA.
Here is the scoop, I have created a program that sleeps for 30 seconds..Nothing more. Within immunity debugger it looks as such:
0x00061000 >/$ 68 30750000 PUSH 7530; /Timeout = 30000. ms
The code for this program is :
#include <windows.h>
void main()
{
Sleep(30000);
return 0;
}
I am trying to read this line with a C++ program. This is the code for that process:
const char *procName = "blank.exe";
HANDLE hProc = GetProcHandle(procName);
if (hProc == NULL){
cout << "Error Proccess Handle == NULL!!! Can not continue...";
getch();
return 1;
}
//Handle aquired continue.... //
cout << "Handle has been Aquired!\n";
LPVOID RMEM[100];
ReadProcessMemory(hProc, (LPVOID)(0x00061000), &RMEM, sizeof(RMEM), 0);
cout << "Read Memory:" << RMEM;
getch();
return 0;
The problem is every time I run the program I get different results. example 3 results for three runs(00FBFC3C, 0086F9C4, 007CF5EO). I want to be able to read the value of sleep and then after this is perfected I want to overwrite it with a new value like: PUSH EA60; What is going on? I have read the msdn page I have tried looking at the values ReadProMem gives me and there is no such offset in the main module. I'm at a complete loss 0.o
Any help and tips would be amazing.
Most likely the call to ReadProcessMemory is failing. Since you don't check for errors you've no way of knowing that. The documentation says:
Return value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is 0 (zero). To get extended error information, call GetLastError.
Your error checking might look like this:
if (!ReadProcessMemory(...))
{
DWORD err = GetLastError();
// report error, bail out, etc.
}
My guess is that ReadProcessMemory fails because the address you pass is not valid in the target process. And then when you output RMEM you are merely outputting uninitialized values.
The first step for you is to fix the error handling. Once you've done that you'll know which API call fails and why it fails. Then likely you'll just need to supply a valid address.
Works just fine here, using win7 pro and 32 bit compiled programs. Both programs were built with Mingw and Code::Blocks, the target memory address was determined with the use of OllyDbg.
I can confirm that the delay is successfully changed. That's the purpose of the getchar() - it's to ensure the delay hasn't been started yet when we alter the target program's memory.
1. Target program source - main.c (hackMe.exe)
#include <windows.h>
void main()
{
getchar();
Sleep(30000);
return 0;
}
2. Target area of target program (using ollydbg)
CPU Disasm
Address Hex dump Command Comments
00401334 /$ 8D4C24 04 LEA ECX,[ARG.1]
00401338 |. 83E4 F0 AND ESP,FFFFFFF0 ; DQWORD (16.-byte) stack alignment
0040133B |. FF71 FC PUSH DWORD PTR DS:[ECX-4]
0040133E |. 55 PUSH EBP
0040133F |. 89E5 MOV EBP,ESP
00401341 |. 51 PUSH ECX
00401342 |. 83EC 14 SUB ESP,14
00401345 |. E8 D6050000 CALL 00401920
0040134A |. E8 41080000 CALL <JMP.&msvcrt.getchar> ; [MSVCRT.getchar
0040134F |. C70424 307500 MOV DWORD PTR SS:[LOCAL.7],7530 ; /Time => 30000. ms
00401356 |. E8 8D080000 CALL <JMP.&KERNEL32.Sleep> ; \KERNEL32.Sleep
0040135B |. 83EC 04 SUB ESP,4
0040135E |. 90 NOP
0040135F |. 8B4D FC MOV ECX,DWORD PTR SS:[LOCAL.2]
00401362 |. C9 LEAVE
00401363 |. 8D61 FC LEA ESP,[ECX-4]
00401366 \. C3 RETN
3. Controlling program - main.c
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
unsigned long GetProcessId( char* szProcName )
{
PROCESSENTRY32 pe32;
HANDLE hHandle;
hHandle = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
pe32.dwSize = sizeof( PROCESSENTRY32 );
if( !Process32First( hHandle, &pe32 ) )
return 0;
while( Process32Next( hHandle, &pe32 ) )
{
if( stricmp( szProcName, pe32.szExeFile ) == 0 )
{
CloseHandle( hHandle );
return pe32.th32ProcessID;
}
}
CloseHandle( hHandle );
return 0;
}
// reads a chunk of memory from a running program's memory space
// Buffer must already be allocaed and hold space for length bytes
BOOL readMemBlock(char *szProgName, unsigned long dwMemAddr, unsigned long length, void *Buffer)
{
HANDLE hHandle;
SYSTEM_INFO sysInfo;
MEMORY_BASIC_INFORMATION mbi;
BOOL resCode;
DWORD lastErrCode;
printf("%s, 0x%x, %d\n", szProgName, dwMemAddr, length);
hHandle = OpenProcess( STANDARD_RIGHTS_REQUIRED|PROCESS_VM_READ, FALSE, GetProcessId( szProgName ) );
if( hHandle == INVALID_HANDLE_VALUE || hHandle == NULL )
{
printf("Error opening process\n");
if (!hHandle)
printf("hHandle == NULL\n");
else
printf("INVALID_HANDLE_VALUE");
return FALSE;
}
resCode = ReadProcessMemory( hHandle, (unsigned long*)dwMemAddr, Buffer, length, NULL );
CloseHandle(hHandle);
return resCode;
}
// reads a chunk of memory from a running program's memory space
// Buffer must already be allocaed and hold space for length bytes
BOOL writeMemBlock(char *szProgName, unsigned long dwMemAddr, unsigned long length, void *Buffer)
{
HANDLE hHandle;
SYSTEM_INFO sysInfo;
MEMORY_BASIC_INFORMATION mbi;
BOOL resCode;
hHandle = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE, FALSE, GetProcessId( szProgName ) );
if( hHandle == INVALID_HANDLE_VALUE || hHandle == NULL )
return FALSE;
resCode = WriteProcessMemory( hHandle, (unsigned long*)dwMemAddr, Buffer, length, NULL );
CloseHandle(hHandle);
return resCode;
}
int main()
{
unsigned long pId = GetProcessId("hackMe.exe");
if (!pId)
{
printf("Proc handle NOT FOUND\n");
return;
}
printf("Proc handle aquired\n");
unsigned char buffer[50];
readMemBlock("hackMe.exe", 0x401334, 50, buffer); //unsigned long length, void *Buffer)
int i;
for (i=0; i<50; i++)
{
unsigned int curElem = buffer[i];
printf("%02X ", (unsigned int)curElem);
if ((i+1)%16 == 0)
printf("\n");
}
/* output
Proc handle aquired
hackMe.exe, 0x401334, 50
8D 4C 24 04 83 E4 F0 FF 71 FC 55 89 E5 51 83 EC
14 E8 D6 05 00 00 E8 41 08 00 00 C7 04 24 30 75 <-- want these 2 bytes 0x30, 0x75
00 00 E8 8D 08 00 00 83 EC 04 90 8B 4D FC C9 8D
61 FC
*/
// change delay to 2.5 seconds (originally 30 secs)
short newDelayValue = 2500;
writeMemBlock("hackMe.exe", 0x401352, 2, &newDelayValue);
return 0;
}