about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorFabrice Desclaux <fabrice.desclaux@cea.fr>2019-11-02 22:24:23 +0100
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2019-11-12 15:10:44 +0100
commit4dc802e3544e669cfea1d6be8a01ca2a2600dfef (patch)
tree96a79b40469c1db9201ca46b210503d4dcf378c5
parent83e54bd2de945a36ab5ccd4cc5b94817d7cb0112 (diff)
downloadfocaccia-miasm-4dc802e3544e669cfea1d6be8a01ca2a2600dfef.tar.gz
focaccia-miasm-4dc802e3544e669cfea1d6be8a01ca2a2600dfef.zip
Clear get_str_* API
get_str_ansi decoded strings using utf8 and was blindly used for pure
windows function (LoadLibraryA) and for stdlib functions (printf,
strlen, ...) even if strlen does not use utf8...

New API is:

get_win_str_a/get_win_str_w and set_win_str_a/set_win_str_w for
windows (respectively codepage1252/windows utf16) .Those functions
should only be used in windows strings manipulations, so there are taken
out of the jitter.

get_c_str/set_c_str: as those functions are "classic" in OSes, they are
keeped in the jitter.
-rw-r--r--example/jitter/unpack_upx.py4
-rw-r--r--example/symbol_exec/dse_crackme.py7
-rw-r--r--miasm/analysis/sandbox.py20
-rw-r--r--miasm/core/utils.py16
-rw-r--r--miasm/jitter/jitload.py41
-rw-r--r--miasm/jitter/loader/elf.py2
-rw-r--r--miasm/jitter/loader/pe.py147
-rw-r--r--miasm/jitter/loader/utils.py23
-rw-r--r--miasm/os_dep/common.py35
-rw-r--r--miasm/os_dep/linux/syscall.py32
-rw-r--r--miasm/os_dep/linux_stdlib.py20
-rw-r--r--miasm/os_dep/win_api_x86_32.py297
-rw-r--r--miasm/os_dep/win_api_x86_32_seh.py6
-rw-r--r--test/arch/x86/qemu/testqemu.py6
-rw-r--r--test/arch/x86/qemu/testqemu64.py6
-rwxr-xr-xtest/os_dep/linux/stdlib.py2
-rwxr-xr-xtest/os_dep/win_api_x86_32.py9
17 files changed, 393 insertions, 280 deletions
diff --git a/example/jitter/unpack_upx.py b/example/jitter/unpack_upx.py
index 3b8125f4..baa6f0bb 100644
--- a/example/jitter/unpack_upx.py
+++ b/example/jitter/unpack_upx.py
@@ -5,6 +5,8 @@ from pdb import pm
 from miasm.loader import pe
 from miasm.analysis.sandbox import Sandbox_Win_x86_32
 
+from miasm.os_dep.common import get_win_str_a
+
 # User defined methods
 
 def kernel32_GetProcAddress(jitter):
@@ -17,7 +19,7 @@ def kernel32_GetProcAddress(jitter):
 
     # Handle ordinal imports
     fname = (args.fname if args.fname < 0x10000
-             else jitter.get_str_ansi(args.fname))
+             else get_win_str_a(jitter, args.fname))
     logging.error(fname)
 
     # Get the generated address of the library, and store it in memory to
diff --git a/example/symbol_exec/dse_crackme.py b/example/symbol_exec/dse_crackme.py
index be9f4490..82a7af08 100644
--- a/example/symbol_exec/dse_crackme.py
+++ b/example/symbol_exec/dse_crackme.py
@@ -20,6 +20,7 @@ from miasm.core.utils import int_to_byte
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.analysis.sandbox import Sandbox_Linux_x86_64
 from miasm.expression.expression import *
+from miasm.os_dep.win_api_x86_32 import get_win_str_a
 
 is_win = platform.system() == "Windows"
 
