65.9K
CodeProject is changing. Read more.
Home

Through the Back-Door: Back From the Stack :)

Feb 5, 2010

CPOL
viewsIcon

7124

http://rapidsh...

http://rapidshare.com/files/346131951/BackdoorEXE.zip.html http://rapidshare.com/files/346132383/BackdoorSLN.zip.html

Introduction

Hello. We could make a rapid return of our instruction pointer from a canceled intricate procedure - just by using of the CException-derived objects... :)

Implementation

There are three steps therefor: Step 1. Make your own exception derivation:
class CBackdoorException : public CException
{
  DECLARE_DYNAMIC(CBackdoorException)

public:
  CBackdoorException();
  virtual ~CBackdoorException();
};

IMPLEMENT_DYNAMIC(CBackdoorException, CException)

CBackdoorException::CBackdoorException()
{
}

CBackdoorException::~CBackdoorException()
{
}
It could be placed directly in the source file of its usage too :) Step 2. Put your call into the TRY/CATCH shell:
/*static*/ DWORD WINAPI CBackdoorDlg::WorkerProcess(CBackdoorDlg* lpBackdoorDlg)
{
  if (lpBackdoorDlg) {
    TRY {
      while (lpBackdoorDlg->CheckProgress()) {
        lpBackdoorDlg->ResetListBox();
        lpBackdoorDlg->Recurse(9); // our "intricate" call is here... :)
        
        lpBackdoorDlg->CheckProgress();
        Sleep(1000);
      }
    } CATCH (CBackdoorException, e) {
      TRACE(_T("Done.\r\n"));
    } END_CATCH
  }

  return 0;
}
Step 3. Implement your check of canceling:
bool CBackdoorDlg::CheckProgress()
{
  if (!m_bInProcess) {
    // return the IP at CATCH section, immediately :)
    THROW(new CBackdoorException());
  }
  // classical answer
  return m_bInProcess;
}

Using of Code

Now we could check the canceling state from any row of our called code, for example:
void CBackdoorDlg::Recurse(BYTE byCount)
{
  if (byCount) {
    // In my case - CBackdoorDlg::OnTraceString(..)
    // will delete the following allocation...
    // Not a good method for messaging, demo only :)
    static CString cszMessage;
    cszMessage.Format(_T(">> Recurse at: %u"), byCount);
    PostMessage(WM_USER, WPARAM(new CString(cszMessage + _T(" -- Memory will be allocated"))));
    //

    // memory allocation
    CBytePtr cBytePtr(new BYTE[20], this, cszMessage);

    CheckProgress();    // may we go home now ? :)
    Sleep(100);

    Recurse(--byCount); // would you like anything else ?
    
    CheckProgress();    // may we go home now ? :)
    Sleep(100);
  } /* CBytePtr::~CBytePtr() will be called here */
}

Points of Interest

We should remember that this method is only safe without of usage of the direct resources allocations (like CreateBrush(..), new BYTE[iLength], CreateFile(..) etc.) - the only destructors of the placed at stack objects instances will be called (!). So it would be a good context for us to use the smart pointers and wrapping objects which release their resources at the destruction. Just a demo objects destructor:
CBytePtr::~CBytePtr()
{
  if (m_pbyContent) {
    delete m_pbyContent; // will be called after an exception too :)
  }
  if (m_pcBackdoorDlg) {
    m_pcBackdoorDlg->PostMessage(WM_USER,
                                 WPARAM(new CString(m_cszStage +
                                                    _T(" -- Memory has been released :)"))));
  }
}
Please remember this warning... Thank you ! :)

History

Fri Feb 5 09:27:22 UTC+0100 2010 -- Created.