• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 392
  • Last Modified:

dynamic array and variant record

Hi all. I'll try to explain my problem. In order to hide some sensitive string
in a my program, I use a tecnique I don't know hot to call it, so I describe it.

I declare a record this way:
Rec = record
      case Boolean of
        False: (s: array[0..51] of AnsiChar);
        True: (i: array[0..12] of Integer);
    end;

Open in new window


Obviously the arry's length depends on the string length. Then, supposing the
string is s:
 
procedure TForm2.btnCreateStringClick(Sender: TObject);
var
  r: Rec;
  s: AnsiString;
  I: Integer;
  code, value: string;
begin
  //da stringa a Cardinal
  FillChar(r.s, SizeOf(r.s), 0);
  s := 'IDontKnowHowToDoItButIHopeYouCanHelpMeEasilyAndSoon';
  Move(PAnsiChar(s)^, r.s, Length(s));
  for I := Low(r.i) to High(r.i) do
  begin
    value := IntToStr(not(r.i[I] shl 1));
    mmoString.Lines.Add('r.i['+ IntToStr(I) +'] := Cardinal(not ' + value + ') shr 1;');
  end;
end;

Open in new window


This way I can refer to the string using r.s and the cracker has to work a lot more
to break my code.

Since I have yet changed several times the string to mask this way (it is the
url for convalidation the software license), I thought to make a little utility
to allow me to simply tyoe the string and output the record values to use in my code.
For the above example this code is:

 
r.i[0] := Cardinal(not 521606959) shr 1;
r.i[1] := Cardinal(not 933339531) shr 1;
r.i[2] := Cardinal(not 790570805) shr 1;
r.i[3] := Cardinal(not 924924205) shr 1;
r.i[4] := Cardinal(not -1557060819) shr 1;
r.i[5] := Cardinal(not 296035637) shr 1;
r.i[6] := Cardinal(not 765672245) shr 1;
r.i[7] := Cardinal(not 758358295) shr 1;
r.i[8] := Cardinal(not -1592183513) shr 1;
r.i[9] := Cardinal(not 1027022613) shr 1;
r.i[10] := Cardinal(not -1592183529) shr 1;
r.i[11] := Cardinal(not 252786489) shr 1;
r.i[12] := Cardinal(not 924784035) shr 1;

Open in new window


The r.s is 'IDontKnowHowToDoItButIHopeYouCanHelpMeEasilyAndSoon'.

Only problem is that I wish only type a string, and click a button without the
need to change the record declaration every time.

I tried to make the two arrays dynamic but I received this error:

"Type 'dynamic array' needs finalization - not alloweed in variant record".

How can I solve this' Have you a workaround?

Thanks in advance for any try to help me
0
Marco Gasi
Asked:
Marco Gasi
  • 5
  • 5
1 Solution
 
epasquierCommented:
first :
Move(PAnsiChar(s)^, r.s, Length(s));
=
Move(s[1], r.s, Length(s));

then, it can be simplified a bit
Type
 EncodedString=Array of Cardinal;

procedure EncodeString(Str:AnsiString;Var R:EncodedString);
Var
 i:integer;
begin
 SetLength(R,Length(Str));
 for i:=1 to Length(Str) do R[i-1]:=Not(Byte(Str[i]) SHL 1);
end;

procedure DecodeString(const R:EncodedString;Var Str:AnsiString);
Var
 i:integer;
begin
 SetLength(Str,Length(R));
 for i:=1 to Length(Str) do Str[i]:=AnsiChar((Not R[i-1]) SHR 1);
end;

procedure WriteDecodingCode(const StrVarName:String;const Enc:EncodedString);
Var
 EncConstArray:String;
 i:integer;
begin
 if Length(Enc)=0 Then Exit; // prevent errors
 mmoString.Lines.Add('DecodeString('+StrVarName+',[');
 EncConstArray:='';
 for i:=0 to Length(Enc)-1 do EncConstArray:=EncConstArray+IntToStr(Enc[i])+',';
 EncConstArray[Length(EncConstArray)]:=']'; // replace last ',' with ']'
 mmoString.Lines.Add(EncConstArray+');');