@@ -37,7 +38,7 @@ def xxx_fopen(jitter):
     '''
     global my_FILE_ptr
     ret_addr, args = jitter.func_args_systemv(['path', 'mode'])
-    fname = jitter.get_str_ansi(args.path)
+    fname = get_win_str_a(jitter, args.path)
     FILE_to_info[my_FILE_ptr] = FInfo(fname, open(fname, "rb"))
     my_FILE_ptr += 1
     return jitter.func_ret_stdcall(ret_addr, my_FILE_ptr - 1)
@@ -139,7 +140,7 @@ def xxx_fopen_symb(dse):
     mode = dse.eval_expr(regs.RSI)
     assert fname_addr.is_int()
     assert mode.is_int()
-    fname = dse.jitter.get_str_ansi(int(fname_addr))
+    fname = get_win_str_a(dse.jitter, int(fname_addr))
     ret_addr = ExprInt(dse.jitter.get_stack_arg(0), regs.RIP.size)
 
     assert len(FILE_to_info_symb) == 0
@@ -223,7 +224,7 @@ class FinishOn(Exception):
         super(FinishOn, self).__init__()
 
 def xxx_puts_symb(dse):
-    string = dse.jitter.get_str_ansi(dse.jitter.cpu.RDI)
+    string = get_win_str_a(dse.jitter, dse.jitter.cpu.RDI)
     raise FinishOn(string)
 
 
diff --git a/miasm/analysis/sandbox.py b/miasm/analysis/sandbox.py
index b8aaf788..3040a1a8 100644
--- a/miasm/analysis/sandbox.py
+++ b/miasm/analysis/sandbox.py
@@ -6,13 +6,13 @@ import logging
 from argparse import ArgumentParser
 
 from future.utils import viewitems, viewvalues
+from past.builtins import basestring
 
-from miasm.core.utils import force_bytes
 from miasm.analysis.machine import Machine
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.analysis import debugging
 from miasm.jitter.jitload import log_func
-
+from miasm.core.utils import force_bytes
 
 
 class Sandbox(object):
@@ -51,8 +51,7 @@ class Sandbox(object):
         """
 
         # Initialize
-        if not isinstance(fname, bytes):
-            fname = fname.encode('utf8')
+        assert isinstance(fname, basestring)
         self.fname = fname
         self.options = options
         if custom_methods is None:
@@ -183,17 +182,18 @@ class Arch(object):
 
 class OS_Win(OS):
     # DLL to import
-    ALL_IMP_DLL = ["ntdll.dll", "kernel32.dll", "user32.dll",
-                   "ole32.dll", "urlmon.dll",
-                   "ws2_32.dll", 'advapi32.dll', "psapi.dll",
-                   ]
-    modules_path = b"win_dll"
+    ALL_IMP_DLL = [
+        "ntdll.dll", "kernel32.dll", "user32.dll",
+        "ole32.dll", "urlmon.dll",
+        "ws2_32.dll", 'advapi32.dll', "psapi.dll",
+    ]
+    modules_path = "win_dll"
 
     def __init__(self, custom_methods, *args, **kwargs):
         from miasm.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\
             preload_pe, libimp_pe, vm_load_pe_and_dependencies
         from miasm.os_dep import win_api_x86_32, win_api_x86_32_seh
-        methods = dict((name.encode(),func) for name, func in viewitems(win_api_x86_32.__dict__))
+        methods = dict((name, func) for name, func in viewitems(win_api_x86_32.__dict__))
         methods.update(custom_methods)
 
         super(OS_Win, self).__init__(methods, *args, **kwargs)
diff --git a/miasm/core/utils.py b/miasm/core/utils.py
index 9856d4f2..7667a656 100644
--- a/miasm/core/utils.py
+++ b/miasm/core/utils.py
@@ -1,4 +1,5 @@
 from __future__ import print_function
+import sys
 from builtins import range
 import struct
 import inspect
@@ -86,6 +87,21 @@ def force_bytes(value):
         return value
 
 
+def force_str(value):
+    if isinstance(value, str):
+        return value
+    elif isinstance(value, bytes):
+        out = ""
+        for i in range(len(value)):
+            # For Python2/Python3 compatibility
+            c = ord(value[i:i+1])
+            out += chr(c)
+        value = out
+    else:
+        raise ValueError("Unsupported type")
+    return value
+
+
 def iterbytes(string):
     for i in range(len(string)):
         yield string[i:i+1]
diff --git a/miasm/jitter/jitload.py b/miasm/jitter/jitload.py
index 9fcb0b0a..e8277e34 100644
--- a/miasm/jitter/jitload.py
+++ b/miasm/jitter/jitload.py
@@ -429,8 +429,8 @@ class Jitter(object):
         return self.cpu.get_exception() | self.vm.get_exception()
 
     # commun functions
-    def get_str_ansi(self, addr, max_char=None):
-        """Get ansi str from vm.
+    def get_c_str(self, addr, max_char=None):
+        """Get C str from vm.
         @addr: address in memory
         @max_char: maximum len"""
         l = 0
@@ -440,31 +440,21 @@ class Jitter(object):
             tmp += 1
             l += 1
         value = self.vm.get_mem(addr, l)
-        return value.decode('utf8')
+        value = force_str(value)
+        return value
 
-    def get_str_unic(self, addr, max_char=None):
-        """Get unicode str from vm.
+    def set_c_str(self, addr, value):
+        """Set C str str from vm.
         @addr: address in memory
-        @max_char: maximum len"""
-        l = 0
-        tmp = addr
-        while ((max_char is None or l < max_char) and
-               self.vm.get_mem(tmp, 2) != b"\x00\x00"):
-            tmp += 2
-            l += 2
-        s = self.vm.get_mem(addr, l)
-        s = s.decode("utf-16le")
-        return s
-
-    def set_str_ansi(self, addr, string):
-        """Set an ansi string in memory"""
-        string = (string + "\x00").encode('utf8')
-        self.vm.set_mem(addr, string)
-
-    def set_str_unic(self, addr, string):
-        """Set an unicode string in memory"""
-        s = (string + "\x00").encode('utf-16le')
-        self.vm.set_mem(addr, s)
+        @value: str"""
+        value = force_bytes(value)
+        self.vm.set_mem(addr, value + b'\x00')
+
+    def get_str_ansi(self, addr, max_char=None):
+        raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a")
+
+    def get_str_unic(self, addr, max_char=None):
+        raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a")
 
     @staticmethod
     def handle_lib(jitter):
@@ -501,7 +491,6 @@ class Jitter(object):
         self.libs = libs
         out = {}
         for name, func in viewitems(user_globals):
-            name = force_bytes(name)
             out[name] = func
         self.user_globals = out
 
diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py
index b70872df..65d96001 100644
--- a/miasm/jitter/loader/elf.py
+++ b/miasm/jitter/loader/elf.py
@@ -9,6 +9,7 @@ import miasm.loader.elf as elf_csts
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
+from miasm.core.utils import force_str
 from miasm.core.interval import interval
 
 import logging
@@ -26,6 +27,7 @@ def get_import_address_elf(e):
         if not hasattr(sh, 'rel'):
             continue
         for k, v in viewitems(sh.rel):
+            k = force_str(k)
             import2addr[('xxx', k)].add(v.offset)
     return import2addr
 
diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py
index c779f508..09319664 100644
--- a/miasm/jitter/loader/pe.py
+++ b/miasm/jitter/loader/pe.py
@@ -12,6 +12,7 @@ from miasm.loader import *
 
 from miasm.jitter.csts import *
 from miasm.jitter.loader.utils import canon_libname_libfunc, libimp
+from miasm.core.utils import force_str
 
 log = logging.getLogger('loader_pe')
 hnd = logging.StreamHandler()
@@ -29,7 +30,27 @@ def get_pe_dependencies(pe_obj):
     out = set()
     for dependency in pe_obj.DirImport.impdesc:
         libname = dependency.dlldescname.name.lower()
+        # transform bytes to chr
+        if isinstance(libname, bytes):
+            libname_str = ''
+            for c in libname:
+                libname_str += chr(c)
+            libname = libname_str
         out.add(libname)
+
+    # If binary has redirected export, add dependencies
+    if pe_obj.DirExport.expdesc != None:
+        addrs = get_export_name_addr_list(pe_obj)
+        for imp_ord_or_name, ad in addrs:
+            # if export is a redirection, search redirected dll
+            # and get function real addr
+            ret = is_redirected_export(pe_obj, ad)
+            if ret is False:
+                continue
+            dllname, func_info = ret
+            dllname = dllname + '.dll'
+            out.add(dllname)
+
     return out
 
 
@@ -40,10 +61,11 @@ def get_import_address_pe(e):
     for s in e.DirImport.impdesc:
         # fthunk = e.rva2virt(s.firstthunk)
         # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s))
-        libname = s.dlldescname.name.lower()
+        libname = force_str(s.dlldescname.name.lower())
+
         for ii, imp in enumerate(s.impbynames):
             if isinstance(imp, pe.ImportByName):
-                funcname = imp.name
+                funcname = force_str(imp.name)
             else:
                 funcname = imp
             # l = "    %2d %-16s" % (ii, repr(funcname))
@@ -59,6 +81,7 @@ def preload_pe(vm, e, runtime_lib, patch_vm_imp=True):
     # log.debug('imported funcs: %s' % fa)
     for (libname, libfunc), ads in viewitems(fa):
         for ad in ads:
+            libname = force_str(libname)
             ad_base_lib = runtime_lib.lib_get_add_base(libname)
             ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad)
 
@@ -88,11 +111,12 @@ def is_redirected_export(pe_obj, addr):
     addr_end = pe_obj.virt.find(b'\x00', addr)
     data = pe_obj.virt.get(addr, addr_end)
 
-    dllname, func_info = data.split(b'.', 1)
+    data = force_str(data)
+    dllname, func_info = data.split('.', 1)
     dllname = dllname.lower()
 
     # Test if function is forwarded using ordinal
-    if func_info.startswith(b'#'):
+    if func_info.startswith('#'):
         func_info = int(func_info[1:])
     return dllname, func_info
 
@@ -102,7 +126,7 @@ def get_export_name_addr_list(e):
     # add func name
     for i, n in enumerate(e.DirExport.f_names):
         addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal]
-        f_name = n.name.name
+        f_name = force_str(n.name.name)
         # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva))))
         out.append((f_name, e.rva2virt(addr.rva)))
 
@@ -268,8 +292,7 @@ def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs):
     """
     out = {}
     for fname in libs_name:
-        if not isinstance(fname, bytes):
-            fname = fname.encode('utf8')
+        assert isinstance(fname, str)
         out[fname] = vm_load_pe_lib(vm, fname, libs, lib_path_base, **kargs)
     return out
 
@@ -371,6 +394,27 @@ class libimp_pe(libimp):
         # dependency -> redirector
         self.created_redirected_imports = {}
 
+
+    def add_function(self, dllname, imp_ord_or_name, addr):
+        assert isinstance(dllname, str)
+        assert isinstance(imp_ord_or_name, (int, str))
+        libad = self.name2off[dllname]
+        c_name = canon_libname_libfunc(
+            dllname, imp_ord_or_name
+        )
+        update_entry = True
+        if addr in self.fad2info:
+            known_libad, known_imp_ord_or_name = self.fad2info[addr]
+            if isinstance(imp_ord_or_name, int):
+                update_entry = False
+        self.cname2addr[c_name] = addr
+        log.debug("Add func %s %s", hex(addr), c_name)
+        if update_entry:
+            log.debug("Real Add func %s %s", hex(addr), c_name)
+            self.fad2cname[addr] = c_name
+            self.fad2info[addr] = libad, imp_ord_or_name
+
+
     def add_export_lib(self, e, name):
         if name in self.created_redirected_imports:
             log.error("%r has previously been created due to redirect\
@@ -397,7 +441,7 @@ class libimp_pe(libimp):
             self.libbase_ad += 0x1000
 
             ads = get_export_name_addr_list(e)
-            todo = ads
+            todo = list(ads)
             # done = []
             while todo:
                 # for imp_ord_or_name, ad in ads:
@@ -408,15 +452,19 @@ class libimp_pe(libimp):
                 ret = is_redirected_export(e, ad)
                 if ret:
                     exp_dname, exp_fname = ret
-                    exp_dname = exp_dname + b'.dll'
+                    exp_dname = exp_dname + '.dll'
                     exp_dname = exp_dname.lower()
                     # if dll auto refes in redirection
                     if exp_dname == name:
                         libad_tmp = self.name2off[exp_dname]
-                        if not exp_fname in self.lib_imp2ad[libad_tmp]:
-                            # schedule func
-                            todo = [(imp_ord_or_name, ad)] + todo
-                            continue
+                        if isinstance(exp_fname, str):
+                            exp_fname = bytes(ord(c) for c in exp_fname)
+                        found = None
+                        for tmp_func, tmp_addr in ads:
+                            if tmp_func == exp_fname:
+                                found = tmp_addr
+                        assert found is not None
+                        ad = found
                     else:
                         # import redirected lib from non loaded dll
                         if not exp_dname in self.name2off:
@@ -428,8 +476,8 @@ class libimp_pe(libimp):
                         # Ensure function entry is created
                         _ = self.lib_get_add_func(new_lib_base, exp_fname)
 
-                    libad_tmp = self.name2off[exp_dname]
-                    ad = self.lib_imp2ad[libad_tmp][exp_fname]
+                        libad_tmp = self.name2off[exp_dname]
+                        ad = self.lib_imp2ad[libad_tmp][exp_fname]
 
                 self.lib_imp2ad[libad][imp_ord_or_name] = ad
                 name_inv = dict(
@@ -543,17 +591,59 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib,
         todo += [(name, os.path.join(lib_path_base, name), weight - 1)
                  for name in new_dependencies]
 
-    ordered_modules = sorted(viewitems(weight2name))
-    for _, modules in ordered_modules:
-        for name in modules:
-            pe_obj = name2module[name]
-            if pe_obj is None:
-                continue
-            # Fix imports
-            if pe_obj.DirExport:
-                runtime_lib.add_export_lib(pe_obj, name)
+    known_export_addresses = {}
+    to_resolve = {}
+    for name, pe_obj in name2module.items():
+        print(name)
+        if pe_obj is None:
+            continue
+        if pe_obj.DirExport.expdesc == None:
+            continue
+        addrs = get_export_name_addr_list(pe_obj)
+        for imp_ord_or_name, ad in addrs:
+            # if export is a redirection, search redirected dll
+            # and get function real addr
+            ret = is_redirected_export(pe_obj, ad)
+            if ret is False:
+                known_export_addresses[(name, imp_ord_or_name)] = ad
+            else:
+                dllname, func_info = ret
+                dllname = dllname + '.dll'
+                to_resolve[(name, imp_ord_or_name)] = (dllname, func_info)
+
+    modified = True
+    while modified:
+        modified = False
+        out = {}
+        for target, dependency in to_resolve.items():
+            dllname, funcname = dependency
+            if dependency in known_export_addresses:
+                known_export_addresses[target] = known_export_addresses[dependency]
+                modified = True
+            else:
+                log.error("Cannot resolve redirection %r %r", dllname, dependency)
+                raise RuntimeError('Cannot resolve redirection')
+        to_resolve = out
 
-    for pe_obj in viewvalues(name2module):
+    for dllname, pe_obj in name2module.items():
+        if pe_obj is None:
+            continue
+        ad = pe_obj.NThdr.ImageBase
+        libad = ad
+        runtime_lib.name2off[dllname] = ad
+        runtime_lib.libbase2lastad[ad] = ad + 0x1
+        runtime_lib.lib_imp2ad[ad] = {}
+        runtime_lib.lib_imp2dstad[ad] = {}
+        runtime_lib.libbase_ad += 0x1000
+
+    for (dllname, imp_ord_or_name), addr in known_export_addresses.items():
+        runtime_lib.add_function(dllname, imp_ord_or_name, addr)
+        libad = runtime_lib.name2off[dllname]
+        runtime_lib.lib_imp2ad[libad][imp_ord_or_name] = addr
+
+    assert not to_resolve
+
+    for dllname, pe_obj in name2module.items():
         if pe_obj is None:
             continue
         preload_pe(vm, pe_obj, runtime_lib, patch_vm_imp=True)
@@ -561,9 +651,10 @@ def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib,
     return name2module
 
 # machine -> arch
-PE_machine = {0x14c: "x86_32",
-              0x8664: "x86_64",
-              }
+PE_machine = {
+    0x14c: "x86_32",
+    0x8664: "x86_64",
+}
 
 
 def guess_arch(pe):
diff --git a/miasm/jitter/loader/utils.py b/miasm/jitter/loader/utils.py
index 375424e6..d03adc8a 100644
--- a/miasm/jitter/loader/utils.py
+++ b/miasm/jitter/loader/utils.py
@@ -2,24 +2,23 @@ from builtins import int as int_types
 import logging
 
 from future.utils import viewitems, viewvalues
-
-from miasm.core.utils import force_bytes
+from past.builtins import basestring
 
 log = logging.getLogger('loader_common')
 hnd = logging.StreamHandler()
 hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
 log.addHandler(hnd)
-log.setLevel(logging.INFO)
+log.setLevel(logging.DEBUG)
 
 
 def canon_libname_libfunc(libname, libfunc):
-    libname = force_bytes(libname)
-    dn = libname.split(b'.')[0]
+    assert isinstance(libname, basestring)
+    assert isinstance(libfunc, basestring) or isinstance(libfunc, int)
+    dn = libname.split('.')[0]
     if isinstance(libfunc, int_types):
         return str(dn), libfunc
     else:
-        libfunc = force_bytes(libfunc)
-        return b"%s_%s" % (dn, libfunc)
+        return "%s_%s" % (dn, libfunc)
 
 
 class libimp(object):
@@ -37,11 +36,11 @@ class libimp(object):
         self.fake_libs = set()
 
     def lib_get_add_base(self, name):
-        name = force_bytes(name)
-        name = name.lower().strip(b' ')
-        if not b"." in name:
+        assert isinstance(name, basestring)
+        name = name.lower().strip(' ')
+        if not "." in name:
             log.debug('warning adding .dll to modulename')
-            name += b'.dll'
+            name += '.dll'
             log.debug(name)
 
         if name in self.name2off:
@@ -74,7 +73,7 @@ class libimp(object):
 
         if imp_ord_or_name in self.lib_imp2ad[libad]:
             return self.lib_imp2ad[libad][imp_ord_or_name]
-        # log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad))
+        log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad))
         ad = self.libbase2lastad[libad]
         self.libbase2lastad[libad] += 0x10  # arbitrary
         self.lib_imp2ad[libad][imp_ord_or_name] = ad
diff --git a/miasm/os_dep/common.py b/miasm/os_dep/common.py
index 0b4d7e11..4a92ef2a 100644
--- a/miasm/os_dep/common.py
+++ b/miasm/os_dep/common.py
@@ -2,25 +2,27 @@ import os
 
 from future.utils import viewitems
 
-from miasm.core.utils import force_bytes
+from miasm.core.utils import force_bytes, force_str
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 from miasm.core.utils import get_caller_name
 from miasm.core.utils import pck64, upck64
 
 BASE_SB_PATH = "file_sb"
+WIN_CODEPAGE = "cp1252"
 
-
-def get_str_ansi(jitter, ad_str, max_char=None):
+def get_win_str_a(jitter, ad_str, max_char=None):
     l = 0
     tmp = ad_str
     while ((max_char is None or l < max_char) and
            jitter.vm.get_mem(tmp, 1) != b"\x00"):
         tmp += 1
         l += 1
-    return jitter.vm.get_mem(ad_str, l)
+    data = jitter.vm.get_mem(ad_str, l)
+    ret = data.decode(WIN_CODEPAGE)
+    return ret
 
 
-def get_str_unic(jitter, ad_str, max_char=None):
+def get_win_str_w(jitter, ad_str, max_char=None):
     l = 0
     tmp = ad_str
     while ((max_char is None or l < max_char) and
@@ -31,18 +33,23 @@ def get_str_unic(jitter, ad_str, max_char=None):
     s = s.decode("utf-16le")
     return s
 
+def encode_win_str_a(value):
+    value = value.encode(WIN_CODEPAGE) + b"\x00"
+    return value
+
+def encode_win_str_w(value):
+    value = value.encode("utf-16le") + b'\x00' * 2
+    return value
+
 
-def set_str_ansi(value):
-    value = force_bytes(value)
-    return value + b"\x00"
+def set_win_str_a(jitter, addr, value):
+    value = encode_win_str_a(value)
+    jitter.vm.set_mem(addr, value)
 
 
-def set_str_unic(value):
-    try:
-        value = value.decode()
-    except AttributeError:
-        pass
-    return value.encode("utf-16le") + b'\x00' * 2
+def set_win_str_w(jitter, addr, value):
+    value = encode_win_str_w(value)
+    jitter.vm.set_mem(addr, value)
 
 
 class heap(object):
diff --git a/miasm/os_dep/linux/syscall.py b/miasm/os_dep/linux/syscall.py
index 7fede9f1..01b1687c 100644
--- a/miasm/os_dep/linux/syscall.py
+++ b/miasm/os_dep/linux/syscall.py
@@ -154,7 +154,7 @@ def sys_arml_newuname(jitter, linux_env):
 def sys_generic_access(jitter, linux_env):
     # Parse arguments
     pathname, mode = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(pathname)
+    rpathname = jitter.get_c_str(pathname)
     rmode = mode
     if mode == 1:
         rmode = "F_OK"
@@ -173,7 +173,7 @@ def sys_generic_access(jitter, linux_env):
 def sys_x86_64_openat(jitter, linux_env):
     # Parse arguments
     dfd, filename, flags, mode = jitter.syscall_args_systemv(4)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_openat(%x, %r, %x, %x)", dfd, rpathname, flags, mode)
 
     # Stub
@@ -184,7 +184,7 @@ def sys_x86_64_openat(jitter, linux_env):
 def sys_x86_64_newstat(jitter, linux_env):
     # Parse arguments
     filename, statbuf = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newstat(%r, %x)", rpathname, statbuf)
 
     # Stub
@@ -201,7 +201,7 @@ def sys_x86_64_newstat(jitter, linux_env):
 def sys_arml_stat64(jitter, linux_env):
     # Parse arguments
     filename, statbuf = jitter.syscall_args_systemv(2)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newstat(%r, %x)", rpathname, statbuf)
 
     # Stub
@@ -229,7 +229,7 @@ def sys_x86_64_writev(jitter, linux_env):
         # };
         iovec = jitter.vm.get_mem(vec + iovec_num * 8 * 2, 8*2)
         iov_base, iov_len = struct.unpack("QQ", iovec)
-        fdesc.write(jitter.get_str_ansi(iov_base)[:iov_len])
+        fdesc.write(jitter.get_c_str(iov_base)[:iov_len])
 
     jitter.syscall_ret_systemv(vlen)
 
@@ -248,7 +248,7 @@ def sys_arml_writev(jitter, linux_env):
         # };
         iovec = jitter.vm.get_mem(vec + iovec_num * 4 * 2, 4*2)
         iov_base, iov_len = struct.unpack("II", iovec)
-        fdesc.write(jitter.get_str_ansi(iov_base)[:iov_len])
+        fdesc.write(jitter.get_c_str(iov_base)[:iov_len])
 
     jitter.syscall_ret_systemv(vlen)
 
@@ -433,7 +433,7 @@ def sys_x86_64_statfs(jitter, linux_env):
     # Parse arguments
     pathname = jitter.cpu.RDI
     buf = jitter.cpu.RSI
-    rpathname = jitter.get_str_ansi(pathname)
+    rpathname = jitter.get_c_str(pathname)
     log.debug("sys_statfs(%r, %x)", rpathname, buf)
 
     # Stub
@@ -486,7 +486,7 @@ def sys_arml_ioctl(jitter, linux_env):
 def sys_generic_open(jitter, linux_env):
     # Parse arguments
     filename, flags, mode = jitter.syscall_args_systemv(3)
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_open(%r, %x, %x)", rpathname, flags, mode)
     # Stub
     # 'mode' is ignored
@@ -569,7 +569,7 @@ def sys_x86_64_newlstat(jitter, linux_env):
     # Parse arguments
     filename = jitter.cpu.RDI
     statbuf = jitter.cpu.RSI
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newlstat(%s, %x)", rpathname, statbuf)
 
     # Stub
@@ -587,7 +587,7 @@ def sys_arml_lstat64(jitter, linux_env):
     # Parse arguments
     filename = jitter.cpu.R0
     statbuf = jitter.cpu.R1
-    rpathname = jitter.get_str_ansi(filename)
+    rpathname = jitter.get_c_str(filename)
     log.debug("sys_newlstat(%s, %x)", rpathname, statbuf)
 
     # Stub
@@ -607,8 +607,8 @@ def sys_x86_64_lgetxattr(jitter, linux_env):
     name = jitter.cpu.RSI
     value = jitter.cpu.RDX
     size = jitter.cpu.R10
-    rpathname = jitter.get_str_ansi(pathname)
-    rname = jitter.get_str_ansi(name)
+    rpathname = jitter.get_c_str(pathname)
+    rname = jitter.get_c_str(name)
     log.debug("sys_lgetxattr(%r, %r, %x, %x)", rpathname, rname, value, size)
 
     # Stub
@@ -622,8 +622,8 @@ def sys_x86_64_getxattr(jitter, linux_env):
     name = jitter.cpu.RSI
     value = jitter.cpu.RDX
     size = jitter.cpu.R10
-    rpathname = jitter.get_str_ansi(pathname)
-    rname = jitter.get_str_ansi(name)
+    rpathname = jitter.get_c_str(pathname)
+    rname = jitter.get_c_str(name)
     log.debug("sys_getxattr(%r, %r, %x, %x)", rpathname, rname, value, size)
 
     # Stub
@@ -646,7 +646,7 @@ def sys_x86_64_connect(jitter, linux_env):
     fd = jitter.cpu.RDI
     uservaddr = jitter.cpu.RSI
     addrlen = jitter.cpu.RDX
-    raddr = jitter.get_str_ansi(uservaddr + 2)
+    raddr = jitter.get_c_str(uservaddr + 2)
     log.debug("sys_connect(%x, %r, %x)", fd, raddr, addrlen)
 
     # Stub
@@ -698,7 +698,7 @@ def sys_x86_64_readlink(jitter, linux_env):
     path = jitter.cpu.RDI
     buf = jitter.cpu.RSI
     bufsize = jitter.cpu.RDX
-    rpath = jitter.get_str_ansi(path)
+    rpath = jitter.get_c_str(path)
     log.debug("sys_readlink(%r, %x, %x)", rpath, buf, bufsize)
 
     # Stub
diff --git a/miasm/os_dep/linux_stdlib.py b/miasm/os_dep/linux_stdlib.py
index 3fa5b02e..348ef9b4 100644
--- a/miasm/os_dep/linux_stdlib.py
+++ b/miasm/os_dep/linux_stdlib.py
@@ -143,7 +143,7 @@ def xxx_puts(jitter):
 
 
 def get_fmt_args(jitter, fmt, cur_arg):
-    return _get_fmt_args(fmt, cur_arg, jitter.get_str_ansi, jitter.get_arg_n_systemv)
+    return _get_fmt_args(fmt, cur_arg, jitter.get_c_str, jitter.get_arg_n_systemv)
 
 
 def xxx_snprintf(jitter):
@@ -153,7 +153,7 @@ def xxx_snprintf(jitter):
     output = get_fmt_args(jitter, fmt, cur_arg)
     output = output[:size - 1]
     ret = len(output)
-    jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
+    jitter.set_c_str(args.string, output)
     return jitter.func_ret_systemv(ret_addr, ret)
 
 
@@ -162,7 +162,7 @@ def xxx_sprintf(jitter):
     cur_arg, fmt = 2, args.fmt
     output = get_fmt_args(jitter, fmt, cur_arg)
     ret = len(output)
-    jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
+    jitter.set_c_str(args.string, output)
     return jitter.func_ret_systemv(ret_addr, ret)
 
 
@@ -177,14 +177,14 @@ def xxx_printf(jitter):
 
 def xxx_strcpy(jitter):
     ret_ad, args = jitter.func_args_systemv(["dst", "src"])
-    str_src = jitter.get_str_ansi(args.src) + '\x00'
-    jitter.vm.set_mem(args.dst, str_src.encode('utf8'))
+    str_src = jitter.get_c_str(args.src)
+    jitter.set_c_str(args.dst, str_src)
     jitter.func_ret_systemv(ret_ad, args.dst)
 
 
 def xxx_strlen(jitter):
     ret_ad, args = jitter.func_args_systemv(["src"])
-    str_src = jitter.get_str_ansi(args.src)
+    str_src = jitter.get_c_str(args.src)
     jitter.func_ret_systemv(ret_ad, len(str_src))
 
 
@@ -201,13 +201,13 @@ def xxx_free(jitter):
 
 def xxx_strcmp(jitter):
     ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_ansi(args.ptr_str1)
-    s2 = jitter.get_str_ansi(args.ptr_str2)
+    s1 = jitter.get_c_str(args.ptr_str1)
+    s2 = jitter.get_c_str(args.ptr_str2)
     jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2))
 
 
 def xxx_strncmp(jitter):
     ret_ad, args = jitter.func_args_systemv(["ptr_str1", "ptr_str2", "size"])
-    s1 = jitter.get_str_ansi(args.ptr_str1, args.size)
-    s2 = jitter.get_str_ansi(args.ptr_str2, args.size)
+    s1 = jitter.get_c_str(args.ptr_str1, args.size)
+    s2 = jitter.get_c_str(args.ptr_str2, args.size)
     jitter.func_ret_systemv(ret_ad, cmp_elts(s1, s2))
diff --git a/miasm/os_dep/win_api_x86_32.py b/miasm/os_dep/win_api_x86_32.py
index cdf6a48f..051cedb5 100644
--- a/miasm/os_dep/win_api_x86_32.py
+++ b/miasm/os_dep/win_api_x86_32.py
@@ -28,7 +28,7 @@ from io import StringIO
 import time
 import datetime
 
-from future.utils import PY3, viewitems
+from future.utils import PY3, viewitems, viewvalues
 
 try:
     from Crypto.Hash import MD5, SHA
@@ -38,8 +38,10 @@ except ImportError:
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE, PAGE_EXEC
 from miasm.core.utils import pck16, pck32, hexdump, whoami, int_to_byte
 from miasm.os_dep.common import heap, windows_to_sbpath
-from miasm.os_dep.common import set_str_unic, set_str_ansi
+from miasm.os_dep.common import set_win_str_w, set_win_str_a
 from miasm.os_dep.common import get_fmt_args as _get_fmt_args
+from miasm.os_dep.common import get_win_str_a, get_win_str_w
+from miasm.os_dep.common import encode_win_str_a, encode_win_str_w
 from miasm.os_dep.win_api_x86_32_seh import tib_address
 
 log = logging.getLogger("win_api_x86_32")
@@ -144,8 +146,8 @@ class c_winobjs(object):
         self.dw_pid_dummy2 = 0x333
         self.dw_pid_cur = 0x444
         self.module_fname_nux = None
-        self.module_name = b"test.exe"
-        self.module_path = b"c:\\mydir\\" + self.module_name
+        self.module_name = "test.exe"
+        self.module_path = "c:\\mydir\\" + self.module_name
         self.hcurmodule = None
         self.module_filesize = None
         self.getversion = 0x0A280105
@@ -169,7 +171,7 @@ class c_winobjs(object):
             0x80000001: b"hkey_current_user",
             0x80000002: b"hkey_local_machine"
         }
-        self.cur_dir = b"c:\\tmp"
+        self.cur_dir = "c:\\tmp"
 
         self.nt_mdl = {}
         self.nt_mdl_ad = None
@@ -203,7 +205,7 @@ process_list = [
         winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "dummy1.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
     [
         0x40,  # DWORD     dwSize;
@@ -215,7 +217,7 @@ process_list = [
         4,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "explorer.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
 
     [
@@ -228,7 +230,7 @@ process_list = [
         winobjs.dw_pid_explorer,  # DWORD     th32ParentProcessID;
         0xbeef,  # LONG      pcPriClassBase;
         0x0,  # DWORD     dwFlags;
-        b"dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
+        "dummy2.exe"  # TCHAR     szExeFile[MAX_PATH];
     ],
 
     [
@@ -337,7 +339,7 @@ def kernel32_Process32First(jitter):
 
     pentry = struct.pack(
         'IIIIIIIII', *process_list[0][:-1]
-    ) + process_list[0][-1]
+    ) + (process_list[0][-1] + '\x00').encode('utf8')
     jitter.vm.set_mem(args.ad_pentry, pentry)
     winobjs.toolhelpsnapshot_info[args.s_handle] = 0
 
@@ -354,7 +356,7 @@ def kernel32_Process32Next(jitter):
         ret = 1
         n = winobjs.toolhelpsnapshot_info[args.s_handle]
         pentry = struct.pack(
-            'IIIIIIIII', *process_list[n][:-1]) + process_list[n][-1]
+            'IIIIIIIII', *process_list[n][:-1]) + (process_list[n][-1]+ '\x00').encode('utf8')
         jitter.vm.set_mem(args.ad_pentry, pentry)
     jitter.func_ret_stdcall(ret_ad, ret)
 
@@ -370,7 +372,7 @@ def kernel32_GetVersion(jitter):
     jitter.func_ret_stdcall(ret_ad, winobjs.getversion)
 
 
-def kernel32_GetVersionEx(jitter, str_size, set_str):
+def kernel32_GetVersionEx(jitter, str_size, encode_str):
     ret_ad, args = jitter.func_args_stdcall(["ptr_struct"])
 
     size = jitter.vm.get_u32(args.ptr_struct)
@@ -382,7 +384,7 @@ def kernel32_GetVersionEx(jitter, str_size, set_str):
             0x2,              # min vers
             0xa28,            # build nbr
             0x2,              # platform id
-            set_str("Service pack 4"),
+            encode_str("Service pack 4"),
             3,                # wServicePackMajor
             0,                # wServicePackMinor
             0x100,            # wSuiteMask
@@ -398,9 +400,9 @@ def kernel32_GetVersionEx(jitter, str_size, set_str):
 
 
 kernel32_GetVersionExA = lambda jitter: kernel32_GetVersionEx(jitter, 128,
-                                                              set_str_ansi)
+                                                              encode_win_str_a)
 kernel32_GetVersionExW = lambda jitter: kernel32_GetVersionEx(jitter, 256,
-                                                              set_str_unic)
+                                                              encode_win_str_w)
 
 
 def kernel32_GetPriorityClass(jitter):
@@ -426,10 +428,10 @@ def user32_GetForegroundWindow(jitter):
 def user32_FindWindowA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pclassname", "pwindowname"])
     if args.pclassname:
-        classname = jitter.get_str_ansi(args.pclassname)
+        classname = get_win_str_a(jitter, args.pclassname)
         log.info("FindWindowA classname %s", classname)
     if args.pwindowname:
-        windowname = jitter.get_str_ansi(args.pwindowname)
+        windowname = get_win_str_a(jitter, args.pwindowname)
         log.info("FindWindowA windowname %s", windowname)
     jitter.func_ret_stdcall(ret_ad, 0)
 
@@ -455,11 +457,11 @@ def advapi32_CryptAcquireContext(jitter, funcname, get_str):
 
 
 def advapi32_CryptAcquireContextA(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_CryptAcquireContextW(jitter):
-    advapi32_CryptAcquireContext(jitter, whoami(), jitter.get_str_unic)
+    advapi32_CryptAcquireContext(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_CryptCreateHash(jitter):
@@ -666,11 +668,11 @@ def kernel32_CreateFile(jitter, funcname, get_str):
 
 
 def kernel32_CreateFileA(jitter):
-    kernel32_CreateFile(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateFileW(jitter):
-    kernel32_CreateFile(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateFile(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_ReadFile(jitter):
@@ -755,9 +757,13 @@ def kernel32_VirtualProtect(jitter):
         old = jitter.vm.get_mem_access(args.lpvoid)
         jitter.vm.set_u32(args.lpfloldprotect, ACCESS_DICT_INV[old])
 
-    for addr in jitter.vm.get_all_memory():
+    print("XXX VIRTUALP")
+    log.warn("set page %x %x", args.lpvoid, args.dwsize)
+    for addr, data in jitter.vm.get_all_memory().items():
+        size = data["size"]
         # Multi-page
-        if args.lpvoid <= addr < args.lpvoid + args.dwsize:
+        if addr <= args.lpvoid < addr + size:
+            log.warn("set page %x %x", addr, ACCESS_DICT[flnewprotect])
             jitter.vm.set_mem_access(addr, ACCESS_DICT[flnewprotect])
 
     jitter.func_ret_stdcall(ret_ad, 1)
@@ -841,11 +847,11 @@ def kernel32_GetModuleFileName(jitter, funcname, set_str):
 
 
 def kernel32_GetModuleFileNameA(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetModuleFileNameW(jitter):
-    kernel32_GetModuleFileName(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetModuleFileName(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_CreateMutex(jitter, funcname, get_str):
@@ -875,11 +881,11 @@ def kernel32_CreateMutex(jitter, funcname, get_str):
 
 
 def kernel32_CreateMutexA(jitter):
-    kernel32_CreateMutex(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateMutexW(jitter):
-    kernel32_CreateMutex(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateMutex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shell32_SHGetSpecialFolderLocation(jitter):
@@ -900,11 +906,11 @@ def kernel32_SHGetPathFromIDList(jitter, funcname, set_str):
 
 
 def shell32_SHGetPathFromIDListW(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), jitter.set_str_unic)
+    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def shell32_SHGetPathFromIDListA(jitter):
-    kernel32_SHGetPathFromIDList(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_SHGetPathFromIDList(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetLastError(jitter):
@@ -935,11 +941,11 @@ def kernel32_LoadLibrary(jitter, get_str):
 
 
 def kernel32_LoadLibraryA(jitter):
-    kernel32_LoadLibrary(jitter, jitter.get_str_ansi)
+    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryW(jitter):
-    kernel32_LoadLibrary(jitter, jitter.get_str_unic)
+    kernel32_LoadLibrary(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryEx(jitter, get_str):
@@ -954,18 +960,18 @@ def kernel32_LoadLibraryEx(jitter, get_str):
 
 
 def kernel32_LoadLibraryExA(jitter):
-    kernel32_LoadLibraryEx(jitter, jitter.get_str_ansi)
+    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_a(jitter, addr, max_char))
 
 
 def kernel32_LoadLibraryExW(jitter):
-    kernel32_LoadLibraryEx(jitter, jitter.get_str_unic)
+    kernel32_LoadLibraryEx(jitter, lambda addr, max_char=None:get_win_str_w(jitter, addr, max_char))
 
 
 def kernel32_GetProcAddress(jitter):
     ret_ad, args = jitter.func_args_stdcall(["libbase", "fname"])
     fname = args.fname
     if fname >= 0x10000:
-        fname = jitter.get_str_ansi(fname, 0x100)
+        fname = jitter.get_c_str(fname, 0x100)
         if not fname:
             fname = None
     if fname is not None:
@@ -995,11 +1001,11 @@ def kernel32_GetModuleHandle(jitter, funcname, get_str):
 
 
 def kernel32_GetModuleHandleA(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetModuleHandleW(jitter):
-    kernel32_GetModuleHandle(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetModuleHandle(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_VirtualLock(jitter):
@@ -1049,29 +1055,28 @@ def kernel32_IsWow64Process(jitter):
 def kernel32_GetCommandLine(jitter, set_str):
     ret_ad, _ = jitter.func_args_stdcall(0)
     alloc_addr = winobjs.heap.alloc(jitter, 0x1000)
-    s = set_str('"%s"' % winobjs.module_path)
-    jitter.vm.set_mem(alloc_addr, s)
+    set_str(alloc_addr, '"%s"' % winobjs.module_path)
     jitter.func_ret_stdcall(ret_ad, alloc_addr)
 
 
 def kernel32_GetCommandLineA(jitter):
-    kernel32_GetCommandLine(jitter, set_str_ansi)
+    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetCommandLineW(jitter):
-    kernel32_GetCommandLine(jitter, set_str_unic)
+    kernel32_GetCommandLine(jitter, lambda addr, value: set_win_str_w(jitter, addr, value))
 
 
 def shell32_CommandLineToArgvW(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pcmd", "pnumargs"])
-    cmd = jitter.get_str_unic(args.pcmd)
+    cmd = get_win_str_w(jitter, args.pcmd)
     log.info("CommandLineToArgv %r", cmd)
     tks = cmd.split(' ')
     addr = winobjs.heap.alloc(jitter, len(cmd) * 2 + 4 * len(tks))
     addr_ret = winobjs.heap.alloc(jitter, 4 * (len(tks) + 1))
     o = 0
     for i, t in enumerate(tks):
-        jitter.set_str_unic(addr + o, t)
+        jitter.set_win_str_w(addr + o, t)
         jitter.vm.set_u32(addr_ret + 4 * i, addr + o)
         o += len(t)*2 + 2
 
@@ -1118,7 +1123,7 @@ def cryptdll_MD5Final(jitter):
 def ntdll_RtlInitAnsiString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ad_ctx", "ad_str"])
 
-    s = jitter.get_str_ansi(args.ad_str)
+    s = get_win_str_a(jitter, args.ad_str)
     l = len(s)
     jitter.vm.set_mem(args.ad_ctx,
                       pck16(l) + pck16(l + 1) + pck32(args.ad_str))
@@ -1286,7 +1291,7 @@ def ntoskrnl_RtlGetVersion(jitter):
                     0x2,  # min vers
                     0x666,  # build nbr
                     0x2,   # platform id
-                    ) + jitter.set_str_unic("Service pack 4")
+                    ) + jitter.set_win_str_w("Service pack 4")
 
     jitter.vm.set_mem(args.ptr_version, s)
     jitter.func_ret_stdcall(ret_ad, 0)
@@ -1378,7 +1383,7 @@ def ntoskrnl_RtlQueryRegistryValues(jitter):
                                              "querytable",
                                              "context",
                                              "environ"])
-    # path = get_str_unic(jitter, args.path)
+    # path = get_win_str_w(jitter, args.path)
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -1403,51 +1408,51 @@ def my_lstrcmp(jitter, funcname, get_str):
 
 def msvcrt_wcscmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s')" % (whoami(), s1, s2))
     jitter.func_ret_cdecl(ret_ad, cmp(s1, s2))
 
 def msvcrt__wcsicmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s')" % (whoami(), s1, s2))
     jitter.func_ret_cdecl(ret_ad, cmp(s1.lower(), s2.lower()))
 
 def msvcrt__wcsnicmp(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2", "count"])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.debug("%s('%s','%s',%d)" % (whoami(), s1, s2, args.count))
     jitter.func_ret_cdecl(ret_ad, cmp(s1.lower()[:args.count], s2.lower()[:args.count]))
 
 def msvcrt_wcsncpy(jitter):
     ret_ad, args = jitter.func_args_cdecl(["dst", "src", "n"])
-    src = jitter.get_str_unic(args.src)
+    src = get_win_str_w(jitter, args.src)
     dst = src[:args.n]
     dst += "\x00\x00" * (args.n-len(dst)+1)
     jitter.vm.set_mem(args.dst, dst)
     jitter.func_ret_cdecl(ret_ad, args.dst)
 
 def kernel32_lstrcmpA(jitter):
-    my_lstrcmp(jitter, whoami(), jitter.get_str_ansi)
+    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_lstrcmpiA(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_ansi(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
 
 
 def kernel32_lstrcmpW(jitter):
-    my_lstrcmp(jitter, whoami(), jitter.get_str_unic)
+    my_lstrcmp(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_lstrcmpiW(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_unic(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_w(jitter, x).lower())
 
 
 def kernel32_lstrcmpi(jitter):
-    my_lstrcmp(jitter, whoami(), lambda x: jitter.get_str_ansi(x).lower())
+    my_lstrcmp(jitter, whoami(), lambda x: get_win_str_a(jitter, x).lower())
 
 
 def my_strcpy(jitter, funcname, get_str, set_str):
@@ -1459,20 +1464,20 @@ def my_strcpy(jitter, funcname, get_str, set_str):
 
 
 def kernel32_lstrcpyW(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_lstrcpyA(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_lstrcpy(jitter):
-    my_strcpy(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_strcpy(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 def msvcrt__mbscpy(jitter):
     ret_ad, args = jitter.func_args_cdecl(["ptr_str1", "ptr_str2"])
-    s2 = jitter.get_str_unic(args.ptr_str2)
-    jitter.set_str_unic(args.ptr_str1, s2)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
+    jitter.set_win_str_w(args.ptr_str1, s2)
     jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
 
 def msvcrt_wcscpy(jitter):
@@ -1482,11 +1487,11 @@ def msvcrt_wcscpy(jitter):
 def kernel32_lstrcpyn(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
                                              "mlen"])
-    s2 = jitter.get_str_ansi(args.ptr_str2)
+    s2 = get_win_str_a(jitter, args.ptr_str2)
     if len(s2) >= args.mlen:
         s2 = s2[:args.mlen - 1]
     log.info("Copy '%r'", s2)
-    jitter.set_str_ansi(args.ptr_str1, s2)
+    jitter.set_win_str_a(args.ptr_str1, s2)
     jitter.func_ret_stdcall(ret_ad, args.ptr_str1)
 
 
@@ -1499,15 +1504,15 @@ def my_strlen(jitter, funcname, get_str, mylen):
 
 
 def kernel32_lstrlenA(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_ansi, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
 
 
 def kernel32_lstrlenW(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_unic, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), len)
 
 
 def kernel32_lstrlen(jitter):
-    my_strlen(jitter, whoami(), jitter.get_str_ansi, len)
+    my_strlen(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), len)
 
 
 def my_lstrcat(jitter, funcname, get_str, set_str):
@@ -1519,11 +1524,11 @@ def my_lstrcat(jitter, funcname, get_str, set_str):
 
 
 def kernel32_lstrcatA(jitter):
-    my_lstrcat(jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_lstrcatW(jitter):
-    my_lstrcat(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_lstrcat(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_GetUserGeoID(jitter):
@@ -1573,11 +1578,11 @@ def my_GetVolumeInformation(jitter, funcname, get_str, set_str):
 
 def kernel32_GetVolumeInformationA(jitter):
     my_GetVolumeInformation(
-        jitter, whoami(), jitter.get_str_ansi, jitter.set_str_ansi)
+        jitter, whoami(), lambda addr:get_win_str_a(jitter, addr), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetVolumeInformationW(jitter):
-    my_GetVolumeInformation(jitter, whoami(), jitter.get_str_unic, jitter.set_str_unic)
+    my_GetVolumeInformation(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_MultiByteToWideChar(jitter):
@@ -1586,7 +1591,7 @@ def kernel32_MultiByteToWideChar(jitter):
                                              "cbmultibyte",
                                              "lpwidecharstr",
                                              "cchwidechar"])
-    src = jitter.get_str_ansi(args.lpmultibytestr) + '\x00'
+    src = get_win_str_a(jitter, args.lpmultibytestr) + '\x00'
     l = len(src)
 
     src = "\x00".join(list(src))
@@ -1611,15 +1616,15 @@ def my_GetEnvironmentVariable(jitter, funcname, get_str, set_str, mylen):
 
 def kernel32_GetEnvironmentVariableA(jitter):
     my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_ansi,
-                              jitter.set_str_ansi,
+                              lambda addr:get_win_str_a(jitter, addr),
+                              lambda addr,value: set_win_str_a(jitter, addr, value),
                               len)
 
 
 def kernel32_GetEnvironmentVariableW(jitter):
     my_GetEnvironmentVariable(jitter, whoami(),
-                              jitter.get_str_unic,
-                              jitter.set_str_ansi,
+                              lambda addr:get_win_str_w(jitter, addr),
+                              lambda addr,value: set_win_str_w(jitter, addr, value),
                               len)
 
 
@@ -1633,11 +1638,11 @@ def my_GetSystemDirectory(jitter, funcname, set_str):
 
 
 def kernel32_GetSystemDirectoryA(jitter):
-    my_GetSystemDirectory(jitter, whoami(), jitter.set_str_ansi)
+    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetSystemDirectoryW(jitter):
-    my_GetSystemDirectory(jitter, whoami(), jitter.set_str_unic)
+    my_GetSystemDirectory(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def my_CreateDirectory(jitter, funcname, get_str):
@@ -1647,11 +1652,11 @@ def my_CreateDirectory(jitter, funcname, get_str):
 
 
 def kernel32_CreateDirectoryW(jitter):
-    my_CreateDirectory(jitter, whoami(), jitter.get_str_unic)
+    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_CreateDirectoryA(jitter):
-    my_CreateDirectory(jitter, whoami(), jitter.get_str_ansi)
+    my_CreateDirectory(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 
@@ -1669,11 +1674,11 @@ def my_CreateEvent(jitter, funcname, get_str):
 
 
 def kernel32_CreateEventA(jitter):
-    my_CreateEvent(jitter, whoami(), jitter.get_str_ansi)
+    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateEventW(jitter):
-    my_CreateEvent(jitter, whoami(), jitter.get_str_unic)
+    my_CreateEvent(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_WaitForSingleObject(jitter):
@@ -1704,7 +1709,7 @@ def kernel32_SetFileAttributesA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["lpfilename",
                                              "dwfileattributes"])
     if args.lpfilename:
-        # fname = get_str_ansi(jitter, args.lpfilename)
+        # fname = get_win_str_a(jitter, args.lpfilename)
         ret = 1
     else:
         ret = 0
@@ -1789,7 +1794,7 @@ def ntdll_ZwFreeVirtualMemory(jitter):
 
 def ntdll_RtlInitString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pstring", "source"])
-    s = jitter.get_str_ansi(args.source)
+    s = get_win_str_a(jitter, args.source)
     l = len(s) + 1
     o = struct.pack('HHI', l, l, args.source)
     jitter.vm.set_mem(args.pstring, o)
@@ -1800,7 +1805,7 @@ def ntdll_RtlAnsiStringToUnicodeString(jitter):
     ret_ad, args = jitter.func_args_stdcall(["dst", "src", "alloc_str"])
 
     l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    s = jitter.get_str_ansi(p_src)
+    s = get_win_str_a(jitter, p_src)
     s = ("\x00".join(s + "\x00"))
     l = len(s) + 1
     if args.alloc_str:
@@ -1822,7 +1827,7 @@ def ntdll_LdrLoadDll(jitter):
 
     l1, l2, p_src = struct.unpack('HHI',
                                   jitter.vm.get_mem(args.modname, 0x8))
-    s = jitter.get_str_unic(p_src)
+    s = get_win_str_w(jitter, p_src)
     libname = s.lower()
 
     ad = winobjs.runtime_dll.lib_get_add_base(libname)
@@ -1834,7 +1839,7 @@ def ntdll_LdrLoadDll(jitter):
 def ntdll_RtlFreeUnicodeString(jitter):
     ret_ad, args = jitter.func_args_stdcall(['src'])
     # l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.src, 0x8))
-    # s = get_str_unic(jitter, p_src)
+    # s = get_win_str_w(jitter, p_src)
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -1843,7 +1848,7 @@ def ntdll_LdrGetProcedureAddress(jitter):
                                              "opt", "p_ad"])
 
     l1, l2, p_src = struct.unpack('HHI', jitter.vm.get_mem(args.pfname, 0x8))
-    fname = jitter.get_str_ansi(p_src)
+    fname = get_win_str_a(jitter, p_src)
 
     ad = winobjs.runtime_dll.lib_get_add_func(args.libbase, fname)
     jitter.add_breakpoint(ad, jitter.handle_lib)
@@ -1866,7 +1871,7 @@ def msvcrt_memset(jitter):
 
 def msvcrt_strrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = jitter.get_str_ansi(args.pstr)
+    s = get_win_str_a(jitter, args.pstr)
     c = int_to_byte(args.c)
     ret = args.pstr + s.rfind(c)
     log.info("strrchr(%x '%s','%s') = %x" % (args.pstr,s,c,ret))
@@ -1874,7 +1879,7 @@ def msvcrt_strrchr(jitter):
 
 def msvcrt_wcsrchr(jitter):
     ret_ad, args = jitter.func_args_cdecl(['pstr','c'])
-    s = jitter.get_str_unic(args.pstr)
+    s = get_win_str_w(jitter, args.pstr)
     c = int_to_byte(args.c)
     ret = args.pstr + (s.rfind(c)*2)
     log.info("wcsrchr(%x '%s',%s) = %x" % (args.pstr,s,c,ret))
@@ -1907,7 +1912,7 @@ def msvcrt_memcmp(jitter):
 
 def shlwapi_PathFindExtensionA(jitter):
     ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = jitter.get_str_ansi(args.path_ad)
+    path = get_win_str_a(jitter, args.path_ad)
     i = path.rfind('.')
     if i == -1:
         i = args.path_ad + len(path)
@@ -1918,19 +1923,19 @@ def shlwapi_PathFindExtensionA(jitter):
 
 def shlwapi_PathRemoveFileSpecW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['path_ad'])
-    path = jitter.get_str_unic(args.path_ad)
+    path = get_win_str_w(jitter, args.path_ad)
     i = path.rfind('\\')
     if i == -1:
         i = 0
     jitter.vm.set_mem(args.path_ad + i * 2, "\x00\x00")
-    path = jitter.get_str_unic(args.path_ad)
+    path = get_win_str_w(jitter, args.path_ad)
     jitter.func_ret_stdcall(ret_ad, 1)
 
 
 def shlwapi_PathIsPrefixW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['ptr_prefix', 'ptr_path'])
-    prefix = jitter.get_str_unic(args.ptr_prefix)
-    path = jitter.get_str_unic(args.ptr_path)
+    prefix = get_win_str_w(jitter, args.ptr_prefix)
+    path = get_win_str_w(jitter, args.ptr_path)
 
     if path.startswith(prefix):
         ret = 1
@@ -1941,7 +1946,7 @@ def shlwapi_PathIsPrefixW(jitter):
 
 def shlwapi_PathIsDirectoryW(jitter):
     ret_ad, args = jitter.func_args_stdcall(['ptr_path'])
-    fname = jitter.get_str_unic(args.ptr_path)
+    fname = get_win_str_w(jitter, args.ptr_path)
 
     sb_fname = windows_to_sbpath(fname)
 
@@ -1977,24 +1982,24 @@ def shlwapi_PathGetDriveNumber(jitter, funcname, get_str):
 
 
 def shlwapi_PathGetDriveNumberA(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_PathGetDriveNumberW(jitter):
-    shlwapi_PathGetDriveNumber(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_PathGetDriveNumber(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shlwapi_PathIsFileSpecA(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_PathIsFileSpecW(jitter):
-    shlwapi_PathIsFileSpec(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_PathIsFileSpec(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def shlwapi_StrToIntA(jitter):
     ret_ad, args = jitter.func_args_stdcall(['i_str_ad'])
-    i_str = jitter.get_str_ansi(args.i_str_ad)
+    i_str = get_win_str_a(jitter, args.i_str_ad)
     try:
         i = int(i_str)
     except:
@@ -2020,11 +2025,11 @@ def shlwapi_StrToInt64Ex(jitter, funcname, get_str):
 
 
 def shlwapi_StrToInt64ExA(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), jitter.get_str_ansi)
+    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def shlwapi_StrToInt64ExW(jitter):
-    shlwapi_StrToInt64Ex(jitter, whoami(), jitter.get_str_unic)
+    shlwapi_StrToInt64Ex(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def user32_IsCharAlpha(jitter, funcname, get_str):
@@ -2042,11 +2047,11 @@ def user32_IsCharAlpha(jitter, funcname, get_str):
 
 
 def user32_IsCharAlphaA(jitter):
-    user32_IsCharAlpha(jitter, whoami(), jitter.get_str_ansi)
+    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def user32_IsCharAlphaW(jitter):
-    user32_IsCharAlpha(jitter, whoami(), jitter.get_str_unic)
+    user32_IsCharAlpha(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def user32_IsCharAlphaNumericA(jitter):
@@ -2067,7 +2072,7 @@ def msvcrt_sprintf_str(jitter, get_str):
     return ret_ad, args, get_fmt_args(jitter, fmt, cur_arg, get_str)
 
 def msvcrt_sprintf(jitter):
-    ret_ad, args, output = msvcrt_sprintf_str(jitter, jitter.get_str_ansi)
+    ret_ad, args, output = msvcrt_sprintf_str(jitter, lambda addr:get_win_str_a(jitter, addr))
     ret = len(output)
     log.info("sprintf() = '%s'" % (output))
     jitter.vm.set_mem(args.string, (output + '\x00').encode('utf8'))
@@ -2076,18 +2081,18 @@ def msvcrt_sprintf(jitter):
 def msvcrt_swprintf(jitter):
     ret_ad, args = jitter.func_args_cdecl(['string', 'fmt'])
     cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, jitter.get_str_unic)
+    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_w(jitter, addr))
     ret = len(output)
-    log.info("swprintf('%s') = '%s'" % (jitter.get_str_unic(args.fmt), output))
+    log.info("swprintf('%s') = '%s'" % (get_win_str_w(jitter, args.fmt), output))
     jitter.vm.set_mem(args.string, output.encode("utf-16le") + b'\x00\x00')
     return jitter.func_ret_cdecl(ret_ad, ret)
 
 def msvcrt_fprintf(jitter):
     ret_addr, args = jitter.func_args_cdecl(['file', 'fmt'])
     cur_arg, fmt = 2, args.fmt
-    output = get_fmt_args(jitter, fmt, cur_arg, jitter.get_str_ansi)
+    output = get_fmt_args(jitter, fmt, cur_arg, lambda addr:get_win_str_a(jitter, addr))
     ret = len(output)
-    log.info("fprintf(%x, '%s') = '%s'" % (args.file, jitter.get_str_ansi(args.fmt), output))
+    log.info("fprintf(%x, '%s') = '%s'" % (args.file, lambda addr:get_win_str_a(jitter, addr)(args.fmt), output))
 
     fd = jitter.vm.get_u32(args.file + 0x10)
     if not fd in winobjs.handle_pool:
@@ -2099,8 +2104,8 @@ def msvcrt_fprintf(jitter):
 def shlwapi_StrCmpNIA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["ptr_str1", "ptr_str2",
                                              "nchar"])
-    s1 = jitter.get_str_ansi(args.ptr_str1).lower()
-    s2 = jitter.get_str_ansi(args.ptr_str2).lower()
+    s1 = get_win_str_a(jitter, args.ptr_str1).lower()
+    s2 = get_win_str_a(jitter, args.ptr_str2).lower()
     s1 = s1[:args.nchar]
     s2 = s2[:args.nchar]
     jitter.func_ret_stdcall(ret_ad, cmp(s1, s2))
@@ -2109,7 +2114,7 @@ def shlwapi_StrCmpNIA(jitter):
 def advapi32_RegCreateKeyW(jitter):
     ret_ad, args = jitter.func_args_stdcall(["hkey", "subkey",
                                              "phandle"])
-    s_subkey = jitter.get_str_unic(args.subkey).lower() if args.subkey else ""
+    s_subkey = get_win_str_w(jitter, args.subkey).lower() if args.subkey else ""
 
     ret_hkey = 0
     ret = 2
@@ -2130,7 +2135,7 @@ def kernel32_GetCurrentDirectoryA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["size","buf"])
     dir_ = winobjs.cur_dir
     log.debug("GetCurrentDirectory() = '%s'" % dir_)
-    jitter.vm.set_mem(args.buf, dir_[:args.size-1] + b"\x00")
+    set_win_str_a(jitter, args.buf, dir_[:args.size-1])
     ret = len(dir_)
     if args.size <= len(dir_):
         ret += 1
@@ -2159,11 +2164,11 @@ def advapi32_RegOpenKeyEx(jitter, funcname, get_str):
 
 
 def advapi32_RegOpenKeyExA(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegOpenKeyExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_RegSetValue(jitter, funcname, get_str):
@@ -2193,19 +2198,19 @@ def advapi32_RegCloseKey(jitter):
     jitter.func_ret_stdcall(ret_ad, 0)
 
 def advapi32_RegSetValueExA(jitter):
-    advapi32_RegSetValueEx(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegSetValueEx(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegSetValueExW(jitter):
-    advapi32_RegOpenKeyEx(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegOpenKeyEx(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def advapi32_RegSetValueA(jitter):
-    advapi32_RegSetValue(jitter, whoami(), jitter.get_str_ansi)
+    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def advapi32_RegSetValueW(jitter):
-    advapi32_RegSetValue(jitter, whoami(), jitter.get_str_unic)
+    advapi32_RegSetValue(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_GetThreadLocale(jitter):
@@ -2220,15 +2225,15 @@ def kernel32_SetCurrentDirectory(jitter, get_str):
     jitter.func_ret_stdcall(ret_ad, 1)
 
 def kernel32_SetCurrentDirectoryW(jitter):
-    return kernel32_SetCurrentDirectory(jitter, jitter.get_str_unic)
+    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_w(jitter, addr))
 
 def kernel32_SetCurrentDirectoryA(jitter):
-    return kernel32_SetCurrentDirectory(jitter, jitter.get_str_ansi)
+    return kernel32_SetCurrentDirectory(jitter, lambda addr:get_win_str_a(jitter, addr))
 
 def msvcrt_wcscat(jitter):
     ret_ad, args = jitter.func_args_cdecl(['ptr_str1', 'ptr_str2'])
-    s1 = jitter.get_str_unic(args.ptr_str1)
-    s2 = jitter.get_str_unic(args.ptr_str2)
+    s1 = get_win_str_w(jitter, args.ptr_str1)
+    s2 = get_win_str_w(jitter, args.ptr_str2)
     log.info("strcat('%s','%s')" % (s1,s2))
     jitter.vm.set_mem(args.ptr_str1, (s1 + s2).encode("utf-16le") + "\x00\x00")
     jitter.func_ret_cdecl(ret_ad, args.ptr_str1)
@@ -2253,11 +2258,11 @@ def kernel32_GetLocaleInfo(jitter, funcname, set_str):
 
 
 def kernel32_GetLocaleInfoA(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetLocaleInfoW(jitter):
-    kernel32_GetLocaleInfo(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetLocaleInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_TlsAlloc(jitter):
@@ -2306,11 +2311,11 @@ def kernel32_GetStartupInfo(jitter, funcname, set_str):
 
 
 def kernel32_GetStartupInfoA(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), jitter.set_str_ansi)
+    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetStartupInfoW(jitter):
-    kernel32_GetStartupInfo(jitter, whoami(), jitter.set_str_unic)
+    kernel32_GetStartupInfo(jitter, whoami(), lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 def kernel32_GetCurrentThreadId(jitter):
@@ -2336,7 +2341,7 @@ def user32_GetSystemMetrics(jitter):
 
 def wsock32_WSAStartup(jitter):
     ret_ad, args = jitter.func_args_stdcall(["version", "pwsadata"])
-    jitter.vm.set_mem(args.pwsadata, "\x01\x01\x02\x02WinSock 2.0\x00")
+    jitter.vm.set_mem(args.pwsadata, b"\x01\x01\x02\x02WinSock 2.0\x00")
     jitter.func_ret_stdcall(ret_ad, 0)
 
 
@@ -2430,11 +2435,11 @@ def kernel32_CreateFileMapping(jitter, funcname, get_str):
 
 
 def kernel32_CreateFileMappingA(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_CreateFileMappingW(jitter):
-    kernel32_CreateFileMapping(jitter, whoami(), jitter.get_str_unic)
+    kernel32_CreateFileMapping(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_MapViewOfFile(jitter):
@@ -2501,11 +2506,11 @@ def kernel32_GetDriveType(jitter, funcname, get_str):
 
 
 def kernel32_GetDriveTypeA(jitter):
-    kernel32_GetDriveType(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetDriveTypeW(jitter):
-    kernel32_GetDriveType(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetDriveType(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_GetDiskFreeSpace(jitter, funcname, get_str):
@@ -2522,11 +2527,11 @@ def kernel32_GetDiskFreeSpace(jitter, funcname, get_str):
 
 
 def kernel32_GetDiskFreeSpaceA(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), jitter.get_str_ansi)
+    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_a(jitter, addr))
 
 
 def kernel32_GetDiskFreeSpaceW(jitter):
-    kernel32_GetDiskFreeSpace(jitter, whoami(), jitter.get_str_unic)
+    kernel32_GetDiskFreeSpace(jitter, whoami(), lambda addr:get_win_str_w(jitter, addr))
 
 
 def kernel32_VirtualQuery(jitter):
@@ -2574,7 +2579,7 @@ def msvcrt_srand(jitter):
 
 def msvcrt_wcslen(jitter):
     ret_ad, args = jitter.func_args_cdecl(["pwstr"])
-    s = jitter.get_str_unic(args.pwstr)
+    s = get_win_str_w(jitter, args.pwstr)
     jitter.func_ret_cdecl(ret_ad, len(s))
 
 def kernel32_SetFilePointer(jitter):
@@ -2777,8 +2782,8 @@ def user32_MessageBoxA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["hwnd", "lptext",
                                              "lpcaption", "utype"])
 
-    text = jitter.get_str_ansi(args.lptext)
-    caption = jitter.get_str_ansi(args.lpcaption)
+    text = get_win_str_a(jitter, args.lptext)
+    caption = get_win_str_a(jitter, args.lpcaption)
 
     log.info('Caption: %r Text: %r', caption, text)
 
@@ -2794,11 +2799,11 @@ def kernel32_myGetTempPath(jitter, set_str):
 
 
 def kernel32_GetTempPathA(jitter):
-    kernel32_myGetTempPath(jitter, jitter.set_str_ansi)
+    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_a(jitter, addr, value))
 
 
 def kernel32_GetTempPathW(jitter):
-    kernel32_myGetTempPath(jitter, jitter.set_str_unic)
+    kernel32_myGetTempPath(jitter, lambda addr,value: set_win_str_w(jitter, addr, value))
 
 
 temp_num = 0
@@ -2809,8 +2814,8 @@ def kernel32_GetTempFileNameA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["path", "ext", "unique", "buf"])
 
     temp_num += 1
-    ext = jitter.get_str_ansi(args.ext) if args.ext else 'tmp'
-    path = jitter.get_str_ansi(args.path) if args.path else "xxx"
+    ext = get_win_str_a(jitter, args.ext) if args.ext else 'tmp'
+    path = get_win_str_a(jitter, args.path) if args.path else "xxx"
     fname = path + "\\" + "temp%.4d" % temp_num + "." + ext
     jitter.vm.set_mem(args.buf, fname)
 
@@ -2887,7 +2892,7 @@ class find_data_mngr(object):
 def kernel32_FindFirstFileA(jitter):
     ret_ad, args = jitter.func_args_stdcall(["pfilepattern", "pfindfiledata"])
 
-    filepattern = jitter.get_str_ansi(args.pfilepattern)
+    filepattern = get_win_str_a(jitter, args.pfilepattern)
     h = winobjs.find_data.findfirst(filepattern)
 
     fname = winobjs.find_data.findnext(h)
@@ -2951,7 +2956,7 @@ def msvcrt__ultow(jitter):
     if not args.radix in [10, 16, 20]:
         raise ValueError("Not tested")
     s = int2base(value, args.radix)
-    jitter.vm.set_mem(args.p, jitter.set_str_unic(s + "\x00"))
+    jitter.vm.set_mem(args.p, lambda addr,value: set_win_str_w(jitter, addr, value)(s + "\x00"))
     jitter.func_ret_cdecl(ret_ad, args.p)
 
 
@@ -2978,15 +2983,15 @@ def msvcrt_myfopen(jitter, get_str):
 
 
 def msvcrt__wfopen(jitter):
-    msvcrt_myfopen(jitter, jitter.get_str_unic)
+    msvcrt_myfopen(jitter, lambda addr:get_win_str_w(jitter, addr))
 
 
 def msvcrt_fopen(jitter):
-    msvcrt_myfopen(jitter, jitter.get_str_ansi)
+    msvcrt_myfopen(jitter, lambda addr:get_win_str_a(jitter, addr))
 
 
 def msvcrt_strlen(jitter):
     ret_ad, args = jitter.func_args_cdecl(["src"])
 
-    s = jitter.get_str_ansi(args.src)
+    s = get_win_str_a(jitter, args.src)
     jitter.func_ret_cdecl(ret_ad, len(s))
diff --git a/miasm/os_dep/win_api_x86_32_seh.py b/miasm/os_dep/win_api_x86_32_seh.py
index dadd0889..8e485285 100644
--- a/miasm/os_dep/win_api_x86_32_seh.py
+++ b/miasm/os_dep/win_api_x86_32_seh.py
@@ -81,7 +81,7 @@ return_from_exception = 0x6eadbeef
 
 name2module = []
 main_pe = None
-main_pe_name = b"c:\\xxx\\toto.exe"
+main_pe_name = "c:\\xxx\\toto.exe"
 
 MAX_SEH = 5
 
@@ -254,9 +254,9 @@ def create_modules_chain(jitter, name2module):
                         fname)
             continue
         addr = base_addr + i * 0x1000
-        bpath = fname.replace(b'/', b'\\')
+        bpath = fname.replace('/', '\\')
         bname_str = os.path.split(fname)[1].lower()
-        bname_unicode = bname_str.decode('utf8').encode("utf-16le")
+        bname_unicode = bname_str.encode("utf-16le")
         log.info("Add module %x %r", pe_obj.NThdr.ImageBase, bname_str)
 
         modules_info.add(bname_str, pe_obj, addr)
diff --git a/test/arch/x86/qemu/testqemu.py b/test/arch/x86/qemu/testqemu.py
index 594a826b..64312928 100644
--- a/test/arch/x86/qemu/testqemu.py
+++ b/test/arch/x86/qemu/testqemu.py
@@ -48,7 +48,7 @@ def xxx___printf_chk(jitter):
     ret_ad, args = jitter.func_args_systemv(["out", "format"])
     if args.out != 1:
         raise RuntimeError("Not implemented")
-    fmt = jitter.get_str_ansi(args.format)
+    fmt = jitter.get_c_str(args.format)
     # Manage llx
     fmt = fmt.replace("llx", "lx")
     fmt = fmt.replace("%016lx", "%016z")
@@ -60,7 +60,7 @@ def xxx___printf_chk(jitter):
     for x in fmt_a:
         a = jitter.vm.get_u32(esp + 8 + 4*i)
         if x == "s":
-            a = jitter.get_str_ansi(a)
+            a = jitter.get_c_str(a)
         elif x in ("x", 'X', "d"):
             pass
         elif x.lower() in ("f", "l"):
@@ -102,7 +102,7 @@ def xxx_puts(jitter):
     writes the string s and a trailing newline to stdout.
     '''
     ret_addr, args = jitter.func_args_systemv(['target'])
