
    UHj3                    4   d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZ  ee      j                         j                  d   Zedz  ZdZd	Zd
ZddZddZddZddZdddZddZd dZd!dZd"dZd#dZd"dZefd$dZd%dZ e!dk(  r e         yy)&zJSummarize script handler table entries used by save-selector leaf streams.    )annotationsN)Path)read_sectionsva_to_offset   outi D i#@ `   c                v    t        ||      }||dz   t        |       kD  ry t        j                  d| |      d   S )N   z<Ir   )r   lenstructunpack_from)exesectionsvaoffsets       ;/home/exedev/hwanse/tools/summarize_script_handler_table.pydword_atr      s?    (B'F~!c#h.dC033    c                V    | D ]$  }|d   }||d   z   }||cxk  r|k  sn |d   c S  y )Nr   raw_sizename )r   r   sectionstartends        r   section_name_for_var      sE     #gj))B6?"	#
 r   c           
         t         |dz  z   }t        | ||      }|t        ||      nd }|d|d|d|d||d|dnd ||t        k(  |dk(  d	}||dk(  r|t        k7  rt	        | ||      |d<   |S )Nr   0x02x08x.text)	opcode	opcodeHexentryVa
entryVaHex	handlerVahandlerVaHexhandlerSectionisDefaultHandlerisCodeHandlerstreamEffect)HANDLER_TABLE_VAr   r   DEFAULT_HANDLER_VAanalyze_stream_effect)r   r   r#   entry_va
handler_vahandler_sectionentrys          r   handler_for_opcoder4   %   s    &1*,H#x2JCMCY)(J?_cO&&8C.)1;1G"Z,-T)&*<<(G3
E /W"<OaAa 5c8Z PnLr   c                    g }t        t              D ]=  }t        | |t        |dz  z         }|t	        ||      dk(  s-|j                  |       ? t        t        |            S )Nr   r"   )rangeHANDLER_TABLE_SCAN_COUNTr   r-   r   appendsortedset)r   r   handlersr#   handlers        r   table_handler_vasr=   9   sf    H01 %3*:VaZ*GH#6x#IW#TOOG$% #h-  r   c                   t        ||      }|yt        | |      D cg c]
  }||kD  s	| }}|rt        |      n||z   }t        dt        |||z
              }| |||z    }	|	j	                  d      }
|
dk\  r|	d |
dz    S |	S c c}w )Nr   r      r   )r   r=   minmaxfind)r   r   r1   max_sizer   r   next_handlersstop_vasizecoderets              r   handler_bytesrI   B   s    (J/F~"3C"BVBb:oRVMV$1c- zH7LGq#h* 456Dvv}%D
))G
C
axIcAgK Ws
   
BBc           	         t        | ||      }g }g }g }d}t        t        |      dz
        D ]  }||z   }	|||dz    dk(  r4|dz   t        |      k  r#|j                  d|dd|	d||dz      d       |||dz    d	v r@|dz   t        |      k  r/||dz      }
|
d
k  r"|j                  d|dd|	d|
d|
dd       |||dz    dk(  rA|dz   t        |      k  r0||dz      }
|
d
k  r#|j                  d|dd|	d|
d|
ddd       |||dz    dk(  s|j                  d|dd|	ddd       	 t        t        |      dz
        D ]  }|||dz    dk(  sd||dz   |dz    v sd}  t        |      ||||dS )NF   s   @@r   r    r!   )handlerOffsetHexvaHexbytes   >      @   H   @   )rL   rM   streamOffsetstreamOffsetHexs   f@)rL   rM   rT   rU   widths   A@storeEaxToContextStream)rL   rM   kind   s   @   T)	scanBytesfixedAdvancesstreamReadsstreamStorescanJumpToDwordAtPlus4)rI   r6   r   r8   )r   r   r1   rG   advancesreadsstorescan_jump_to_stream_plus4r   absolutestream_offsets              r   r/   r/   P   sF   h
3DHEF$D	A&  &
#66A:D	;QOO&($5hs^,fqj) 
 
#'NNSY\]S]`cdh`iSi !,M$*,VCL(9!(30$1)+M#+>'?	  
#66A:D	;Q !,M$*,VCL(9!(30$1)+M#+>'?  
#6MM&($5hs^,1 9 B D	A& ,
#6?dSY\]S]_ehj_jNk;k'+$, Y!!9 r   c                   i }| D ]@  }d|j                  d      |j                  d      xs g fd|j                  d      |j                  d      xs g fg}|D ]  \  }}}|s
|D ]  }|j                  d      }t        |t              s%t        |d      }	|	d	z  }
|j	                  |
g       j                  |||j                  d
      |j                  d      ||j                  d      |j                  d      |j                  d      |j                  d      |j                  d      |j                  d      du d         C |S )NleafleafPointerHexwordsnestednestedPointerHexnestedWordsvalueHexrS      indexrM   sourcetargetcnspointerT)
