winexe: Fix translation of the winexesvc binaries to C
authorKarl Lenz <xorangekiller@gmail.com>
Thu, 4 Jul 2019 22:30:44 +0000 (18:30 -0400)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 5 Jul 2019 03:33:19 +0000 (03:33 +0000)
Two small Windows binaries that winexe uses to execute commands on a
remote system, winexesvc32.exe and winexesvc64.exe, are compiled then
translated into a C byte array as hex so that they can be embedded into
the winexe binary. Although the winexesvc binaries were built properly,
the Python method that does the translation to C tried to open them in
text mode, which would have worked in Python 2 before the concept of
bytearrays was introduced, but instead raises an exception in Python 3.
The exception was unfortunately suppressed, so the build didn't stop,
and the winexe binary that was produced was effectively useless because
it didn't contain either winexesvc binary as expected. After winexe
successfully authenticated with a Windows host, it showed the error
message below rather than executing the given command on the remote
system.

$ ./bin/winexe -U karl%password1 -d 2 //192.168.56.3 cmd
winexe_svc_install: dcerpc_svcctl_StartServiceW failed: WERR_BAD_EXE_FORMAT
main: winexe_svc_install failed: NT_STATUS_BAD_INITIAL_PC

This commit fixes that problem by opening the winexesvc binaries in
binary mode rather than text mode when the winexe build script reads
them to translate them to C. Furthermore it adds an additional
sanity check that will cause the winexesvc binary generator commands to
fail if the winexesvc binaries cannot be opened or read correctly to
guarantee that the build does not silently "succeed" if something like
this ever happens again.

Signed-off-by: Karl Lenz <xorangekiller@gmail.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
examples/winexe/wscript_build

index ecad3772461b8d3d69b9f3ea0dbce699acda2107..43c09717e3dc04dc67dd36a22d17475290f7fec5 100644 (file)
@@ -3,10 +3,18 @@
 import samba_utils
 
 def generate_winexesvc_c_from_exe(t):
+    '''generate a C source file with the contents of the given binary'''
     src = t.inputs[0].bldpath(t.env)
     tgt = t.outputs[0].bldpath(t.env)
     fn = t.env.SAMBA_GENERATOR_VARS['WINEXE_FN']
-    src_blob = samba_utils.load_file(src)
+
+    try:
+        with open(src, 'rb') as f:
+            src_blob = f.read()
+            f.close()
+    except:
+        print('Failed to read %s to convert to C array' % (src))
+        return -1
 
     def c_array(src):
         N = 0
@@ -14,11 +22,23 @@ def generate_winexesvc_c_from_exe(t):
         while src:
             l = src[:8]
             src = src[8:]
-            h = ' '.join(["0x%02X," % ord(x) for x in l])
+            # Even files opened in binary mode are read as type "str" in
+            # Python 2, so we need to get the integer ordinal of each
+            # character in the string before we try to convert it to hex.
+            if isinstance(l, str):
+                h = ' '.join(["0x%02X," % ord(x) for x in l])
+            # Files opened in binary mode are read as type "bytes" in
+            # Python 3, so we can convert each individual integer in the
+            # array of bytes to hex directly.
+            else:
+                h = ' '.join(["0x%02X," % x for x in l])
             result += "\t\t%s\n" % (h)
         return result
 
     src_array = c_array(src_blob)
+    if len(src_array) <= 0:
+        print('Failed to convert %s to C array' % (src))
+        return -1
 
     contents = '''
 #include "replace.h"
@@ -38,8 +58,10 @@ const DATA_BLOB *%s(void)
 }
 ''' % (fn, fn, src_array)
 
-    ret = samba_utils.save_file(tgt, contents)
-    assert(ret == True)
+    if not samba_utils.save_file(tgt, contents):
+        print('Failed to write C source file %s' % (tgt))
+        return -1
+    return 0
 
 winexesvc_binaries = ''