end;

Open in new window

0
 
epasquierCommented:
so, in your encoding tool application :

Var
 Enc:EncodedString;
begin
 EncodeString(edtStringToEncode.Text, Enc );
 WriteDecodingCode( edtStringVarName.Text, Enc );
end;

and include DecodeString in your target application
0
 
Marco GasiFreelancerAuthor Commented:
Thanks for your answer, epasquier. I'll try it as soon as possible  - now I have to prepare my wedding anniversary and I can stay no more at the beloved computer ;-)

Only a thing. You simplified the Move statement but you didn't use it in your code: your code doesn't need it? Or I have to merge my code with yours?

'See' you later...
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
epasquierCommented:
no need to merge anything, take just my code

I only started with a comment on Move because obviously you didn't knew how to perform it that way.

Good Wedding Anniversary !

A night of love one never forgets...
0
 
Marco GasiFreelancerAuthor Commented:
Thanks a lot for your help, epasquier. It works very fine :-)
0
 
Marco GasiFreelancerAuthor Commented:
Hi, epasquier. Are you still monitoring this question? I have a little problem: I can't copy and past the output of your code because Delphi7 doesn't compile it. Suppose string is 'Pippo'; The output is

DecodeString(Pippo,[
4294967135,4294967085,4294967071,4294967071,4294967073]);

Thisis wrong, because DecodeString procedure requires the first parameter be and EncodedString and the second one an AnsiString. I tried to change this way

DecodeString([
4294967135,4294967085,4294967071,4294967071,4294967073], s);

But with this code I receive this error: 'Constants expression violates subrange bounds'

I tried several ways, with quotes, without brackets and so on  but I didn't succeed. Can youhelp me?
0
 
epasquierCommented:
ok, my bad you cannot pass array of Cardinal like that. Only  'array of const' can be but it's more complex. Let's build a var EncConst of type EncodedString instead and pass it (first parameter, I made also an error here)

procedure WriteDecodingCode(const StrVarName:String;const Enc:EncodedString);
Var
 i:integer;
begin
 if Length(Enc)=0 Then Exit; // prevent errors
 mmoString.Lines.Add('SetLength(EncConst,'+IntToStr(Length(Enc))+');');
 for i:=0 to Length(Enc)-1 do 
  mmoString.Lines.Add(Format('EncConst[%d]=%d',[i,Enc[i]]));
 mmoString.Lines.Add('DecodeString(EncConst,'+StrVarName+');');
end;

Open in new window

0
 
Marco GasiFreelancerAuthor Commented:
Hi, epasquier. Thank you for trying to help me and I'm sorry to waste your time, but that doesn't work.

The result is

SetLength(EncConst,5);
EncConst[0]=-161
EncConst[1]=-211
EncConst[2]=-225
EncConst[3]=-225
EncConst[4]=-223
DecodeString(EncConst,pippo);

The problem is syntactical and I fixed that making this

SetLength(EncConst,5);
EncConst[0]:=-161;
EncConst[1]:=-211;
EncConst[2]:=-225;
EncConst[3]:=-225;
EncConst[4]:=-223;
DecodeString(EncConst,s);

where s is an empty string which will holds the decoded value (It's right this?). Unfortunately I still receive the same error message: 'Constants expression violates subrange bounds'

Thanks a lot.
0
 
epasquierCommented:
Cardinal is unsigned int, so I guess the format function treats it as Integer. Just declare
Type
 EncodedString=Array of Integer;

Open in new window

0
 
Marco GasiFreelancerAuthor Commented:
Yeah, now it works fine! Thank you very mutch for your help. On to the next. :-)
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 5
  • 5
Tackle projects and never again get stuck behind a technical roadblock.
Join Now