I am trying to scan all heap memory regions from a Process and scan a pattern in them.
I am using x64, and Windows 10. I am inside the target Process just for testing purposes.
My code is:
std::vector<__int64> matches; // Holds all pattern matches
int FindPattern(__int64 patternAddress, char * mask) {
SYSTEM_INFO sysInfo; // Holds System Information
GetSystemInfo(&sysInfo);
__int64 procMin = (__int64)sysInfo.lpMinimumApplicationAddress; // Minimum memory address of process
__int64 procMax = (__int64)sysInfo.lpMaximumApplicationAddress; // Maximum memory address of process
MEMORY_BASIC_INFORMATION mBI, mBINext;
DWORD firstOldProtect = NULL;
DWORD secondOldProtect = NULL;
HMODULE hdll;
DWORD patternSize = (DWORD)strlen(mask);
while (procMin < procMax) { // While still scanning memory
VirtualQueryEx(GetCurrentProcess(), (LPVOID)procMin, &mBI, sizeof(MEMORY_BASIC_INFORMATION)); // Get memory page details
if (mBI.State == MEM_COMMIT) {
VirtualProtect((LPVOID)procMin, mBI.RegionSize, PAGE_EXECUTE_READWRITE, &firstOldProtect); // Set page to read/write/execute
for (auto n = (__int64)mBI.BaseAddress; n < (__int64)mBI.BaseAddress + mBI.RegionSize; n += 0x01) { // For each byte in this page
if (n + patternSize > procMax) { // If our pattern will extend past the maximum memory address, break
break;
}
if (*(char*)n == (*(char*)patternAddress)) { // If first byte of pattern matches current byte
if (n + patternSize < (UINT)mBI.BaseAddress + mBI.RegionSize) { // If entire length of pattern is within this page
if (ComparePattern((__int64)n, patternAddress, mask)) { // Test if full pattern matches
matches.push_back((__int64)n); // If it does, add it to the vector
}
}
else { // If it isn't within the same page
VirtualQueryEx(GetCurrentProcess(), (LPVOID)(procMin + mBI.RegionSize), &mBINext, sizeof(MEMORY_BASIC_INFORMATION)); // Same memory page stuff with next page
if (mBINext.State == MEM_COMMIT) {
VirtualProtect((LPVOID)(procMin + mBI.RegionSize), mBINext.RegionSize, PAGE_EXECUTE_READWRITE, &secondOldProtect);
if (ComparePattern((__int64)n, patternAddress, mask)) {
matches.push_back((__int64)n);
}
}
}
}
}
VirtualProtect((LPVOID)procMin, mBI.RegionSize, firstOldProtect, NULL); // Reset memory page state of first page
if (secondOldProtect) { // If we scanned into the second page
VirtualProtect((LPVOID)procMin, mBINext.RegionSize, secondOldProtect, NULL); // Reset memory page state of second page
secondOldProtect = NULL;
}
}
procMin = procMin + (__int64) mBI.RegionSize; // Start scanning next page
}
return 0;
}
Then the ComparePattern function is:
bool ComparePattern(__int64 address, __int64 patternAddress, char * mask) {
int patternLen = strlen(mask);
for (auto i = 1; i < patternLen; i++) {
if (mask[i] != *"?" && *(char*)(address + i) != *(char*)(patternAddress + i)) { // Compare each byte of the pattern with each byte after the current scanning address
return false;
}
}
if (address != patternAddress) { // Make sure we aren't returning a match for the pattern defined within your DLLMain
return true;
}
return false;
}
I retrieve several memory blocks, but I am not being able to retrieve the specific memory region/block where the pattern is located using this VirtualQueryEx code.
To test this and the weird part is that if I use the Heap APIs I am able to identify the memory allocated and the specified pattern:
__int64 ReturnMachHeapAPI(__int64 patternAddress, char * mask) {
HANDLE hHeaps[250];
DWORD numHeaps = GetProcessHeaps(250, hHeaps);
unsigned long i;
if (numHeaps <= 250)
{
for (i = 0; i < numHeaps; i++) {
HeapLock(hHeaps[i]);
PROCESS_HEAP_ENTRY entry;
memset(&entry, '\0', sizeof entry);
bool found = false;
while (!found && HeapWalk(hHeaps[i], &entry) != FALSE)
{
for (auto ii = (__int64)entry.lpData; ii < (__int64)entry.lpData + entry.cbData; ii += 0x01) {
if (ComparePattern((__int64)ii, patternAddress, mask)) {
return ii;
}
}
}
HeapUnlock(hHeaps[i]);
}
}
return 0;
}
I appreciate any hints on why the VirtualQueryEx code is not working as expected. One point worth to mention is that my Process has several modules (DLLs) along with the main executable.
Thanks so much.
EDIT:
I re-wrote the VirtualQueryEx loop, using ReadProcessMemory now. It is working perfect now.
The working code is:
char* InScan(char* pattern, char* mask, char* begin, unsigned int size)
{
//strlen the mask, not the pattern if you use the pattern
//you will get short length because null terminator
unsigned int patternLength = strlen(mask);
for (unsigned int i = 0; i < size - patternLength; i++)
{
bool found = true;
for (unsigned int j = 0; j < patternLength; j++)
{
if (mask[j] != '?' && pattern[j] != *(begin + i + j))
{
found = false;
break;
}
}
if (found)
{
return (begin + i);
}
}
return 0;
}
char * PatternScan(char* pattern, char* mask)
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
__int64 end = (__int64)sysInfo.lpMaximumApplicationAddress;
char* currentChunk = 0;
char* match = nullptr;
SIZE_T bytesRead;
while (currentChunk < (char *) end)
{
MEMORY_BASIC_INFORMATION mbi;
HANDLE process = GetCurrentProcess();
int hr = GetLastError();
if (!VirtualQueryEx(process, currentChunk, &mbi, sizeof(mbi)))
{
return 0;
}
char* buffer = 0;
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS)
{
buffer = new char[mbi.RegionSize];
DWORD oldprotect;
if (VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect))
{
ReadProcessMemory(process, mbi.BaseAddress, buffer, mbi.RegionSize, &bytesRead);
VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, oldprotect, &oldprotect);
char* internalAddress = InScan(pattern, mask, buffer, bytesRead);
if (internalAddress != 0)
{
//calculate from internal to external
__int64 offsetFromBuffer = internalAddress - buffer;
match = currentChunk + offsetFromBuffer;
delete[] buffer;
break;
}
}
}
currentChunk = currentChunk + mbi.RegionSize;
if (buffer) delete[] buffer;
buffer = 0;
}
return match;
}
I re-wrote the VirtualQueryEx loop, including the use of ReadProcessMemory and works perfect.
char* InScan(char* pattern, char* mask, char* begin, unsigned int size)
{
unsigned int patternLength = strlen(mask);
for (unsigned int i = 0; i < size - patternLength; i++)
{
bool found = true;
for (unsigned int j = 0; j < patternLength; j++)
{
if (mask[j] != '?' && pattern[j] != *(begin + i + j))
{
found = false;
break;
}
}
if (found)
{
return (begin + i);
}
}
return 0;
}
char * PatternScan(char* pattern, char* mask)
{
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
__int64 end = (__int64)sysInfo.lpMaximumApplicationAddress;
char* currentChunk = 0;
char* match = nullptr;
SIZE_T bytesRead;
while (currentChunk < (char *) end)
{
MEMORY_BASIC_INFORMATION mbi;
HANDLE process = GetCurrentProcess();
int hr = GetLastError();
if (!VirtualQueryEx(process, currentChunk, &mbi, sizeof(mbi)))
{
return 0;
}
char* buffer = 0;
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS)
{
buffer = new char[mbi.RegionSize];
DWORD oldprotect;
if (VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldprotect))
{
ReadProcessMemory(process, mbi.BaseAddress, buffer, mbi.RegionSize, &bytesRead);
VirtualProtectEx(process, mbi.BaseAddress, mbi.RegionSize, oldprotect, &oldprotect);
char* internalAddress = InScan(pattern, mask, buffer, bytesRead);
if (internalAddress != 0)
{
//calculate from internal to external
__int64 offsetFromBuffer = internalAddress - buffer;
match = currentChunk + offsetFromBuffer;
delete[] buffer;
break;
}
}
}
currentChunk = currentChunk + mbi.RegionSize;
if (buffer) delete[] buffer;
buffer = 0;
}
return match;
}
Related
Basically, what I am trying to do is to find last section of PE file. I have read PE specification very attentively, yet I can't discover where my code fails.
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)(pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)(pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));
buffer is a byte array containing loaded executable, and pish is a pointer to the last section. For some reason, it appears that number of sections is over 20 000.
Any ideas ?
Thanks in advance
There is one problem I see off hand: e_lfanew is the offset to the IMAGE_NT_HEADERS structure in bytes. You are adding this number of bytes to a IMAGE_DOS_HEADER pointer, so you are moving forward by sizeof(IMAGE_DOS_HEADER)*pidh->e_lfanew bytes.
Fixed version:
PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)buffer;
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS)((BYTE*)pidh + pidh->e_lfanew);
PIMAGE_FILE_HEADER pifh = (PIMAGE_FILE_HEADER)&pinh->FileHeader;
PIMAGE_OPTIONAL_HEADER pioh = (PIMAGE_OPTIONAL_HEADER)&pinh->OptionalHeader;
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER)((BYTE*)pinh + sizeof(IMAGE_NT_HEADERS) + (pifh->NumberOfSections - 1) * sizeof(IMAGE_SECTION_HEADER));
The best way to debug problems like this is to drop into the code with your debugger and view the PE data yourself in memory. You can open up the Visual Studio hex editor for example and see all of the byte data, and which values you are actually reading out.
Here's some information on viewing program memory in VS 2010:
http://msdn.microsoft.com/en-us/library/s3aw423e.aspx
Various section address and data can be obtained by below way also :
#include<windows.h>
#include<iostream>
int main()
{
LPCSTR fileName="inputFile.exe";
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS peHeader;
PIMAGE_SECTION_HEADER sectionHeader;
hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if(hFile==INVALID_HANDLE_VALUE)
{
std::cout<<"\n CreateFile failed \n";
return 1;
}
hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(hFileMapping==0)
{
std::cout<<"\n CreateFileMapping failed \n";
CloseHandle(hFile);
return 1;
}
lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0);
if(lpFileBase==0)
{
std::cout<<"\n MapViewOfFile failed \n";
CloseHandle(hFileMapping);
CloseHandle(hFile);
return 1;
}
dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;
if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
{
std::cout<<"\n DOS Signature (MZ) Matched \n";
peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
if(peHeader->Signature==IMAGE_NT_SIGNATURE)
{
std::cout<<"\n PE Signature (PE) Matched \n";
sectionHeader = IMAGE_FIRST_SECTION(peHeader);
UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
//No of Sections
std::cout<<"\n No of Sections : "<<nSectionCount<<" \n";
//sectionHeader contains pointer to first section
//sectionHeader++ will move to next section
for( UINT i=0; i<nSectionCount; ++i, ++sectionHeader )
{
std::cout<<"\n-----------------------------------------------\n";
std::cout<<"\n Section Name : "<<sectionHeader->Name<<" \n";
//address can be obtained as (PBYTE)lpFileBase+sectionHeader->PointerToRawData
std::cout<<"\n Size of section data : "<<sectionHeader->Misc.VirtualSize<<" \n";
std::cout<<"\n-----------------------------------------------\n";
}
//Now sectionHeader will have pointer to last section
//if you add sectionHeader++ in for loop instead of ++sectionHeader it will point to memory after last section
}
else
{
return 1;
}
}
else
{
return 1;
}
return 0;
}
You just do it the wrong way.
I wrote some code for you, hope it helps.It can show the data of the last section of a PE file.
#include <stdio.h>
#include <malloc.h>
#include <windows.h>
void ShowHexData(BYTE *ptr,DWORD len)
{
int index = 0;
int i = 0;
const int width = 16;
while(index + width < len)
{
int i;
for(i = 0; i < width; ++i)
{
printf(" %02X",ptr[index + i]);
}
printf(" \t");
for(i = 0; i < width; ++i)
{
if(ptr[index + i] >= 0x20 &&
ptr[index + i] <= 0x7F)
{
putchar(ptr[index + i]);
}else{
putchar('.');
}
}
index += width;
putchar('\n');
}
for(i = 0; index + i < len; ++ i)
{
printf(" %02X",ptr[index + i]);
}
while(i < width)
{
printf(" ");
i += 1;
}
printf(" \t");
for(i = 0; index + i < len; ++ i)
{
if(ptr[index + i] >= 0x20 &&
ptr[index + i] <= 0x7F)
{
putchar(ptr[index + i]);
}else{
putchar('.');
}
}
putchar('\n');
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Usage : %s filename\n",argv[0]);
return -1;
}else{
FILE *fp = fopen(argv[1],"rb");
IMAGE_DOS_HEADER DosHeader = {0};
IMAGE_FILE_HEADER FileHeader = {0};
IMAGE_SECTION_HEADER SectionHeader = {0};
DWORD Signature = 0;
DWORD RawPointerToPeHeader = 0, SizeOfFile = 0;
DWORD SectionCount = 0;
DWORD ByteCount = 0;
BYTE *pData = NULL;
if(!fp)
{
perror("");
return -1;
}
fseek(fp,0,SEEK_END);
SizeOfFile = ftell(fp);
if(SizeOfFile <
sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))
goto not_pe_file;
fseek(fp,0,SEEK_SET);
fread(&DosHeader,1,sizeof DosHeader,fp);
if(DosHeader.e_magic != 'M' + 'Z' * 256)
goto not_pe_file;
RawPointerToPeHeader = DosHeader.e_lfanew;
if(SizeOfFile <=
RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS))
goto not_pe_file;
fseek(fp,RawPointerToPeHeader,SEEK_SET);
fread(&Signature,1,sizeof(DWORD),fp);
if(Signature != 'P' + 'E' * 256)
goto not_pe_file;
fread(&FileHeader,1,sizeof FileHeader,fp);
if(FileHeader.SizeOfOptionalHeader !=
sizeof(IMAGE_OPTIONAL_HEADER))
goto not_pe_file;
SectionCount = FileHeader.NumberOfSections;
if(SectionCount == 0)
{
printf("No section for this file.\n");
fclose(fp);
return -1;
}
if(SizeOfFile <=
RawPointerToPeHeader +
sizeof(IMAGE_NT_HEADERS) +
SectionCount * sizeof(IMAGE_SECTION_HEADER))
goto not_pe_file;
fseek(fp,
RawPointerToPeHeader + sizeof(IMAGE_NT_HEADERS) +
(SectionCount - 1) * sizeof(IMAGE_SECTION_HEADER),
SEEK_SET);
fread(&SectionHeader,1,sizeof SectionHeader,fp);
ByteCount = SectionHeader.Misc.VirtualSize < SectionHeader.PointerToRawData ?
SectionHeader.Misc.VirtualSize : SectionHeader.PointerToRawData;
if(ByteCount == 0)
{
printf("No data to read for target section.\n");
fclose(fp);
return -1;
}else if(ByteCount + SectionHeader.PointerToRawData > SizeOfFile)
{
printf("Bad section data.\n");
fclose(fp);
return -1;
}
fseek(fp,SectionHeader.PointerToRawData,SEEK_SET);
pData = (BYTE*)malloc(ByteCount);
fread(pData,1,ByteCount,fp);
ShowHexData(pData,ByteCount);
free(pData);
fclose(fp);
return 0;
not_pe_file:
printf("Not a PE file.\n");
fclose(fp);
return -1;
}
return 0;
}
In short, you do not know where the data is, until you analyze the data according to the file header.
sections pointer:
PIMAGE_SECTION_HEADER pish = IMAGE_FIRST_SECTION(pinh); // definition
in winnt.h
or
PIMAGE_SECTION_HEADER pish = (PIMAGE_SECTION_HEADER )((BYTE*)pioh +
pifh->SizeOfOptionalHeader);
the last section pointer is:
PIMAGE_SECTION_HEADER pilsh = &pish[pifh->NumberOfSections-1]
Environment:
Ubuntu 16.04 (x64)
C++
ffmpeg
Use-case
Multiple MPEG-TS fragments are rapidly decoded ( numerous every sec )
The format of the TS fragments is dynamic and can't be known ahead of time
The first A/V frames of each fragment are needed to be extracted
Problem statement
The code bellow successfully decodes A/V, BUT, has a huge memory leak ( MBytes/sec )
According to the docs seems all memory is freed as it should ( does it... ? )
Why do I get this huge mem leak, what am I missing in the following code snap ?
struct MEDIA_TYPE {
ffmpeg::AVMediaType eType;
union {
struct {
ffmpeg::AVPixelFormat colorspace;
int width, height;
float fFPS;
} video;
struct : WAVEFORMATEX {
short sSampleFormat;
} audio;
} format;
};
struct FRAME {
enum { MAX_PALNES = 3 + 1 };
int iStrmId;
int64_t pts; // Duration in 90Khz clock resolution
uint8_t** ppData; // Null terminated
int32_t* pStride;// Zero terminated
};
HRESULT ProcessTS(IN Operation op, IN uint8_t* pTS, IN uint32_t uiBytes, bool(*cb)(IN const MEDIA_TYPE& mt, IN FRAME& frame, IN PVOID pCtx), IN PVOID pCbCtx)
{
uiBytes -= uiBytes % 188;// align to 188 packet size
struct CONTEXT {
uint8_t* pTS;
uint32_t uiBytes;
int32_t iPos;
} ctx = { pTS, uiBytes, 0 };
LOGTRACE(TSDecoder, "ProcessTS(%d, 0x%.8x, %d, 0x%.8x, 0x%.8x), this=0x%.8x\r\n", (int)op, pTS, uiBytes, cb, pCbCtx, this);
ffmpeg::AVFormatContext* pFmtCtx = 0;
if (0 == (pFmtCtx = ffmpeg::avformat_alloc_context()))
return E_OUTOFMEMORY;
ffmpeg::AVIOContext* pIoCtx = ffmpeg::avio_alloc_context(pTS, uiBytes, 0, &ctx
, [](void *opaque, uint8_t *buf, int buf_size)->int {
auto pCtx = (CONTEXT*)opaque;
int size = pCtx->uiBytes;
if (pCtx->uiBytes - pCtx->iPos < buf_size)
size = pCtx->uiBytes - pCtx->iPos;
if (size > 0) {
memcpy(buf, pCtx->pTS + pCtx->iPos, size);
pCtx->iPos += size;
}
return size;
}
, 0
, [](void* opaque, int64_t offset, int whence)->int64_t {
auto pCtx = (CONTEXT*)opaque;
switch (whence)
{
case SEEK_SET:
pCtx->iPos = offset;
break;
case SEEK_CUR:
pCtx->iPos += offset;
break;
case SEEK_END:
pCtx->iPos = pCtx->uiBytes - offset;
break;
case AVSEEK_SIZE:
return pCtx->uiBytes;
}
return pCtx->iPos;
});
pFmtCtx->pb = pIoCtx;
int iRet = ffmpeg::avformat_open_input(&pFmtCtx, "fakevideo.ts", m_pInputFmt, 0);
if (ERROR_SUCCESS != iRet) {
assert(false);
pFmtCtx = 0;// a user-supplied AVFormatContext will be freed on failure.
return E_FAIL;
}
struct DecodeContext {
ffmpeg::AVStream* pStream;
ffmpeg::AVCodec* pDecoder;
int iFramesProcessed;
};
HRESULT hr = S_OK;
int iStreamsProcessed = 0;
bool bVideoFound = false;
int64_t ptsLast = 0;
int64_t dtsLast = 0;
auto pContext = (DecodeContext*)alloca(sizeof(DecodeContext) * pFmtCtx->nb_streams);
for (unsigned int i = 0; i < pFmtCtx->nb_streams; i++) {
assert(pFmtCtx->streams[i]->index == i);
pContext[i].pStream = pFmtCtx->streams[i];
pContext[i].pDecoder = ffmpeg::avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id);
pContext[i].iFramesProcessed= 0;
if (0 == pContext[i].pDecoder)
continue;
if ((iRet = ffmpeg::avcodec_open2(pFmtCtx->streams[i]->codec, pContext[i].pDecoder, NULL)) < 0) {
_ASSERT(FALSE);
hr = E_FAIL;
goto ErrExit;
}
}
while (S_OK == hr) {
ffmpeg::AVFrame* pFrame = 0;
ffmpeg::AVPacket pkt;
ffmpeg::av_init_packet(&pkt);
if (ERROR_SUCCESS != (iRet = ffmpeg::av_read_frame(pFmtCtx, &pkt))) {
hr = E_FAIL;
break;
}
if ((0 == dtsLast) && (0 != pkt.dts))
dtsLast = pkt.dts;
if ((0 == ptsLast) && (0 != pkt.pts))
ptsLast = pkt.pts;
DecodeContext& ctx = pContext[pkt.stream_index];
if (Operation::DECODE_FIRST_FRAME_OF_EACH_STREAM == op) {
if (iStreamsProcessed == pFmtCtx->nb_streams) {
hr = S_FALSE;
goto Next;
}
if (ctx.iFramesProcessed > 0)
goto Next;
iStreamsProcessed++;
}
if (0 == ctx.pDecoder)
goto Next;
if (0 == (pFrame = ffmpeg::av_frame_alloc())) {
hr = E_OUTOFMEMORY;
goto Next;
}
LOGTRACE(TSDecoder, "ProcessTS(%d, 0x%.8x, %d, 0x%.8x, 0x%.8x), this=0x%.8x, decode, S:%d, T:%d\r\n", (int)op, pTS, uiBytes, cb, pCbCtx, this, pkt.stream_index, ctx.pStream->codec->codec_type);
int bGotFrame = false;
int iBytesUsed = 0;
MEDIA_TYPE mt;
memset(&mt, 0, sizeof(mt));
mt.eType = ctx.pStream->codec->codec_type;
switch (mt.eType) {
case ffmpeg::AVMediaType::AVMEDIA_TYPE_AUDIO:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if((iRet = ffmpeg::avcodec_decode_audio4(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
goto Next;
}
_ASSERT(pkt.size == iRet);
// FFMPEG AAC decoder oddity, first call to 'avcodec_decode_audio4' results mute audio where the second result the expected audio
bGotFrame = false;
if ((iRet = ffmpeg::avcodec_decode_audio4(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
goto Next;
}
_ASSERT(pkt.size == iRet);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (false == bGotFrame)
goto Next;
iBytesUsed = ctx.pStream->codec->frame_size;
mt.format.audio.nChannels = ctx.pStream->codec->channels;
mt.format.audio.nSamplesPerSec = ctx.pStream->codec->sample_rate;
mt.format.audio.wBitsPerSample = ffmpeg::av_get_bytes_per_sample(ctx.pStream->codec->sample_fmt) * 8;
mt.format.audio.nBlockAlign = mt.format.audio.nChannels * mt.format.audio.wBitsPerSample / 8;
mt.format.audio.sSampleFormat = (short)pFrame->format;
break;
case ffmpeg::AVMediaType::AVMEDIA_TYPE_VIDEO:
if ((iRet = ffmpeg::avcodec_decode_video2(ctx.pStream->codec, pFrame, &bGotFrame, &pkt)) < 0) {
hr = E_FAIL;
break;
}
if (false == bGotFrame)
goto Next;
assert(ffmpeg::AVPixelFormat::AV_PIX_FMT_YUV420P == ctx.pStream->codec->pix_fmt);// Thats is the only color space currently supported
iBytesUsed = (ctx.pStream->codec->width * ctx.pStream->codec->height * 3) / 2;
mt.format.video.width = ctx.pStream->codec->width;
mt.format.video.height = ctx.pStream->codec->height;
mt.format.video.colorspace = ctx.pStream->codec->pix_fmt;
mt.format.video.fFPS = (float)ctx.pStream->codec->framerate.num / ctx.pStream->codec->framerate.den;
bVideoFound = true;
break;
default:
goto Next;
}
ctx.iFramesProcessed++;
{
FRAME f = { ctx.pStream->index, ((0 == ptsLast) ? dtsLast : ptsLast), (uint8_t**)pFrame->data, (int32_t*)pFrame->linesize };
if ((iRet > 0) && (false == cb(mt, f, pCbCtx)))
hr = S_FALSE;// Breaks the loop
}
Next:
ffmpeg::av_free_packet(&pkt);
if (0 != pFrame) {
//ffmpeg::av_frame_unref(pFrame);
ffmpeg::av_frame_free(&pFrame);
pFrame = 0;
}
}
ErrExit:
for (unsigned int i = 0; i < pFmtCtx->nb_streams; i++)
ffmpeg::avcodec_close(pFmtCtx->streams[i]->codec);
pIoCtx->buffer = 0;// We have allocated the buffer, no need for ffmpeg to free it 4 us
pFmtCtx->pb = 0;
ffmpeg::av_free(pIoCtx);
ffmpeg::avformat_close_input(&pFmtCtx);
ffmpeg::avformat_free_context(pFmtCtx);
return hr;
}
You need to unref the packets before reusing them. And there's no need to allocate and deallocate them all the time.
Here's how I do it which might help you:
// Initialise a packet queue
std::list<AVPacket *> packets;
...
for (int c = 0; c < MAX_PACKETS; c++) {
ff->packets.push_back(av_packet_alloc());
}
while (!quit) {
... get packet from queue
int err = av_read_frame(ff->context, packet);
... process packet (audio, video, etc)
av_packet_unref(packet); // add back to queue for reuse
}
// Release packets
while (ff->packets.size()) { // free packets
AVPacket *packet = ff->packets.front();
av_packet_free(&packet);
ff->packets.pop_front();
}
In your code you've freed a packet which wasn't allocated in the first place.
I'm trying to use FP routine, but it doesn't work...Why?
This is my code:
int output = FindPattern(0x0042A000, 0x2000, "\x68\x00\x00\x00\x00\xFF\x76\x08\x89\x46\x44", "x????xxxxxx");
if (output > -1) {
ReadProcessMemory(hProcHandle, (PVOID)address, &value2, sizeof(value2), NULL);
}
Function:
int FindPattern(int start_offset, int size, const char * pattern, const char * mask)
{
int pos = 0;
for (int retAddress = start_offset; retAddress < start_offset + size; retAddress++)
{
if (*(const char*)retAddress == pattern[pos] || mask[pos] == '?')
{
if (mask[pos+1] == '\0')
return retAddress+1;
pos++;
}
else
pos = 0;
}
return -1;
}
I also tried:
DWORD output = FindPattern(hProcHandle, "\x68\x00\x00\x00\x00\xFF\x76\x08\x89\x46\x44", "x????xxxxxx");
bool VerifyAddress(HANDLE hwnd, DWORD dwAddress, char *bMask, char *szMask )
{
PBYTE *pTemp = { 0 };
for ( int i = 0; *szMask; ++szMask, ++bMask, ++i )
{
if ( !ReadProcessMemory( hwnd, reinterpret_cast<LPCVOID>(dwAddress + i), &pTemp, sizeof(pTemp), 0 ) ){
return false;
}
if ( *szMask == 'x' && (char)pTemp != *bMask){
return false;
}
}
return true;
}
DWORD FindPattern(HANDLE hwnd, char* bMask, char *szMask )
{
for ( DWORD dwCurrentAddress = 0x4FFFFFF; dwCurrentAddress < 0x7FFFFFF; dwCurrentAddress++ ){
if ( VerifyAddress( hwnd, dwCurrentAddress, bMask, szMask )) {
return dwCurrentAddress;
}
}
But with these codes I get always
Unhandled exception at 0x01034BB1 in Program.exe: 0xC0000005: Access
violation reading location 0x02343DA2.
This code:
int output = FindPattern(0x0042A000, 0x2000,
indicates that you are using address 0x0042A000 local to your process, so you are iterating over some random addresses in your process which is Undefined Behaviour and ends with exception.
ReadProcessMemory copies specified memory from some other process to your process and stores in in memory buffer you provide in this function call as lpBuffer parameter.
Currently I'm using this function which I've cobbled together from reading several loosely related questions all over the internet. The problem I'm having is that the first time I ran it it returned an error, but unfortunately I haven't been able to reproduce it. Now when I run it it simply returns 0 every time.
DWORD GetAddressOfString(char *input)
{
unsigned char *p = NULL;
MEMORY_BASIC_INFORMATION info;
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, _processID);
for (p = NULL; VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info); p += info.RegionSize)
{
if (info.State == MEM_COMMIT && (info.Type == MEM_MAPPED || info.Type == MEM_PRIVATE))
{
char *buffer = new char[info.RegionSize];
SIZE_T bytesRead;
ReadProcessMemory(process, p, &buffer, info.RegionSize, &bytesRead);
for (int i = 0; i <= (info.RegionSize - sizeof(input)); i++)
{
if (memcmp(input, &buffer[i], sizeof(input)) == 0)
{
return i;
}
}
}
}
}
Here's a quick and dirty version that searches for data in itself. If you open up Notepad++, type "SomeDataToFind", replace the pid with the correct value, and run it, it should find the data as well. It might give you something to start with and embellish to suit your needs.
Your code was searching for the wrong length, returning the wrong offset, leaking memory like a sieve, and not always returning a value which is undefined behavior.
#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
char* GetAddressOfData(DWORD pid, const char *data, size_t len)
{
HANDLE process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
if(process)
{
SYSTEM_INFO si;
GetSystemInfo(&si);
MEMORY_BASIC_INFORMATION info;
std::vector<char> chunk;
char* p = 0;
while(p < si.lpMaximumApplicationAddress)
{
if(VirtualQueryEx(process, p, &info, sizeof(info)) == sizeof(info))
{
p = (char*)info.BaseAddress;
chunk.resize(info.RegionSize);
SIZE_T bytesRead;
if(ReadProcessMemory(process, p, &chunk[0], info.RegionSize, &bytesRead))
{
for(size_t i = 0; i < (bytesRead - len); ++i)
{
if(memcmp(data, &chunk[i], len) == 0)
{
return (char*)p + i;
}
}
}
p += info.RegionSize;
}
}
}
return 0;
}
int main()
{
const char someData[] = "SomeDataToFind";
std::cout << "Local data address: " << (void*)someData << "\n";
//Pass whatever process id you like here instead.
DWORD pid = GetCurrentProcessId();
char* ret = GetAddressOfData(pid, someData, sizeof(someData));
if(ret)
{
std::cout << "Found: " << (void*)ret << "\n";
}
else
{
std::cout << "Not found\n";
}
return 0;
}
I've put the contents of a file in a char-array using this function:
void Read::readFile(){
FILE * fp = fopen(this->filename,"rt");
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *pData = new char[size + 1];
fread(pData, sizeof(char), size, fp);
fclose(fp);
this->data = pData;
}
Now I want to strip all line-endings from the char-array.
How do I do this without casting the char-array into a string first?
btw. this is part of a homework where we aren't allowed to use the string-library.
#include <algorithm>
size = std::remove(pData, pData + size, '\n') - pData;
pData[size] = 0; // optional
For some C++11 lambda fun:
#include <algorithm>
size = std::remove_if(pData, pData + size, [](char c) { return c == '\n'; }) - pData;
pData[size] = 0; // optional
The easiest approach is to make a second buffer the size of the original array.
int len = size;
char* newBufer = calloc(len,sizeof(char));
int i = 0;
int j = 0;
int nlCount = 0;
for(i=0; i<len; i++) {
if(pData[i] != '\n') {
newBuffer[j++] = pData[i];
} else {
nlCount++;
}
}
printf("Finished copying array without newlines. Total newlines removed: %d",nlCount);
The added benefit here is since you calloc'ed instead of malloc'ing your array, all values are zero initially, so in this case, once you are done copying, the data at (len-nlCount) through to (len) will all be zero (ie: '\0') so it is automatically null-terminated, like a string would be anyways. Don't forget to free() the array when you are done.
In place removal:
void strip_newlines(char* p) {
char* q = p;
while (p != 0 && *p != '\0') {
if (*p == '\n') {
p++;
*q = *p;
}
else {
*q++ = *p++;
}
}
*q = '\0';
}
Something like this:
void Read::readFile()
{
FILE * fp = fopen(this->filename,"rt");
if (fp)
{
char *pData = NULL;
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
if (size != -1L)
{
pData = new char[size];
if (size > 0)
{
fseek(fp, 0, SEEK_SET);
size = fread(pData, sizeof(char), size, fp);
}
}
fclose(fp);
if (size < 0)
{
delete[] pData;
pData = NULL;
}
else if (size > 0)
{
char *start = pData;
char *end = start + size;
char *ptr = (char*) memchr(pData, '\n', size);
while (ptr)
{
int len = 1;
if ((ptr > start) && ((*ptr-1) == '\r'))
{
--ptr;
++len;
}
memmove(ptr, ptr+len, end - (ptr+len));
end -= len;
ptr = (char*) memchr(ptr, '\n', end - ptr);
}
size = (end - start);
}
this->data = pData;
this->size = size;
}
}