我的编程空间,编程开发者的网络收藏夹
学习永远不晚

LyScript实现Hook隐藏调试器的方法详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

LyScript实现Hook隐藏调试器的方法详解

LyScript 插件集成的内置API函数可灵活的实现绕过各类反调试保护机制,前段时间发布的那一篇文章并没有详细讲解各类反调试机制的绕过措施,本次将补充这方面的知识点,运用LyScript实现绕过大多数通用调试机制,实现隐藏调试器的目的。

我们以此实现Patches如下函数:

  • IsDebuggerPresent
  • ZwQueryInformationProcess
  • CheckRemoteDebuggerPresent
  • PEB.IsDebugged
  • PEB.ProcessHeap.Flag
  • PEB.NtGlobalFlag
  • PEB.Ldr 0xFEEEFEEE filling
  • GetTickCount
  • ZwQuerySystemInformation
  • FindWindowA
  • FindWindowW
  • FindWindowExA
  • FindWindowExW
  • EnumWindows

首先第一步我们需要自己封装实现一个反汇编转机器码的函数,其作用是当用户传入汇编列表时,自动将其转为机器码并输出为列表格式。

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ShellCode = GetOpCode(dbg, ["DB 0x64","mov eax,dword ptr ds:[18]","sub eax,eax","ret"])

    print(ShellCode)

    dbg.close()

输出效果如下:

Patch_PEB

PEB结构存在许多反调试变量,首先我们需要先将这些变量填充为空。

# ----------------------------------------------
# By: LyShark
# Email: me@lyshark.com
# Project: https://github.com/lyshark/LyScript
# ----------------------------------------------

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

def Patch_PEB(dbg):
    PEB = dbg.get_peb_address(dbg.get_process_id())
    if PEB == 0:
        return 0

    # 写出0 Patching PEB.IsDebugged
    dbg.write_memory_byte(PEB + 0x2,GetOpCode(dbg,["db 0"])[0])
    print("补丁地址: {}".format(hex(PEB+0x2)))

    # 写出0 Patching PEB.ProcessHeap.Flag
    temp = dbg.read_memory_dword(PEB + 0x18)
    temp += 0x10
    dbg.write_memory_dword(temp, GetOpCode(dbg,["db 0"])[0])
    print(("补丁地址: {}".format(hex(temp))))

    # 写出0 atching PEB.NtGlobalFlag
    dbg.write_memory_dword(PEB+0x68, 0)
    print(("补丁地址: {}".format(hex(PEB+0x68))))

    # 循环替换 Patch PEB_LDR_DATA 0xFEEEFEEE fill bytes about 3000 of them
    addr = dbg.read_memory_dword(PEB + 0x0c)

    while addr != 0:
        addr += 1

        try:
            b = dbg.read_memory_dword(addr)
            c = dbg.read_memory_dword(addr + 4)

            # 仅修补填充运行
            print(b)
            if (b == 0xFEEEFEEE) and (c == 0xFEEEFEEE):
                dbg.write_memory_dword(addr,0)
                dbg.write_memory_dword(addr + 4, 0)
                print("patch")
        except Exception:
            break

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    Patch_PEB(dbg)
    
    dbg.close()

Patch_IsDebuggerPresent

该函数用于检测自身是否处于调试状态,其C系列代码如下所示,绕过此种方式很简单,只需要在函数头部写出ret指令即可。

#include <Windows.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])
{
	BOOL ref = IsDebuggerPresent();
	printf("是否被调试: %d \n", ref);

	getchar();
	return 0;
}

注意:此Api检查PEB中的值,因此如果修补PEB,则无需修补Api,这段绕过代码如下。

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