streamKindstreamVaHex	wordIndex	wordVaHexrm   rh   rk   rp   rq   rr   rs   )get
isinstancestrint
setdefaultr8   )	leaf_rowsrefsrowstreamsstream_kind	stream_vari   word	value_hexvaluer#   s              r   leaf_word_refsr      sR   "$D SWW-.0@0FBGsww12CGGM4J4PbQ
 .5 	)KE  HHZ0	!)S1Ir*+22&1'0%)XXg%6%)XXg%6$-*-''2B*C,/GG4F,G"%''("3"%''("3#xx#'88I#6$#>	: Kr   c                ^   t        |       }t        |      }t        |      }g }|D ]9  }t        | ||      }t	        ||         |d<   ||   |d<   |j                  |       ; t        dt        dt        dt        ddt	        |      t        d |D              t        d |D              |d	S )	NreferenceCount
referencesr   r!   zCfirst-byte handler candidates from save-selector leaf stream dwordsc              3  ,   K   | ]  }|d    s	d  yw)r+   r   Nr   .0r3   s     r   	<genexpr>z build_summary.<locals>.<genexpr>   s     Qe%:PQ   
c              3  ,   K   | ]  }|d    s	d  yw)r*   r   Nr   r   s     r   r   z build_summary.<locals>.<genexpr>   s     "WUCU=V1"Wr   )	handlerTableVahandlerTableVaHexdefaultHandlerVadefaultHandlerVaHexscopeopcodeCountcodeHandlerCountdefaultHandlerCountentries)	r   r   r9   r4   r   r8   r-   r.   sum)r   r}   r   r~   opcodesr   r#   r3   s           r   build_summaryr      s    S!H)$DTlGG "3&9"%d6l"3"6llu	 +!"23!78.!#$6s#;<V7|QwQQ""W'"WW
 
r   c                   ddddddd| d    dd	| d
    d| d    d| d    ddddg}| d   D ]  }dj                  d |d   d d D              }|d   dkD  r|dz  }t        |j                  d      xs i       }|j                  d|d    d|d    d|j                  d      xs d d |j                  d!      xs d d"| d"|j                  d#      rd$nd% d"|d    d"| d&        |j                  d       d'j                  |      S )(Nz!# Script Handler Table Candidates z`These rows map the low byte of each save-selector leaf-stream dword to the script handler table.zdThey are first-byte handler candidates only; they do not prove instruction length or operand layout.zeRows whose resolved handler is not in `.text` are likely operand/pointer low bytes, not real opcodes.zHandler table: `r   z`.z Distinct first-byte candidates: r   z (r   z resolve into `.text`, r   z use the default handler).zd| opcode | handler entry | handler | section | stream effect | default | refs | example leaf words |z2| --- | --- | --- | --- | --- | --- | ---: | --- |r   z, c              3  B   K   | ]  }|d     d|d    d|d      ywru   [rv   z]=rm   Nr   r   refs     r   r   zmarkdown.<locals>.<genexpr>   s:      
 =!"!C$4#5RJ7HI
s   r      r   z, ...r,   z| `r$   z` | `r&   r(   -z` | r)   z | r*   yesnoz |
)joinstream_effect_textrx   r8   )summarylinesr3   exampleseffects        r   markdownr      s   +
jno

7#678;
*7=+A*B C&'((?H]@^?__y	{
n<E # 
99 
\*2A.
 
 !"Q&H#EIIn$=$CD%$%U5+>*?uUYY~E^EebeDffjyy)*1c2#fXS%))TfJgmq@rru%&'s8*B8	

 