-    output = jitter.get_str_ansi(args.target)
+    output = jitter.get_c_str(args.target)
     # Check with expected result
     line = next(expected)
     if output != line.rstrip():
diff --git a/test/arch/x86/qemu/testqemu64.py b/test/arch/x86/qemu/testqemu64.py
index 636cb6a9..8d25ca68 100644
--- a/test/arch/x86/qemu/testqemu64.py
+++ b/test/arch/x86/qemu/testqemu64.py
@@ -48,7 +48,7 @@ def xxx___printf_chk(jitter):
     ret_ad, args = jitter.func_args_systemv(["out", "format"])
     if args.out != 1:
         raise RuntimeError("Not implemented")
-    fmt = jitter.get_str_ansi(args.format)
+    fmt = jitter.get_c_str(args.format)
     # Manage llx
     fmt = fmt.replace("llx", "lx")
     fmt = fmt.replace("%016lx", "%016z")
@@ -60,7 +60,7 @@ def xxx___printf_chk(jitter):
     for x in fmt_a:
         a = jitter.get_arg_n_systemv(2 + i)
         if x == "s":
-            a = jitter.get_str_ansi(a)
+            a = jitter.get_c_str(a)
         elif x in ("x", 'X', 'd', 'z', 'Z'):
             pass
         elif x.lower() in ("f","l"):
