3

Reading this page on TLDP: http://www.tldp.org/LDP/abs/html/mathc.html

I've found the following command:

bash$ echo "16i[q]sa[ln0=aln100%Pln100/snlbx]sbA0D68736142snlbxq" | dc
Bash

And I was just wondering: someone knows what type of hash is that and how I can convert a simple text to generate that kind of hash?

thanks

Hector
  • 31
  • 1
  • Yes, thanks, it's what I have done. Unfortunately I can't find what I am looking for. I suppose there is a way in perl to encode or decode that type of hash or string, but I have no idea how. – Hector Aug 19 '14 at 11:08
  • `dc` doesn't have hashes. `[...]` creates a string. – Barmar Aug 19 '14 at 11:10
  • 1
    [This site](https://www.mkssoftware.com/docs/man1/dc.1.asp#Array_Operations) looks like a decent tutorial on `dc`. – Barmar Aug 19 '14 at 11:13
  • I don't think `dc` is heavily used these days, so you may have to wait a while for someone who knows it to come around and translate that for you. Maybe the author of the web site can help you. – Barmar Aug 19 '14 at 11:14
  • 4
    From the way that command is presented on tldp.org, it looks like it was designed to be confusing -- it's an example of the `dc experts` showing off how cryptic they can write things. – Barmar Aug 19 '14 at 11:17

1 Answers1

4

Relatively good tutorial is here. Using it, you'll get the next decomposition:

  • 16i - the input will be hexadecimal (like in bc - ibase=16)
  • [q] - the [..] mean string. So this store a string q to the top of stack. Usually the [....] is a series of commands stored for later execution (like a macro), in this case the command q - quit.
  • the s - take the top of stack and store it to register identified by the next letter, so the [q]sa together in this case mean: store the the string q into register a
  • same with the next, store the string ln0=aln100%Pln100/snlbx into register b
  • the next A0D68736142sn, store the A0D68736142 into register n. In this case not a string, but because we have input hexaadecimal, this is an hexadecimal number

The above is an like a preparation phase, translated into common programming language:

$a = "q";
$b = "ln0=aln100%Pln100/snlbx";
$n = 0xA0D68736142";

The stack is now empty (everything is stored in registres).

The next is the final calculation:

  • the l mean take the the the value from the followed register, and put it to the top of stack so the lb mean: take the value of register b.
  • the x mean: execute it as an series of commands - in this case read it as eval "$b";
  • the last q mean quit

now need decompose the ln0=aln100%Pln100/snlbx (content of register b - what is eval-ing.)

  • ln - as above, take the value from the register n in our case: the hexa-number
  • next is a tricky part: 0=a, take the top of stack, and if it is zero execute the string (macro) stored in the registry "a" (in our case this is a "q" - quit), e.g. like:
if( $n == 0 ) eval "a"; #a contains "q" = quit
  • if the $n isn't zero, take the content of regsiter n again (ln) (put to the top of stack)
  • put the number 100 (it is hexa) to to top of stack
  • % modulo the two numbers from the top of the stack (so: $n % 0x100) and put it to the top of the stack
  • print the top of stack as an ascii string ( chr($stack) )
  • ln take again the number $n (again, it comes to the top of stack)
  • put 100 to the stack
  • / divide the to numbers in the stack (result comes into the top)
  • sn store the stack into the $n (replaces the original number)
  • lbx - as above - eval the register b

So, in short:

  • from the number 0xA0D68736142 stored in $n,
  • modulo it by 0x100 get the last two digits, convert it to ascii and print it,
  • divide it by 0x100 (removes last two digits) - and store it to $n
  • repeat until nothing remained (zero)

For the 0xA0D68736142 you will get (use man ascii)

  • 42 - B
  • 61 - a
  • 73 - s
  • 68 - h
  • 0D - \r
  • A (as 0A) - \n

Creating such hexsting from normal ascii string with perl

perl -E '$s=reverse("Bash\r\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'

prints

0A0D68736142

or

perl -E '$s=reverse("Stackoverflow rocks\n");$s =~ s/(.)/sprintf("%02x",ord($1))/seg;say uc $s'

0A736B636F7220776F6C667265766F6B63617453

and

echo "16i[q]sa[ln0=aln100%Pln100/snlbx]sb0A736B636F7220776F6C667265766F6B63617453snlbxq" | dc

prints:

Stackoverflow rocks

Ps: with dc is one strange thing - it is much-much easier to read and understand a "program" as creating one. :)

clt60
  • 62,119
  • 17
  • 107
  • 194
  • @Hector this is not "dc-string", but simple hexadecimal values of the string. You can create some manually with `man ascii` or see the edit for perl script. – clt60 Aug 19 '14 at 12:53
  • @Hector - And if youre satisfied with the answer, you can also click Accept (the green mark) at the answer... :) – clt60 Aug 19 '14 at 13:35