Memory is overwritten after calling functions in DLL

Memory is overwritten after calling functions in DLL

Postby hua » Wed Oct 05, 2011 6:41 am

Hi Antonio and all FWH gurus,
This post is a continuation from this thread. I've now managed to build a much reduced, sorta self-contained sample :). I agree with Roberto Parisi that it looks like a case of memory that got overwritten as with my reduced sample, space is not replaced by 'N' but some other character. Unfortunately, his tip of using hg_gcall() didn't work for me. Here's the screenshot:

Image

The sample was compiled using BCC5.82 + Harbour rev 17053 + FWH11.8. Download the source here
Just copy the whole thing into fwh\samples and link using buildh.bat or the modified -3.bat supplied.

The bug would go away if I don't call ValidLic32() at all but I can't do that as copy-protection is implemented using it (a SoftwareKey.com product). Any help to resolve this is greatly appreciated.

Here's the test code at a glance for those interested:
Code: Select all  Expand view


#include "fivewin.ch"
// License file defines
#define LF_CREATE_NORMAL    0 //attribute used if License File is created
#define LF_FILE             1 //normal filesystem
#define PP_SUCCESS          1

#define VAR_COMPANY         1
#define VAR_EXPIRE_TYPE     9

memvar zname // Company Name

function bugs()
  local i, cStr, cOriStr, cTitle
  public zname
  if !ValidLic32() // License validation. zname assigned here
     return nil
  endif

  cOriStr := zname
  cStr    := ""

  // copy the string one character at a time
  for i := 1 to len(cOriStr)
     cStr += substr(cOriStr,i,1)
  next

  msginfo( "cOriStr: " + cOriStr + CRLF + ;
           "cStr   : " + cStr,"Copied string: "+if(cOriStr==cStr, "IDENTICAL", "DIFFERENT"))
RETURN NIL
//----------------------------------------------------------------------
function ValidLic32()
  local cDataPath := cFilePath(getmodulefilename(getinstance())), nRet, lRet := .t., oSWKey

  // turn pp_xxx funcs into a class to avoid a very frequent loading and unloading
  // of keylib32.dll in a very short time
  if (oSWKey := TValidLic():new()) == nil
     return .f.
  endif

  begin sequence
    // open license file
    nRet := oSWKey:pp_lfopen(cDataPath+'product.lf', LF_CREATE_NORMAL, LF_FILE, "password")
    if nRet != PP_SUCCESS
       oSWKey:SayErr(nRet)
       break
    endif

    oSWKey:GetZname()   // Read company name from license file
    oSWKey:expiryType() // rem-ing this part would make the bug stop to appear

  recover
    lRet := .f.
  end

  oSWKey:end()
  oSWKey := nil
return ( lRet )
//----------------------------------------------------------------------
class TValidLic
  data hDLL, lfHnd, cExpType

  method new()
  method GetZName()
  method expiryType()
  method pp_errorstr(errorcode, @buffer )
  method pp_lfopen(filename, flags, lfType, password)
  method pp_getvarchar(varno, @buffer)
  method pp_lfclose()
  method SayErr(nRet)
  method end()
endclass
//----------------------------------------------------------------------
method new() class TValidLic
  local oRet
  ::hDLL := 0
  if abs(::hDLL := LoadLibrary("keylib32.dll")) <= 32
     msgalert("Error loading keylib32.dll", "Error "+lstr(::hDLL))
  else
     oRet := self
  endif
return oRet
//----------------------------------------------------------------------
method pp_errorstr( errorcode, buffer) class TValidLic
  local nRet, cFarProc
  if Abs( ::hDLL ) > 32
     cFarProc = GetProcAdd( ::hDLL, "pp_errorstr", .T., 0,7,9 )
     nRet := FWCallDLL( cFarProc, errorcode, @buffer )
  end

return nRet
//----------------------------------------------------------------------
method pp_getvarchar(varno, buffer) class TValidLic
  local nRet, cFarProc
  if Abs( ::hDLL ) > 32
     cFarProc := GetProcAdd( ::hDLL, "pp_getvarchar", .T., 7,7,7,9 )
     nRet := FWCallDLL( cFarProc, ::lfhnd , varno, @buffer )
  end

return nRet
//----------------------------------------------------------------------
method pp_lfclose() class TValidLic
  local nRet, cFarProc
  if Abs( ::hDLL ) > 32
     cFarProc = GetProcAdd( ::hDLL, "pp_lfclose", .T., 7,7 )
     nRet := FWCallDLL( cFarProc, ::lfhnd )
  end