LL99Ur   c                   | syg }t        | j                  dg       D ch c]%  }|j                  d      s|j                  d      ' c}      }|r*|j                  ddj                  d |D              z          t        | j                  dg       D ch c]%  }|j                  d      s|j                  d      ' c}      }|r&|j                  d	d
j                  |d d       z          | j                  d      r|j                  d       | j                  d      r|j                  d       dj                  |      xs dS c c}w c c}w )Nr   r\   rN   zadvance /c              3  &   K   | ]	  }d |   yw)+Nr   )r   r   s     r   r   z%stream_effect_text.<locals>.<genexpr>   s     *M5Qug;*Ms   r]   rU   zread ,rY   r_   zjump [stream+4]r^   zwrites streamz; )r9   rx   r8   r   )r   partsitemr`   ra   s        r   r   r      s   EVZZQS5TjTX\X`X`ahXitxx(jkHZ#((*MH*M"MMNFJJ}VX<YyD]a]e]efw]xDHH./yzEWsxxbq	223zz)*&'zz.!_%99U"s" k zs   EEE,Ec                   g }| d   D ]  }dj                  d |d   d d D              }|d   dkD  r|dz  }t        |j                  d      xs i       }|j                  d	t	        j
                  |d
          dt	        j
                  |d          dt	        j
                  |j                  d      xs d       dt	        j
                  |j                  d      xs d       dt	        j
                  |       d|j                  d      rdnd d|d    d| d        dj                  dddddddddd d!d"d#d$d%d&d'd(t	        j
                  | d)          d*| d+    d,| d-    d.| d/    d0	d1d2d3dj                  |      xs d4d5d6d7d8d9g      S ):Nr   z<br>c           	   3  h   K   | ]*  }t        j                  |d     d|d    d|d           , ywr   )htmlescaper   s     r   r   zhtml_page.<locals>.<genexpr>   sC      
 KK3}-.aK0@/AC
OCTUV
s   02r   
   r   z<br>...r,   z<tr><td><code>r$   z</code></td><td><code>r&   r(   r   z</code></td><td>r)   z	</td><td>r*   r   r   z
</td></tr>r   z<!doctype html>z<html lang="en">z<head>z  <meta charset="utf-8">zF  <meta name="viewport" content="width=device-width, initial-scale=1">z0  <title>Script Handler Table Candidates</title>z	  <style>z^    body { margin: 24px; background: #101010; color: #eee; font: 14px system-ui, sans-serif; }z5    table { border-collapse: collapse; width: 100%; }zM    th, td { border: 1px solid #333; padding: 6px 8px; vertical-align: top; }z9    th { background: #1d1d1d; position: sticky; top: 0; }z    code { color: #f5d76e; }z
  </style>z</head>z<body>z*  <h1>Script Handler Table Candidates</h1>z  <p>These rows map the low byte of each save-selector leaf-stream dword to the script handler table. They are first-byte handler candidates only; rows whose resolved handler is not in <code>.text</code> are likely operand/pointer low bytes.</p>z  <p>Handler table: <code>r   z</code>. Distinct candidates: r   z; code handlers: r   z; default handlers: r   z.</p>z	  <table>z    <thead><tr><th>opcode</th><th>entry</th><th>handler</th><th>section</th><th>stream effect</th><th>default</th><th>refs</th><th>examples</th></tr></thead>z    <tbody>z,<tr><td colspan="8">No candidates.</td></tr>z    </tbody>z
  </table>z</body>z</html>r   )r   r   rx   r8   r   r   )r   	body_rowsr3   r   r   s        r   	html_pager      sN   I# 
;; 
\*3B/
 
 !"R'	!H#EIIn$=$CDU;%789 :U<%89: ;UYY~%>%E#FG H;;uyy)9:AcBC D;;v&' (!II&895tD E)*+ ,* 		

( 99"P:h?WC&4 	@
$T[[9L1M%N$OOmnu  wD  oE  nF  FW  X_  `r  Xs  Wt  tH  IP  Qf  Ig  Hh  hm  	n 	h		)N N
7  r   c                    |j                  dd       |dz  j                  t        j                  | dd      dz   d	       y )
NT)parentsexist_okscript_handler_table.jsonF)r   :)ensure_ascii
separatorsr   utf-8encoding)mkdir
write_textjsondumps)r   out_dirs     r   write_outputsr   "  sC    MM$M.**66

7:FM 7 r   c                    t        j                  t              } | j                  dt        t
        dz         | j                  dt        t        dz         | j                  dt        t               | j                         }t        |j                  j                         t        j                  |j                  j                  d	                  }t        ||j                          t#        d
|d    d|j                   dz          y )N)descriptionz--exezHwanse2.exe)typedefaultz--leaf-streamszsave_selector_leaf_streams.jsonz	--out-dirr   r   zwrote r   z script handler candidates -> r   )argparseArgumentParser__doc__add_argumentr   ROOTOUT
parse_argsr   r   
read_bytesr   loadsleaf_streams	read_textr   r   print)parserargsr   s      r   mainr   *  s    $$9F
dD=4HI
(tSCd=de
$<D

4$$...@AG '4<<(	F7=)**HXsIsHt
uvr   __main__)r   rN   r   
list[dict]r   r{   returnz
int | None)r   r   r   r{   r   z
str | None)r   rN   r   r   r#   r{   r   dict)r   rN   r   r   r   z	list[int])i   )
r   rN   r   r   r1   r{   rC   r{   r   rN   )r   rN   r   r   r1   r{   r   r   )r}   r   r   zdict[int, list[dict]])r   rN   r}   r   r   r   )r   r   r   rz   )r   r   r   rz   )r   r   r   r   r   None)r   r   )"r   
__future__r   r   r   r   r   pathlibr   probe_exe_scene_tablesr   r   __file__resolver   r   r   r-   r.   r7   r   r   r4   r=   rI   r/   r   r   r   r   r   r   r   __name__r   r   r   <module>r      s    P "      > H~''*
Ul   4(!0fD.@#"2j 25 w zF r   