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 have written a C++ program in Code::Blocks which reads REG_NONE type value from registry.
Here are my codes:
#define KEY_WOW64_64KEY 0x0100
#include "string"
#include "windows.h"
using namespace std;
int main()
{
HKEY hKey;
long longErrorCode;
string strErrorCaption = "Hata";
string strErrorMessage;
string strSubKey = "Software\\DownloadManager\\Scheduler";
longErrorCode = RegOpenKeyEx(HKEY_CURRENT_USER, strSubKey.c_str(), 0, KEY_ALL_ACCESS | KEY_WOW64_64KEY, &hKey);
if (longErrorCode != ERROR_SUCCESS)
{
strErrorMessage = "Anahtar açılamadı.";
MessageBox(NULL, strErrorMessage.c_str(), strErrorCaption.c_str(), MB_OK | MB_ICONERROR);
return 0;
}
else
{
DWORD dwSize = MAX_PATH;
DWORD dwValueContent;
DWORD dwValueType = REG_NONE;
string strValueName = "startDay";
longErrorCode = RegQueryValueEx(hKey, strValueName.c_str(), 0, &dwValueType, (LPBYTE)&dwValueContent, &dwSize);
if (longErrorCode != ERROR_SUCCESS)
{
RegCloseKey(hKey);
strErrorMessage = "Değer açılamadı.";
MessageBox(NULL, strErrorMessage.c_str(), strErrorCaption.c_str(), MB_OK | MB_ICONERROR);
return 0;
}
else
{
string strValueContent = to_string(dwValueContent);
RegCloseKey(hKey);
strErrorCaption = "Başarılı!";
MessageBox(NULL, strValueContent.c_str(), strErrorCaption.c_str(), MB_OK | MB_ICONINFORMATION);
return 0;
}
}
}
The real value of the registry key which I tried to read is "f5 68 4b 5c".
But the problem is I got "1548445941". I also tried stringstream; but it didn't work.
So, what should I do in order to fix this issue?
the number is correct when you notice the bytes are ordered from the lower to the upper bytes.
Hex 5C4B68F5 = dec 1548445941
Open up windows calculator. Switch to programmer mode. Press DEC type in 1548445941. Notice how it shows HEX is 5C 4B 68 F5. Realise this is the value you got from registry but reversed, then read up about little endian.
I've been attempting to play around with the wincrypt api, but can't seem to figure out why the output from CryptEncrypt doesn't match the output from a language like Go.
wincrypt code
BYTE *inBuffer = (BYTE*)"Hello World";
HCRYPTPROV phProv = NULL;
HCRYPTKEY key = NULL;
HCRYPTHASH hHash = NULL;
DWORD len = bufLen;
BYTE password[] = "password";
DWORD passLen = strlen((char*)password);
if (!CryptAcquireContext(&phProv, NULL, NULL, PROV_RSA_FULL, 0)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptAcquireContext error %d", dwStatus);
}
if (!CryptCreateHash(phProv, CALG_MD5, 0, 0, &hHash)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptCreateHash error %d", dwStatus);
}
if (!hHash)
error.Fatal("Hash create fail");
if (!CryptHashData(hHash, password, passLen, 0)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptHashData error %d", dwStatus);
}
if (!CryptDeriveKey(phProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &key)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptDeriveKey error %d", dwStatus);
}
if (!CryptEncrypt(key, 0, TRUE, 0, NULL, &len, 0)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptEncrypt error %d", dwStatus);
}
outBuffLen = len;
BYTE *cipherBlock = (BYTE*)calloc(len, sizeof(BYTE));
memcpy_s(cipherBlock, len, inBuffer, len);
if (!CryptEncrypt(key, 0, TRUE, 0, cipherBlock, &len, outBuffLen)) {
DWORD dwStatus = GetLastError();
error.Fatal("CryptEncrypt error %d", dwStatus);
}
CryptDestroyKey(key);
CryptReleaseContext(phProv, 0);
CryptDestroyHash(hHash);
go code
package main
import (
"crypto/rc4"
"fmt"
"log"
)
func main() {
key := []byte("5f4dcc3b5aa765d61d8327deb882cf99")
src := []byte("Hello World")
c, err := rc4.NewCipher(key)
if err != nil {
log.Fatal(err)
}
dst := make([]byte, len(src))
c.XORKeyStream(dst, src)
for _, x := range dst {
fmt.Printf("%02X ", x)
}
}
If the key is "password" the output should be: B7 90 54 62 23 1E E3 C1 13 3D CF
If the key is md5 hash of "password" ("5f4dcc3b5aa765d61d8327deb882cf99") the output should be: E4 F9 36 64 83 8A 3F 78 41 82 15
The output I'm getting from wincrypt: a0 9d 47 51 1a 7b 32 8e 03 54 c3
Is there something simple I'm missing?
I have the following line in ASM
_:004F73BB C6 83 54 41 03 00 01 mov byte ptr [ebx+34154h], 1
In c++ i need to return the value of 34154h as an address ( 0x34154 )
Im hoping this can be done like so:
void getADR(BYTE *ptr1){//something like this?
__asm{//i don't know how to call this at 004F73BB
mov [ptr1], ebx
mov byte ptr [ebx+34154h], 1
}
// return ((BYTE)0x004F73BB - ptr1)
}
_____MY Logger____
This is my address logger that gets the ASM line 0x004F73BB
The playerpointer and server pointers are both easy to get because the byte patters point to a MOV and MOV returns the pointer of itself.
DWORD FindPattern(DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask)
{
for (DWORD i = 0; i < dwLen; i++)
if (Match((BYTE*)(dwAddress + i), bMask, szMask))
return (DWORD)(dwAddress + i);
return 0;
}
void SearchPatterns(void)
{
while (true){
add_log("ADR_PlayerPointer", "\xA4\xA2\xAE\x00", "xxx?", "A4 A2 AE 00, xxx?");
add_log("ADR_ServerPointer", "\x48\x92\xAE\x00", "xxx?", "A1 48 92 AE 00, xxx?");
add_log("OFS_5thSlot", "\x75\x09\xC6\x83\x54\x41\x03\x00\x01", "xxxxxxx?x", "75 09 C6 83 54 41 03 00 01, xxxxxxx?x");
ExitProcess(0);
}
}
BOOL WINAPI DllMain(HMODULE hDll, DWORD dwReason, LPVOID lpReserved)
{
//DisableThreadLibraryCalls(hDll);
if (dwReason == DLL_PROCESS_ATTACH)
{
logging(hDll);
CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)SearchPatterns, NULL, NULL, NULL);
}
return TRUE;
}
If you need more information leave a comment.
With that just bit of information, simply load the bytes into an char array, read the values at index 2, 3, 4, 5, do some little endian/big endian math. Or make a int* and make it point to the index 2 in the array and read the value.
Or if you know the offset in the binary, read the exe file, then point your int* to that location and read the value.
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;
}