@@ -98,7 +98,7 @@ def xxx_puts(jitter):
     writes the string s and a trailing newline to stdout.
     '''
     ret_addr, args = jitter.func_args_systemv(['target'])
-    output = jitter.get_str_ansi(args.target)
+    output = jitter.get_c_str(args.target)
     # Check with expected result
     line = next(expected)
     if output != line.rstrip():
diff --git a/test/os_dep/linux/stdlib.py b/test/os_dep/linux/stdlib.py
index ef890625..a0432e65 100755
--- a/test/os_dep/linux/stdlib.py
+++ b/test/os_dep/linux/stdlib.py
@@ -33,7 +33,7 @@ class TestLinuxStdlib(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         stdlib.xxx_sprintf(jit)
-        ret = jit.get_str_ansi(buf)
+        ret = jit.get_c_str(buf)
         self.assertEqual(ret, "'coucou' 1111")
 
 
diff --git a/test/os_dep/win_api_x86_32.py b/test/os_dep/win_api_x86_32.py
index f759c6af..66a4e628 100755
--- a/test/os_dep/win_api_x86_32.py
+++ b/test/os_dep/win_api_x86_32.py
@@ -6,6 +6,7 @@ import unittest
 import logging
 from miasm.analysis.machine import Machine
 import miasm.os_dep.win_api_x86_32 as winapi
+from miasm.os_dep.win_api_x86_32 import get_win_str_a, get_win_str_w
 from miasm.core.utils import pck32
 from miasm.jitter.csts import PAGE_READ, PAGE_WRITE
 
@@ -42,7 +43,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         winapi.msvcrt_sprintf(jit)
-        ret = jit.get_str_ansi(buf)
+        ret = get_win_str_a(jit, buf)
         self.assertEqual(ret, "'coucou' 1111")
 
 
@@ -63,7 +64,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(buf)
         jit.push_uint32_t(0) # ret_ad
         winapi.msvcrt_swprintf(jit)
-        ret = jit.get_str_unic(buf)
+        ret = get_win_str_w(jit, buf)
         self.assertEqual(ret, u"'coucou' 1111")
 
 
@@ -94,7 +95,7 @@ class TestWinAPI(unittest.TestCase):
         jit.push_uint32_t(size)   # size
         jit.push_uint32_t(0)      # @return
         winapi.kernel32_GetCurrentDirectoryA(jit)
-        dir_ = jit.get_str_ansi(addr)
+        dir_ = get_win_str_a(jit, addr)
         size_ret = jit.cpu.EAX
         self.assertEqual(len(dir_), size_ret)
 
@@ -106,7 +107,7 @@ class TestWinAPI(unittest.TestCase):
         winapi.kernel32_GetCurrentDirectoryA(jit)
         size_ret = jit.cpu.EAX
         self.assertEqual(len(dir_)+1, size_ret)
-        dir_short = jit.get_str_ansi(addr)
+        dir_short = get_win_str_a(jit, addr)
         self.assertEqual(dir_short, dir_[:4])
 
     def test_MemoryManagementFunctions(self):