def Patch_IsDebuggerPresent(dbg):
    # 得到模块句柄
    ispresent = dbg.get_module_from_function("kernel32.dll","IsDebuggerPresent")
    print(hex(ispresent))

    if(ispresent <= 0):
        print("无法得到模块基地址,请以管理员方式运行调试器.")
        return 0

    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg, ["DB 0x64", "mov eax,dword ptr ds:[18]", "sub eax,eax", "ret"])
    print(ShellCode)

    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(ispresent + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0
    return flag

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ref = Patch_IsDebuggerPresent(dbg)
    print("补丁状态: {}".format(ref))

    dbg.close()

当程序运行后会向IsDebuggerPresent函数写出返回,从而实现绕过调试的目的。

Patch_CheckRemoteDebuggerPresent

此Api调用ZwQueryInformationProcess因此通常不需要对两者进行修补。

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

def Patch_CheckRemoteDebuggerPresent(dbg):
    # 得到模块句柄
    ispresent = dbg.get_module_from_function("kernel32.dll","CheckRemoteDebuggerPresent")
    print(hex(ispresent))

    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg,
                          [
                              "mov edi,edi",
                              "push ebp",
                              "mov ebp,esp",
                              "mov eax,[ebp+0xc]",
                              "push 0",
                              "pop dword ptr ds:[eax]",
                              "xor eax,eax",
                              "pop ebp",
                              "ret 8"
                          ]
                          )

    print(ShellCode)

    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(ispresent + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0
    return flag

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ref = Patch_CheckRemoteDebuggerPresent(dbg)
    print("写出状态: {}".format(ref))

    dbg.close()

写出效果如下:

Patch_GetTickCount

GetTickCount返回(retrieve)从操作系统启动所经过(elapsed)的毫秒数,常用于定时计数,绕过方式只需初始化即可。

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

def Patch_GetTickCount(dbg):
    # 得到模块句柄
    ispresent = dbg.get_module_from_function("kernel32.dll","GetTickCount")
    print(hex(ispresent))

    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg,
                          [
                              "mov edx,0x7ffe0000",
                              "sub eax,eax",
                              "add eax,0xB0B1560D",
                              "ret"
                          ]
                          )

    print(ShellCode)

    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(ispresent + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0
    return flag

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ref = Patch_GetTickCount(dbg)
    print("写出状态: {}".format(ref))

    dbg.close()

写出效果如下:

Patch_ZwQueryInformationProcess

此函数打补丁需要跳转两次,原因是因为函数开头部分无法填充更多指令,需要我们自己来申请空间,并实现跳转。

# ----------------------------------------------
# By: LyShark
# Email: me@lyshark.com
# Project: https://github.com/lyshark/LyScript
# ----------------------------------------------

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

# 获取指定位置前index条指令的长度
def GetOpCodeSize(dbg,address,index):
    ref_size = 0

    dasm = dbg.get_disasm_code(address,index)
    for index in dasm:
        count = dbg.assemble_code_size(index.get("opcode"))
        ref_size += count
    return ref_size

def Patch_ZwQueryInformationProcess(dbg):
    # 得到模块句柄
    ispresent = dbg.get_module_from_function("ntdll.dll","ZwQueryInformationProcess")
    print(hex(ispresent))

    create_address = dbg.create_alloc(1024)
    print("分配空间: {}".format(hex(create_address)))


    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg,
                          [
                              "cmp dword [esp + 8],7",
                              "DB 0x74",
                              "DB 0x06",
                              f"push {hex(ispresent)}",
                              "ret",
                              "mov eax,dword [esp +0x0c]",
                              "push 0",
                              "pop dword [eax]",
                              "xor eax,eax",
                              "ret 14"
                          ]
                          )

    print(ShellCode)

    # 把shellcode写出到自己分配的堆中
    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(create_address + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0

    # 填充跳转位置
    jmp_shellcode = GetOpCode(dbg,
                              [
                                  f"push {hex(create_address)}",
                                  "ret"
                              ]
                              )
    for index in range(0,len(jmp_shellcode)):
        flag = dbg.write_memory_byte(ispresent + index,jmp_shellcode[index])
        if flag:
            flag = 1
        else:
            flag = 0

    return flag

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ref = Patch_ZwQueryInformationProcess(dbg)

    print("补丁状态: {}".format(ref))

    dbg.close()

这段代码运行后,首先会申请内存,然后将特定的一段机器码写出到此内存中。

内存写出以后,再将函数头部替换为跳转,这样一来当函数被调用,也就自动转向了。

Patch_FindWindow

FindWindow函数功能是取窗体句柄,有AW与Ex系列,使用同上方法替代即可。

# ----------------------------------------------
# By: LyShark
# Email: me@lyshark.com
# Project: https://github.com/lyshark/LyScript
# ----------------------------------------------

from LyScript32 import MyDebug
import ctypes

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

def Patch_FindWindow(dbg):
    # 得到模块句柄
    FindWindowA = dbg.get_module_from_function("user32.dll","FindWindowA")
    FindWindowW = dbg.get_module_from_function("user32.dll","FindWindowW")
    FindWindowExA = dbg.get_module_from_function("user32.dll","FindWindowExA")
    FindWindowExW = dbg.get_module_from_function("user32.dll","FindWindowExW")
    print("A = {} w = {} exA = {} exW = {}".format(hex(FindWindowA),hex(FindWindowW),hex(FindWindowExA),hex(FindWindowExW)))

    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg,
                          [
                              "xor eax,eax",
                              "ret 0x8",
                          ]
                          )

    ShellCodeEx = GetOpCode(dbg,
                            [
                                "xor eax,eax",
                                "ret 0x10",
                            ]
                            )
    # 写出
    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(FindWindowA + index,ShellCode[index])
        flag = dbg.write_memory_byte(FindWindowW + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0

    for index in range(0,len(ShellCodeEx)):
        flag = dbg.write_memory_byte(FindWindowExA + index,ShellCodeEx[index])
        flag = dbg.write_memory_byte(FindWindowExW + index,ShellCodeEx[index])
        if flag:
            flag = 1
        else:
            flag = 0

    return flag

if __name__ == "__main__":
    dbg = MyDebug()

    connect = dbg.connect()

    ref = Patch_FindWindow(dbg)
    print("补丁状态: {}".format(ref))

    dbg.close()

补丁应用会分别替换四个函数。

Patch_EnumWindows

枚举窗体的补丁与上方代码一致,此处就不再分析了。

如下案例,实现了在枚举窗体过程中实现弹窗,并不影响窗体的枚举。

from LyScript32 import MyDebug

# 传入汇编代码,得到对应机器码
def get_opcode_from_assemble(dbg_ptr,asm):
    byte_code = bytearray()

    addr = dbg_ptr.create_alloc(1024)
    if addr != 0:
        asm_size = dbg_ptr.assemble_code_size(asm)
        # print("汇编代码占用字节: {}".format(asm_size))

        write = dbg_ptr.assemble_write_memory(addr,asm)
        if write == True:
            for index in range(0,asm_size):
                read = dbg_ptr.read_memory_byte(addr + index)
                # print("{:02x} ".format(read),end="")
                byte_code.append(read)
        dbg_ptr.delete_alloc(addr)
        return byte_code
    else:
        return bytearray(0)

# 传入汇编机器码得到机器码列表
def GetOpCode(dbg, Code):
    ShellCode = []

    for index in Code:
        ref = get_opcode_from_assemble(dbg,index)
        for opcode in ref:
            ShellCode.append(opcode)

    return ShellCode

# 获取指定位置前index条指令的长度
def GetOpCodeSize(dbg,address,index):
    ref_size = 0

    dasm = dbg.get_disasm_code(address,index)
    for index in dasm:
        count = dbg.assemble_code_size(index.get("opcode"))
        ref_size += count
    return ref_size

def Patch_EnumWindows(dbg):
    # 得到模块句柄
    address = dbg.get_module_from_function("user32.dll","EnumWindows")
    print(hex(address))

    msg_box = dbg.get_module_from_function("user32.dll","MessageBoxA")
    print(hex(msg_box))

    create_address = dbg.create_alloc(1024)
    print("分配空间: {}".format(hex(create_address)))

    # 找call地址,找到后取出他的内存地址
    dasm_list = dbg.get_disasm_code(address,20)
    call_addr = 0
    call_next_addr = 0
    for index in range(0,len(dasm_list)):

        # 如果找到了call,取出call地址以及下一条地址
        if dasm_list[index].get("opcode").split(" ")[0] == "call":
            call_addr = dasm_list[index].get("addr")
            call_next_addr = dasm_list[index+1].get("addr")
            print("call = {} call_next = {}".format(hex(call_addr),hex(call_next_addr)))

    # 将反调试语句转为机器码
    ShellCode = GetOpCode(dbg,
                          [
                              "push 0",
                              "push 0",
                              "push 0",
                              "push 0",
                              f"call {hex(msg_box)}",
                              "mov eax,1",
                              "pop ebp",
                              "ret 10",

                              f"call {hex(call_addr)}",
                              "pop ebp",
                              "ret 8"
                          ]
                          )

    print(ShellCode)

    # 把shellcode写出到自己分配的堆中
    flag = 0
    for index in range(0,len(ShellCode)):
        flag = dbg.write_memory_byte(create_address + index,ShellCode[index])
        if flag:
            flag = 1
        else:
            flag = 0


    # 填充跳转位置
    jmp_shellcode = GetOpCode(dbg,
                              [
                                  f"push {hex(create_address)}",
                                  "ret"
                              ]
                              )
    for index in range(0,len(jmp_shellcode)):
        flag = dbg.write_memory_byte(call_addr + index,jmp_shellcode[index])
        if flag:
            flag = 1
        else:
            flag = 0

    return flag

if __name__ == "__main__":
    dbg = MyDebug()
    connect = dbg.connect()

    ref = Patch_EnumWindows(dbg)

    dbg.close()

输出效果如下:

以上就是LyScript实现Hook隐藏调试器的方法详解的详细内容,更多关于LyScript Hook隐藏调试器的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

LyScript实现Hook隐藏调试器的方法详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用android隐藏api实现亮度调节的方法

Android 1.5之后将调节亮度的api隐藏了,不过android的源码中依然有方法可以实现,如下:代码如下:IPowerManager power = IPowerManager.Stub.asInterface(ServiceMan
2022-06-06

Android编程实现隐藏状态栏及测试Activity是否活动的方法

本文实例讲述了Android编程实现隐藏状态栏及测试Activity是否活动的方法。分享给大家供大家参考,具体如下: 一、 隐藏状态栏 方法如下:在程序中加入//remove title 的那部分代码即可实现。package cn.edu.
2022-06-06

详解Linux下调试器GDB的基本使用方法

目录一、概述二、gdb调试2.1、设置断点2.1.1、断点commands高级功能2.2、运行2.3、显示栈帧2.4、显示变量2.5、显示寄存器2.6、单步执行2.7、继续执行2.8、监视点2.9、改变变量的值2.10、生成内核转储文件2.
2022-06-03

Python调用实现最小二乘法的方法详解

所谓线性最小二乘法,可以理解为是解方程的延续,区别在于,当未知量远小于方程数的时候,将得到一个无解的问题。本文主要和大家分享Python调用实现最小二乘法的方法,需要的可以参考一下
2023-05-17

Python实现调用jar或执行java代码的方法详解

这篇文章主要介绍了Python实现调用jar或执行java代码的方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-12-21

解析android中隐藏与显示软键盘及不自动弹出键盘的实现方法

1、//隐藏软键盘 ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(WidgetSearchActivity.t
2022-06-06

详解Android中通过Intent类实现组件间调用的方法

Intent是Android中用来调用其它组件的类,通过Intent,我们可以非常方便的调用Activity,Broadcast Receiver和Service。Intent intent = new Intent(Intent.ACTI
2022-06-06

Go语言实现定时器的方法详解

这篇文章主要为大家详细介绍了Go语言实现定时器的两种方法:一次性定时器(Timer)和周期性定时器(Ticker),感兴趣的小伙伴可以跟随小编一起学习一下
2022-12-20

Android实现定时器的五种方法实例详解

一、Timer Timer是Android直接启动定时器的类,TimerTask是一个子线程,方便处理一些比较复杂耗时的功能逻辑,经常与handler结合使用。 跟handler自身实现的定时器相比,Timer可以做一些复杂的处理,例如,需
2022-06-06

Java调用微信客服消息实现发货通知的方法详解

本文实例讲述了Java调用微信客服消息实现发货通知的方法。分享给大家供大家参考,具体如下:微信文档地址:https://mp.weixin.qq.com/wikit=resource/res_main&id=mp1421140547&tok
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录