return nRet
//----------------------------------------------------------------------
method pp_lfopen(filename, flags, lfType, password) class TValidLic
  local nRet, cFarProc
  if Abs( ::hDLL ) > 32
     cFarProc = GetProcAdd( ::hDLL, "pp_lfopen", .T., 7,9,7,7,9,7 )
     nRet := FWCallDLL( cFarProc, filename, flags, lfType, password, @::lfhnd )
  end
return nRet
//----------------------------------------------------------------------
method function getzname() class TValidLic

  zname := space(50)
  ::pp_getvarchar(VAR_COMPANY, @zname)
  zname := upper(trim(zname))
  if asc(right(zname,1))==0
     zname := left(zname, len(zname)-1)
  endif
  zname := trim(zname)
return nil
//----------------------------------------------------------------------
method expiryType() class TValidLic
  local nRet, cExpType := space(1)
  nRet := ::pp_getvarchar(VAR_EXPIRE_TYPE, @cExpType)
  ::cExpType := cExpType
return nRet
//----------------------------------------------------------------------
method SayErr(nRet) class TValidLic
  local cStr := space(50),a := procname(1)+" ("+ltrim(str(procline(1)))+")"
  ::pp_errorstr(nRet, @cStr)

  msglist({"License error: "+ltrim(str(nret))+" "+cStr,"Called from "+a},"Error",10,20,18,59.5,"Ok")

return nil
//----------------------------------------------------------------------
method end() class TValidLic
  if !empty(::lfhnd)
     ::pp_lfclose()
  endif
  if abs(::hDLL) > 32
     freeLibrary(::hDLL)
  endif
return nil
//----------------------------------------------------------------------
 


TQVM
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1070
Joined: Fri Oct 28, 2005 2:27 am

Re: Memory is overwritten after calling functions in DLL

Postby nageswaragunupudi » Wed Oct 05, 2011 8:21 am

cExpType := space(1)

What if cExpType is initialized with longer char value, lime Space(20) or so?
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10482
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: Memory is overwritten after calling functions in DLL

Postby hua » Wed Oct 05, 2011 10:15 am

OMG! :shock: It worked! Thanks a million Rao! :) I don't know what actually happened but that little trick works!

So, what's the idea actually? I thought doing such kind of thing could overwrite data in other memory addresses since we're stepping out of our bounds (i.e. passing a var with length of 10 instead of the documented 1)?

Anyway, big two thumbs up to you Rao. Bugs for this module has been on my to do list for months. I can also put off research on using Harbour's native DLL function [hb_libload(), hb_libfree() and hb_dyncall() ]

I've changed the pp_getvarchar() and getZName() method this way:
Code: Select all  Expand view

method pp_getvarchar(varno, buffer) class TValidLic
  local nRet, cFarProc, nOriLen := len(buffer)
  buffer += space(10)
  if Abs( ::hDLL ) > 32
     cFarProc := GetProcAdd( ::hDLL, "pp_getvarchar", .T., 7,7,7,9 )
     nRet := FWCallDLL( cFarProc, ::lfhnd , varno, @buffer )
  end
  buffer := padr(strtran(buffer,chr(0)), nOriLen)
return nRet

method function getzname() class TValidLic

  zname := space(50)
  ::pp_getvarchar(VAR_COMPANY, @zname)
  zname := upper(trim(zname))
return nil
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1070
Joined: Fri Oct 28, 2005 2:27 am

Re: Memory is overwritten after calling functions in DLL

Postby nageswaragunupudi » Wed Oct 05, 2011 1:07 pm

Code: Select all  Expand view
So, what's the idea actually? I thought doing such kind of thing could overwrite data in other memory addresses since we're stepping out of our bounds (i.e. passing a var with length of 10 instead of the documented 1)?
 

If the length documented is 1, please try with Space(2). One extra character to accommodate the trailing zero of c char strings.
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10482
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Re: Memory is overwritten after calling functions in DLL

Postby hua » Wed Oct 05, 2011 2:04 pm

Thanks for the tip Rao. Will amend my code as you suggested :)
FWH 11.08/FWH 19.12
BCC5.82/BCC7.3
xHarbour/Harbour
hua
 
Posts: 1070
Joined: Fri Oct 28, 2005 2:27 am


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: nageswaragunupudi and 17 guests